# HG changeset patch
# User Hollis Blanchard <hollisb@xxxxxxxxxx>
# Node ID 9b3b420ec064ba6933998f82f0e07e0c816bef35
# Parent af7c87d42bc6d85441a7ff0a03f8bbbc67195f8e
[XEN][POWERPC] memory clean up (phase 3)
The following changes are included:
Open Firmware:
- use all args for of_claim()
- handle broken claim methods as best we can
- describe where the Dom0 image is comming from
- stop copying the Dom0 image
Heaps:
- make sure we do not overwrite the oftree
- release as much memory as possible to xenheap
- release Dom0 image after we are done with it
- Lots of checks and simplifications
Signed-off-by: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx>
---
xen/arch/powerpc/boot_of.c | 127 +++++++++++++++++++++++----------------------
xen/arch/powerpc/setup.c | 105 ++++++++++++++++++++++++-------------
2 files changed, 135 insertions(+), 97 deletions(-)
diff -r af7c87d42bc6 -r 9b3b420ec064 xen/arch/powerpc/boot_of.c
--- a/xen/arch/powerpc/boot_of.c Thu Aug 17 07:10:57 2006 -0400
+++ b/xen/arch/powerpc/boot_of.c Tue Aug 29 13:20:31 2006 -0500
@@ -26,6 +26,7 @@
#include <xen/spinlock.h>
#include <xen/serial.h>
#include <xen/time.h>
+#include <xen/sched.h>
#include <asm/page.h>
#include <asm/io.h>
#include "exceptions.h"
@@ -322,17 +323,18 @@ static void __init of_test(const char *o
}
}
-static int __init of_claim(void * virt, u32 size)
+static int __init of_claim(u32 virt, u32 size, u32 align)
{
int rets[1] = { OF_FAILURE };
- of_call("claim", 3, 1, rets, virt, size, 0/*align*/);
+ of_call("claim", 3, 1, rets, virt, size, align);
if (rets[0] == OF_FAILURE) {
- DBG("%s 0x%p 0x%08x -> FAIL\n", __func__, virt, size);
- return OF_FAILURE;
- }
-
- DBG("%s 0x%p 0x%08x -> 0x%x\n", __func__, virt, size, rets[0]);
+ DBG("%s 0x%08x 0x%08x 0x%08x -> FAIL\n", __func__, virt, size, align);
+ return OF_FAILURE;
+ }
+
+ DBG("%s 0x%08x 0x%08x 0x%08x -> 0x%08x\n", __func__, virt, size, align,
+ rets[0]);
return rets[0];
}
@@ -683,32 +685,47 @@ static int boot_of_fixup_chosen(void *me
}
static ulong space_base;
-static ulong find_space(u32 size, ulong align, multiboot_info_t *mbi)
+static int broken_claim;
+
+/*
+ * The following function is necessary because we cannot depend on all
+ * FW to actually allocate us any space, so we look for it _hoping_
+ * that at least is will fail if we try to claim something that
+ * belongs to FW. This hope does not seem to be true on some version
+ * of PIBS.
+ */
+static ulong find_space(u32 size, u32 align, multiboot_info_t *mbi)
{
memory_map_t *map = (memory_map_t *)((ulong)mbi->mmap_addr);
ulong eomem = ((u64)map->length_high << 32) | (u64)map->length_low;
ulong base;
- of_printf("%s base=0x%016lx eomem=0x%016lx size=0x%08x align=0x%lx\n",
+ if (size == 0) return base;
+
+ if (align == 0)
+ of_panic("cannot call %s() with align of 0\n", __func__);
+
+ if (!broken_claim) {
+ /* just try and claim it to the FW chosen address */
+ base = of_claim(0, size, align);
+ if (base != OF_FAILURE)
+ return base;
+ of_printf("%s: Firmware does not allocate memory for you\n", __func__);
+ broken_claim = 1;
+ }
+
+ of_printf("%s base=0x%016lx eomem=0x%016lx size=0x%08x align=0x%x\n",
__func__, space_base, eomem, size, align);
base = ALIGN_UP(space_base, PAGE_SIZE);
- if ((base + size) >= 0x4000000) return 0;
- if (base + size > eomem) of_panic("not enough RAM\n");
-
- if (size == 0) return base;
- if (of_claim((void*)base, size) != OF_FAILURE) {
- space_base = base + size;
- return base;
- } else {
- for(base += 0x100000; (base+size) < 0x4000000; base += 0x100000) {
- of_printf("Trying 0x%016lx\n", base);
- if (of_claim((void*)base, size) != OF_FAILURE) {
- space_base = base + size;
- return base;
- }
- }
- return 0;
- }
+
+ while ((base + size) < rma_size(cpu_rma_order())) {
+ if (of_claim(base, size, 0) != OF_FAILURE) {
+ space_base = base + size;
+ return base;
+ }
+ base += (PAGE_SIZE > align) ? PAGE_SIZE : align;
+ }
+ of_panic("Cannot find memory in the RMA\n");
}
/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges
@@ -834,9 +851,8 @@ static void boot_of_module(ulong r3, ulo
static module_t mods[3];
void *oftree;
ulong oftree_sz = 48 * PAGE_SIZE;
- char *mod0_start;
+ ulong mod0_start;
ulong mod0_size;
- ulong mod0;
static const char sepr[] = " -- ";
extern char dom0_start[] __attribute__ ((weak));
extern char dom0_size[] __attribute__ ((weak));
@@ -844,59 +860,48 @@ static void boot_of_module(ulong r3, ulo
if ((r3 > 0) && (r4 > 0)) {
/* was it handed to us in registers ? */
- mod0_start = (void *)r3;
+ mod0_start = r3;
mod0_size = r4;
+ of_printf("%s: Dom0 was loaded and found using r3/r4:"
+ "0x%lx[size 0x%lx]\n",
+ __func__, mod0_start, mod0_size);
} else {
/* see if it is in the boot params */
p = strstr((char *)((ulong)mbi->cmdline), "dom0_start=");
if ( p != NULL) {
p += 11;
- mod0_start = (char *)simple_strtoul(p, NULL, 0);
+ mod0_start = simple_strtoul(p, NULL, 0);
p = strstr((char *)((ulong)mbi->cmdline), "dom0_size=");
p += 10;
mod0_size = simple_strtoul(p, NULL, 0);
-
- of_printf("mod0: %o %c %c %c\n",
- mod0_start[0],
- mod0_start[1],
- mod0_start[2],
- mod0_start[3]);
-
+ of_printf("%s: Dom0 was loaded and found using cmdline:"
+ "0x%lx[size 0x%lx]\n",
+ __func__, mod0_start, mod0_size);
} else if ( ((ulong)dom0_start != 0) && ((ulong)dom0_size != 0) ) {
/* was it linked in ? */
- mod0_start = dom0_start;
+ mod0_start = (ulong)dom0_start;
mod0_size = (ulong)dom0_size;
- of_printf("%s: linked in module copied after _end "
- "(start 0x%p size 0x%lx)\n",
+ of_printf("%s: Dom0 is linked in: 0x%lx[size 0x%lx]\n",
__func__, mod0_start, mod0_size);
} else {
- mod0_start = _end;
+ mod0_start = (ulong)_end;
mod0_size = 0;
- }
+ of_printf("%s: FYI Dom0 is unknown, will be caught later\n",
+ __func__);
+ }
+ }
+
+ if (mod0_size > 0) {
+ const char *c = (const char *)mod0_start;
+
+ of_printf("mod0: %o %c %c %c\n", c[0], c[1], c[2], c[3]);
}
space_base = (ulong)_end;
- mod0 = find_space(mod0_size, PAGE_SIZE, mbi);
-
- /* three cases
- * 1) mod0_size is not 0 and the image can be copied
- * 2) mod0_size is not 0 and the image cannot be copied
- * 3) mod0_size is 0
- */
- if (mod0_size > 0) {
- if (mod0 != 0) {
- memcpy((void *)mod0, mod0_start, mod0_size);
- mods[0].mod_start = mod0;
- mods[0].mod_end = mod0 + mod0_size;
- } else {
- of_panic("No space to copy mod0\n");
- }
- } else {
- mods[0].mod_start = mod0;
- mods[0].mod_end = mod0;
- }
+ mods[0].mod_start = mod0_start;
+ mods[0].mod_end = mod0_start + mod0_size;
of_printf("%s: mod[0] @ 0x%016x[0x%x]\n", __func__,
mods[0].mod_start, mods[0].mod_end);
diff -r af7c87d42bc6 -r 9b3b420ec064 xen/arch/powerpc/setup.c
--- a/xen/arch/powerpc/setup.c Thu Aug 17 07:10:57 2006 -0400
+++ b/xen/arch/powerpc/setup.c Tue Aug 29 13:20:31 2006 -0500
@@ -61,6 +61,7 @@ unsigned long wait_init_idle;
unsigned long wait_init_idle;
ulong oftree;
ulong oftree_len;
+ulong oftree_end;
cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
cpumask_t cpu_online_map; /* missing ifdef in schedule.c */
@@ -193,17 +194,37 @@ void startup_cpu_idle_loop(void)
reset_stack_and_jump(idle_loop);
}
+static ulong free_xenheap(ulong start, ulong end)
+{
+ start = ALIGN_UP(start, PAGE_SIZE);
+ end = ALIGN_DOWN(end, PAGE_SIZE);
+
+ printk("%s: 0x%lx - 0x%lx\n", __func__, start, end);
+
+ if (oftree <= end && oftree >= start) {
+ printk("%s: Go around the devtree: 0x%lx - 0x%lx\n",
+ __func__, oftree, oftree_end);
+ init_xenheap_pages(start, ALIGN_DOWN(oftree, PAGE_SIZE));
+ init_xenheap_pages(ALIGN_UP(oftree_end, PAGE_SIZE), end);
+ } else {
+ init_xenheap_pages(start, end);
+ }
+ return ALIGN_UP(end, PAGE_SIZE);
+}
+
static void __init __start_xen(multiboot_info_t *mbi)
{
char *cmdline;
module_t *mod = (module_t *)((ulong)mbi->mods_addr);
ulong heap_start;
- ulong modules_start, modules_size;
ulong eomem = 0;
ulong heap_size = 0;
ulong bytes = 0;
- ulong freemem = (ulong)_end;
- ulong oftree_end;
+ ulong freemem;
+ ulong dom0_start, dom0_len;
+ ulong initrd_start, initrd_len;
+
+ int i;
memcpy(0, exception_vectors, exception_vectors_end - exception_vectors);
synchronize_caches(0, exception_vectors_end - exception_vectors);
@@ -234,10 +255,6 @@ static void __init __start_xen(multiboot
if (!(mbi->flags & MBI_MEMMAP)) {
panic("FATAL ERROR: Bootloader provided no memory information.\n");
}
-
- /* mark the begining of images */
- modules_start = mod[0].mod_start;
- modules_size = mod[mbi->mods_count-1].mod_end - mod[0].mod_start;
/* OF dev tree is the last module */
oftree = mod[mbi->mods_count-1].mod_start;
@@ -283,7 +300,15 @@ static void __init __start_xen(multiboot
/* Architecturally the first 4 pages are exception hendlers, we
* will also be copying down some code there */
- heap_start = init_boot_allocator(4 << PAGE_SHIFT);
+ heap_start = 4 << PAGE_SHIFT;
+ if (oftree < (ulong)_start)
+ heap_start = ALIGN_UP(oftree_end, PAGE_SIZE);
+
+ heap_start = init_boot_allocator(heap_start);
+ if (heap_start > (ulong)_start) {
+ panic("space below _start (%p) is not enough memory "
+ "for heap (0x%lx)\n", _start, heap_start);
+ }
/* we give the first RMA to the hypervisor */
xenheap_phys_end = rma_size(cpu_rma_order());
@@ -295,24 +320,28 @@ static void __init __start_xen(multiboot
/* Add memory between the beginning of the heap and the beginning
* of out text */
- init_xenheap_pages(heap_start, (ulong)_start);
-
- /* move the modules to just after _end */
- if (modules_start) {
- printk("modules at: %016lx - %016lx\n", modules_start,
- modules_start + modules_size);
- freemem = ALIGN_UP(freemem, PAGE_SIZE);
- memmove((void *)freemem, (void *)modules_start, modules_size);
-
- oftree -= modules_start - freemem;
- modules_start = freemem;
- freemem += modules_size;
- printk(" moved to: %016lx - %016lx\n", modules_start,
- modules_start + modules_size);
+ free_xenheap(heap_start, (ulong)_start);
+ freemem = ALIGN_UP((ulong)_end, PAGE_SIZE);
+
+ for (i = 0; i < mbi->mods_count; i++) {
+ u32 s;
+
+ s = ALIGN_DOWN(mod[i].mod_start, PAGE_SIZE);
+
+ if (mod[i].mod_start > (ulong)_start &&
+ mod[i].mod_start < (ulong)_end) {
+ /* mod was linked in */
+ continue;
+ }
+
+ if (s < freemem)
+ panic("module addresses must assend\n");
+
+ freemem = free_xenheap(freemem, s);
}
/* the rest of the xenheap, starting at the end of modules */
- init_xenheap_pages(freemem, xenheap_phys_end);
+ free_xenheap(freemem, xenheap_phys_end);
#ifdef OF_DEBUG
@@ -353,22 +382,26 @@ static void __init __start_xen(multiboot
/* Scrub RAM that is still free and so may go to an unprivileged domain. */
scrub_heap_pages();
- /*
- * We're going to setup domain0 using the module(s) that we
- * stashed safely above our heap. The second module, if present,
- * is an initrd ramdisk. The last module is the OF devtree.
- */
- if (construct_dom0(dom0,
- modules_start,
- mod[0].mod_end-mod[0].mod_start,
- (mbi->mods_count == 1) ? 0 :
- modules_start +
- (mod[1].mod_start-mod[0].mod_start),
- (mbi->mods_count == 1) ? 0 :
- mod[mbi->mods_count-1].mod_end - mod[1].mod_start,
+ dom0_start = mod[0].mod_start;
+ dom0_len = mod[0].mod_end - mod[0].mod_start;
+ if (mbi->mods_count > 1) {
+ initrd_start = mod[1].mod_start;
+ initrd_len = mod[1].mod_end - mod[1].mod_start;
+ } else {
+ initrd_start = 0;
+ initrd_len = 0;
+ }
+ if (construct_dom0(dom0, dom0_start, dom0_len,
+ initrd_start, initrd_len,
cmdline) != 0) {
panic("Could not set up DOM0 guest OS\n");
}
+
+ free_xenheap(ALIGN_UP(dom0_start, PAGE_SIZE),
+ ALIGN_DOWN(dom0_start + dom0_len, PAGE_SIZE));
+ if (initrd_start)
+ free_xenheap(ALIGN_UP(initrd_start, PAGE_SIZE),
+ ALIGN_DOWN(initrd_start + initrd_len, PAGE_SIZE));
init_trace_bufs();
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|