@@ -339,6 +339,67 @@ static void __init request_standard_resources(void)
339339 }
340340}
341341
342+ #ifdef CONFIG_BLK_DEV_INITRD
343+ /*
344+ * Relocate initrd if it is not completely within the linear mapping.
345+ * This would be the case if mem= cuts out all or part of it.
346+ */
347+ static void __init relocate_initrd (void )
348+ {
349+ phys_addr_t orig_start = __virt_to_phys (initrd_start );
350+ phys_addr_t orig_end = __virt_to_phys (initrd_end );
351+ phys_addr_t ram_end = memblock_end_of_DRAM ();
352+ phys_addr_t new_start ;
353+ unsigned long size , to_free = 0 ;
354+ void * dest ;
355+
356+ if (orig_end <= ram_end )
357+ return ;
358+
359+ /*
360+ * Any of the original initrd which overlaps the linear map should
361+ * be freed after relocating.
362+ */
363+ if (orig_start < ram_end )
364+ to_free = ram_end - orig_start ;
365+
366+ size = orig_end - orig_start ;
367+
368+ /* initrd needs to be relocated completely inside linear mapping */
369+ new_start = memblock_find_in_range (0 , PFN_PHYS (max_pfn ),
370+ size , PAGE_SIZE );
371+ if (!new_start )
372+ panic ("Cannot relocate initrd of size %ld\n" , size );
373+ memblock_reserve (new_start , size );
374+
375+ initrd_start = __phys_to_virt (new_start );
376+ initrd_end = initrd_start + size ;
377+
378+ pr_info ("Moving initrd from [%llx-%llx] to [%llx-%llx]\n" ,
379+ orig_start , orig_start + size - 1 ,
380+ new_start , new_start + size - 1 );
381+
382+ dest = (void * )initrd_start ;
383+
384+ if (to_free ) {
385+ memcpy (dest , (void * )__phys_to_virt (orig_start ), to_free );
386+ dest += to_free ;
387+ }
388+
389+ copy_from_early_mem (dest , orig_start + to_free , size - to_free );
390+
391+ if (to_free ) {
392+ pr_info ("Freeing original RAMDISK from [%llx-%llx]\n" ,
393+ orig_start , orig_start + to_free - 1 );
394+ memblock_free (orig_start , to_free );
395+ }
396+ }
397+ #else
398+ static inline void __init relocate_initrd (void )
399+ {
400+ }
401+ #endif
402+
342403u64 __cpu_logical_map [NR_CPUS ] = { [0 ... NR_CPUS - 1 ] = INVALID_HWID };
343404
344405void __init setup_arch (char * * cmdline_p )
@@ -372,6 +433,7 @@ void __init setup_arch(char **cmdline_p)
372433 acpi_boot_table_init ();
373434
374435 paging_init ();
436+ relocate_initrd ();
375437 request_standard_resources ();
376438
377439 early_ioremap_reset ();
0 commit comments