Blame 0802-arm_boot-Change-initrd-load-address-to-halfway-throu.patch

771708
From d3a43fe4b870154032db4651824bc88e3cb81dc5 Mon Sep 17 00:00:00 2001
771708
From: Peter Maydell <peter.maydell@linaro.org>
771708
Date: Fri, 26 Oct 2012 16:29:38 +0100
771708
Subject: [PATCH] arm_boot: Change initrd load address to "halfway through
771708
 RAM"
771708
771708
To avoid continually having to bump the initrd load address
771708
to account for larger kernel images, put the initrd halfway
771708
through RAM. This allows large kernels on new boards with lots
771708
of RAM to work OK, without breaking existing usecases for
771708
boards with only 32MB of RAM.
771708
771708
Note that this change fixes in passing a bug where we were
771708
passing an overly large max_size to load_image_targphys()
771708
for the initrd, which meant that we wouldn't correctly refuse
771708
to load an enormous initrd that didn't actually fit into RAM.
771708
771708
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
771708
---
771708
 hw/arm-misc.h |  1 +
771708
 hw/arm_boot.c | 41 ++++++++++++++++++++++++++---------------
771708
 2 files changed, 27 insertions(+), 15 deletions(-)
771708
771708
diff --git a/hw/arm-misc.h b/hw/arm-misc.h
771708
index bdd8fec..0f7deb5 100644
771708
--- a/hw/arm-misc.h
771708
+++ b/hw/arm-misc.h
771708
@@ -56,6 +56,7 @@ struct arm_boot_info {
771708
                                      const struct arm_boot_info *info);
771708
     /* Used internally by arm_boot.c */
771708
     int is_linux;
771708
+    target_phys_addr_t initrd_start;
771708
     target_phys_addr_t initrd_size;
771708
     target_phys_addr_t entry;
771708
 };
771708
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
771708
index a6e9143..920c337 100644
771708
--- a/hw/arm_boot.c
771708
+++ b/hw/arm_boot.c
771708
@@ -18,7 +18,6 @@
771708
 
771708
 #define KERNEL_ARGS_ADDR 0x100
771708
 #define KERNEL_LOAD_ADDR 0x00010000
771708
-#define INITRD_LOAD_ADDR 0x00d00000
771708
 
771708
 /* The worlds second smallest bootloader.  Set r0-r2, then jump to kernel.  */
771708
 static uint32_t bootloader[] = {
771708
@@ -109,7 +108,7 @@ static void set_kernel_args(const struct arm_boot_info *info)
771708
         /* ATAG_INITRD2 */
771708
         WRITE_WORD(p, 4);
771708
         WRITE_WORD(p, 0x54420005);
771708
-        WRITE_WORD(p, info->loader_start + INITRD_LOAD_ADDR);
771708
+        WRITE_WORD(p, info->initrd_start);
771708
         WRITE_WORD(p, initrd_size);
771708
     }
771708
     if (info->kernel_cmdline && *info->kernel_cmdline) {
771708
@@ -185,10 +184,11 @@ static void set_kernel_args_old(const struct arm_boot_info *info)
771708
     /* pages_in_vram */
771708
     WRITE_WORD(p, 0);
771708
     /* initrd_start */
771708
-    if (initrd_size)
771708
-        WRITE_WORD(p, info->loader_start + INITRD_LOAD_ADDR);
771708
-    else
771708
+    if (initrd_size) {
771708
+        WRITE_WORD(p, info->initrd_start);
771708
+    } else {
771708
         WRITE_WORD(p, 0);
771708
+    }
771708
     /* initrd_size */
771708
     WRITE_WORD(p, initrd_size);
771708
     /* rd_start */
771708
@@ -281,14 +281,13 @@ static int load_dtb(target_phys_addr_t addr, const struct arm_boot_info *binfo)
771708
 
771708
     if (binfo->initrd_size) {
771708
         rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
771708
-                binfo->loader_start + INITRD_LOAD_ADDR);
771708
+                binfo->initrd_start);
771708
         if (rc < 0) {
771708
             fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
771708
         }
771708
 
771708
         rc = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
771708
-                    binfo->loader_start + INITRD_LOAD_ADDR +
771708
-                    binfo->initrd_size);
771708
+                    binfo->initrd_start + binfo->initrd_size);
771708
         if (rc < 0) {
771708
             fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
771708
         }
771708
@@ -375,6 +374,19 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
771708
     big_endian = 0;
771708
 #endif
771708
 
771708
+    /* We want to put the initrd far enough into RAM that when the
771708
+     * kernel is uncompressed it will not clobber the initrd. However
771708
+     * on boards without much RAM we must ensure that we still leave
771708
+     * enough room for a decent sized initrd, and on boards with large
771708
+     * amounts of RAM we must avoid the initrd being so far up in RAM
771708
+     * that it is outside lowmem and inaccessible to the kernel.
771708
+     * So for boards with less  than 256MB of RAM we put the initrd
771708
+     * halfway into RAM, and for boards with 256MB of RAM or more we put
771708
+     * the initrd at 128MB.
771708
+     */
771708
+    info->initrd_start = info->loader_start +
771708
+        MIN(info->ram_size / 2, 128 * 1024 * 1024);
771708
+
771708
     /* Assume that raw images are linux kernels, and ELF images are not.  */
771708
     kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
771708
                            NULL, NULL, big_endian, ELF_MACHINE, 1);
771708
@@ -398,10 +410,9 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
771708
     if (is_linux) {
771708
         if (info->initrd_filename) {
771708
             initrd_size = load_image_targphys(info->initrd_filename,
771708
-                                              info->loader_start
771708
-                                              + INITRD_LOAD_ADDR,
771708
-                                              info->ram_size
771708
-                                              - INITRD_LOAD_ADDR);
771708
+                                              info->initrd_start,
771708
+                                              info->ram_size -
771708
+                                              info->initrd_start);
771708
             if (initrd_size < 0) {
771708
                 fprintf(stderr, "qemu: could not load initrd '%s'\n",
771708
                         info->initrd_filename);
771708
@@ -419,9 +430,9 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
771708
          */
771708
         if (info->dtb_filename) {
771708
             /* Place the DTB after the initrd in memory */
771708
-            target_phys_addr_t dtb_start = TARGET_PAGE_ALIGN(info->loader_start
771708
-                                                             + INITRD_LOAD_ADDR
771708
-                                                             + initrd_size);
771708
+            target_phys_addr_t dtb_start = TARGET_PAGE_ALIGN(
771708
+                                                        info->initrd_start +
771708
+                                                        initrd_size);
771708
             if (load_dtb(dtb_start, info)) {
771708
                 exit(1);
771708
             }
771708
-- 
771708
1.7.12.1
771708