diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 5ddba727d4..a0e1110719 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -1000,20 +1000,6 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu, if (info->nb_cpus == 0) info->nb_cpus = 1; - /* - * We want to put the initrd far enough into RAM that when the - * kernel is uncompressed it will not clobber the initrd. However - * on boards without much RAM we must ensure that we still leave - * enough room for a decent sized initrd, and on boards with large - * amounts of RAM we must avoid the initrd being so far up in RAM - * that it is outside lowmem and inaccessible to the kernel. - * So for boards with less than 256MB of RAM we put the initrd - * halfway into RAM, and for boards with 256MB of RAM or more we put - * the initrd at 128MB. - */ - info->initrd_start = info->loader_start + - MIN(info->ram_size / 2, 128 * 1024 * 1024); - /* Assume that raw images are linux kernels, and ELF images are not. */ kernel_size = arm_load_elf(info, &elf_entry, &elf_low_addr, &elf_high_addr, elf_machine, as); @@ -1065,6 +1051,26 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu, } info->entry = entry; + + /* + * We want to put the initrd far enough into RAM that when the + * kernel is uncompressed it will not clobber the initrd. However + * on boards without much RAM we must ensure that we still leave + * enough room for a decent sized initrd, and on boards with large + * amounts of RAM we must avoid the initrd being so far up in RAM + * that it is outside lowmem and inaccessible to the kernel. + * So for boards with less than 256MB of RAM we put the initrd + * halfway into RAM, and for boards with 256MB of RAM or more we put + * the initrd at 128MB. + * We also refuse to put the initrd somewhere that will definitely + * overlay the kernel we just loaded, though for kernel formats which + * don't tell us their exact size (eg self-decompressing 32-bit kernels) + * we might still make a bad choice here. + */ + info->initrd_start = info->loader_start + + MAX(MIN(info->ram_size / 2, 128 * 1024 * 1024), kernel_size); + info->initrd_start = TARGET_PAGE_ALIGN(info->initrd_start); + if (is_linux) { uint32_t fixupcontext[FIXUP_MAX];