[U-Boot] [PATCH 1/2] rpi: Change load addresses to make more room for the kernel

Tuomas Tynkkynen tuomas.tynkkynen at iki.fi
Mon Jun 19 11:08:03 UTC 2017


According to the comment in rpi.h, the current kernel load address is
picked such that the compressed kernel and the uncompressed kernel don't
overlap in memory to avoid unnecessary relocation of the compressed
image in the decompressor stub. However, as is evident from the
kernel boot log snipped below, a full-blown ARMv7 distro kernel
(v4.11.3) can use as much as 17063 kB uncompressed. That is larger
than the current 16M reservation which means that the relocation
indeed is happening.

[    0.000000] Virtual kernel memory layout:
                 .text : 0xc0208000 - 0xc0f00000   (13280 kB)
                 .init : 0xc1500000 - 0xc1700000   (2048 kB)
                 .data : 0xc1700000 - 0xc18b1978   (1735 kB)

Additionally, on AArch64 the kernel images are much larger than
on ARM. A full-blown 4.11.3 distro kernel takes 24M, which with the
current load addresses (reserving only 17M) stomps over the initrd,
breaking the boot of such large kernels.

Fix both of these problems by tweaking the load addresses as appropriate
depending on the CPU architecture. To make things simpler, pxefile_addr_r
is moved from low memory next to scriptaddr.

After this patch we end up with this memory map on ARM (assuming the
most conservative CPU-GPU memory split of 128M for the CPU):
0x00000100 - 0x00008000 (    31 kB): fdt_addr_r - decompressed_kernel_start
0x00008000 - 0x03000000 ( 49120 kB): decompressed_kernel - kernel_addr_r
0x03000000 - 0x04000000 ( 16384 kB): kernel_addr_r - scriptaddr
0x04000000 - 0x04100000 (  1024 kB): scriptaddr - pxefile_addr_r
0x04100000 - 0x04200000 (  1024 kB): pxefile_addr_r - ramdisk_addr_r
0x04200000 - 0x08000000 ( 63488 kB): ramdisk_addr_r - top_of_ram

And this for AArch64:
0x00000100 - 0x00080000 (   511 kB): fdt_addr_r - kernel_addr_r
0x00080000 - 0x04000000 ( 65024 kB): kernel_addr_r - scriptaddr
0x04000000 - 0x04100000 (  1024 kB): scriptaddr - pxefile_addr_r
0x04100000 - 0x04200000 (  1024 kB): pxefile_addr_r - ramdisk_addr_r
0x04200000 - 0x08000000 ( 63488 kB): ramdisk_addr_r - top_of_ram

Signed-off-by: Tuomas Tynkkynen <tuomas.tynkkynen at iki.fi>
---
This has been tested on:
 - RPi 1 booting the RPi Foundation downstream kernel
 - RPi 3 booting a distro multi_v7_defconfig in 32-bit mode
 - RPi 3 booting a AArch64 distro defconfig in 64-bit mode
---
 include/configs/rpi.h | 36 +++++++++++++++++++++++++-----------
 1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/include/configs/rpi.h b/include/configs/rpi.h
index d715eaad14..a2d82a9146 100644
--- a/include/configs/rpi.h
+++ b/include/configs/rpi.h
@@ -131,32 +131,46 @@
  *   U-Boot (and scripts it executes) typicaly ignore the DT loaded by the FW
  *   and loads its own DT from disk (triggered by boot.scr or extlinux.conf).
  *
- * pxefile_addr_r can be pretty much anywhere that doesn't conflict with
- *   something else. Put it low in memory to avoid conflicts.
+ * kernel_addr_r has different constraints on ARM and Aarch64.
+ *   For Aarch64, the kernel image is uncompressed and must be loaded at
+ *   text_offset bytes (specified in the header of the Image) into a
+ *   2MB boundary. As Linux uses a default text_offset of 0x80000, load
+ *   the kernel at 0x80000 so that the 'booti' command does not need
+ *   to perform any relocation of the Image in the typical case.
  *
- * kernel_addr_r must be within the first 128M of RAM in order for the
+ *   For 32-bit ARM, it must be within the first 128M of RAM in order for the
  *   kernel's CONFIG_AUTO_ZRELADDR option to work. Since the kernel will
  *   decompress itself to 0x8000 after the start of RAM, kernel_addr_r
  *   should not overlap that area, or the kernel will have to copy itself
  *   somewhere else before decompression. Similarly, the address of any other
  *   data passed to the kernel shouldn't overlap the start of RAM. Pushing
- *   this up to 16M allows for a sizable kernel to be decompressed below the
+ *   this up to 48M allows for a sizable kernel to be decompressed below the
  *   compressed load address.
  *
  * scriptaddr can be pretty much anywhere that doesn't conflict with something
- *   else. Choosing 32M allows for the compressed kernel to be up to 16M.
+ *   else. Choosing 64M allows for the compressed kernel to be up to 16M on
+ *   32-bit ARM and roughly 64M for the uncompressed kernel on Aarch64.
+ *
+ * pxefile_addr_r can be pretty much anywhere that doesn't conflict with
+ *   something else. Choosing 65M allows for any boot script to be up to 1M,
+ *   which is hopefully plenty.
  *
- * ramdisk_addr_r simply shouldn't overlap anything else. Choosing 33M allows
- *   for any boot script to be up to 1M, which is hopefully plenty.
+ * ramdisk_addr_r simply shouldn't overlap anything else. Choosing 66M allows
+ *   for any PXE configuration file to be up to 1M, which is hopefully plenty.
  */
+#ifdef CONFIG_ARM64
+# define KERNEL_ADDR_R "0x00080000"
+#else
+# define KERNEL_ADDR_R "0x03000000"
+#endif
 #define ENV_MEM_LAYOUT_SETTINGS \
 	"fdt_high=ffffffff\0" \
 	"initrd_high=ffffffff\0" \
 	"fdt_addr_r=0x00000100\0" \
-	"pxefile_addr_r=0x00100000\0" \
-	"kernel_addr_r=0x01000000\0" \
-	"scriptaddr=0x02000000\0" \
-	"ramdisk_addr_r=0x02100000\0" \
+	"kernel_addr_r=" KERNEL_ADDR_R "\0" \
+	"scriptaddr=0x04000000\0" \
+	"pxefile_addr_r=0x04100000\0" \
+	"ramdisk_addr_r=0x04200000\0" \
 
 #define BOOT_TARGET_DEVICES(func) \
 	func(MMC, mmc, 0) \
-- 
2.13.0



More information about the U-Boot mailing list