# HG changeset patch
# User Jimi Xenidis <[EMAIL PROTECTED]>
# Node ID 697bd866535ba6d73de5fc6c988e96bc034bbdd0
# Parent  5e4dcc79f29a9dc5217a86b561e36b8d07c2d7dc
[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
---
 xen/arch/powerpc/boot_of.c |  127 +++++++++++++++++++++++----------------------
 xen/arch/powerpc/setup.c   |  107 +++++++++++++++++++++++++------------
 2 files changed, 137 insertions(+), 97 deletions(-)

diff -r 5e4dcc79f29a -r 697bd866535b 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        Thu Aug 17 16:21:34 2006 -0400
@@ -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 5e4dcc79f29a -r 697bd866535b 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  Thu Aug 17 16:21:34 2006 -0400
@@ -44,6 +44,8 @@
 #include "exceptions.h"
 #include "of-devtree.h"
 
+DEFINE_PER_CPU(ulong, pcpu_var);
+
 #define DEBUG
 unsigned long xenheap_phys_end;
 
@@ -61,6 +63,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 +196,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 +257,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 +302,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 +322,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 +384,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-ppc-devel mailing list
Xen-ppc-devel@lists.xensource.com
http://lists.xensource.com/xen-ppc-devel

Reply via email to