On Fri, 3 May 2019 at 18:13, Peter Maydell <peter.mayd...@linaro.org> wrote: > > We currently put the initrd at the smaller of: > * 128MB into RAM > * halfway into the RAM > (with the dtb following it). > > However for large kernels this might mean that the kernel > overlaps the initrd. For some kinds of kernel (self-decompressing > 32-bit kernels, and ELF images with a BSS section at the end) > we don't know the exact size, but even there we have a > minimum size. Put the initrd at least further into RAM than > that. For image formats that can give us an exact kernel size, this > will mean that we definitely avoid overlaying kernel and initrd. > > Signed-off-by: Peter Maydell <peter.mayd...@linaro.org> > --- > hw/arm/boot.c | 34 ++++++++++++++++++++-------------- > 1 file changed, 20 insertions(+), 14 deletions(-) > > diff --git a/hw/arm/boot.c b/hw/arm/boot.c > index a830655e1af..7c978fedde4 100644 > --- a/hw/arm/boot.c > +++ b/hw/arm/boot.c > @@ -998,20 +998,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); > @@ -1056,6 +1042,26 @@ static void arm_setup_direct_kernel_boot(ARMCPU *cpu, > exit(1); > } > 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); > +
I belatedly realized that we should probably check here whether this is off the end of the ram, as otherwise following code will get an underflow in "info->ram_size - info->initrd_start" which is unlikely to result in useful behaviour. thanks -- PMM