aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc_oldworld.c
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2011-06-15 23:27:19 +0200
committerAlexander Graf <agraf@suse.de>2011-06-17 02:58:27 +0200
commitb9e17a345382ebb91446fd6cf0bb8f0eb5ba5706 (patch)
tree718cacaede8d8b12b0f77c6e003cea0c893779b9 /hw/ppc_oldworld.c
parent826e7b827c5f83e88d5aa84c0bf0b3459f28ec35 (diff)
PPC: calculate kernel,initrd,cmdline locations dynamically
During testing, I was generating a vmlinux binary that easily occupied more than 20MB of RAM. Since the current -kernel code loads the initrd at a fixed address behind the kernel, we were overwriting kernel data when the kernel got too big. To finally get rid of the issue, let's calculate the initrd and cmdline addresses relative to the kernel size, so we can have kernels and initrds that are as big as they want to - as long as they fit in RAM. Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'hw/ppc_oldworld.c')
-rw-r--r--hw/ppc_oldworld.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 75a312742e..20cd8e1a8d 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -59,6 +59,11 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
}
+static target_phys_addr_t round_page(target_phys_addr_t addr)
+{
+ return (addr + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
+}
+
static void ppc_heathrow_init (ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename,
@@ -71,7 +76,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
qemu_irq *pic, **heathrow_irqs;
int linux_boot, i;
ram_addr_t ram_offset, bios_offset;
- uint32_t kernel_base, initrd_base;
+ uint32_t kernel_base, initrd_base, cmdline_base = 0;
int32_t kernel_size, initrd_size;
PCIBus *pci_bus;
MacIONVRAMState *nvr;
@@ -157,7 +162,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
}
/* load initrd */
if (initrd_filename) {
- initrd_base = INITRD_LOAD_ADDR;
+ initrd_base = round_page(kernel_base + kernel_size + KERNEL_GAP);
initrd_size = load_image_targphys(initrd_filename, initrd_base,
ram_size - initrd_base);
if (initrd_size < 0) {
@@ -165,9 +170,11 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
initrd_filename);
exit(1);
}
+ cmdline_base = round_page(initrd_base + initrd_size);
} else {
initrd_base = 0;
initrd_size = 0;
+ cmdline_base = round_page(kernel_base + kernel_size + KERNEL_GAP);
}
ppc_boot_device = 'm';
} else {
@@ -278,8 +285,8 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base);
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
if (kernel_cmdline) {
- fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
- pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base);
+ pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline);
} else {
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
}