|
|
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 |
|