direct-io.hg

changeset 11357:9b3b420ec064

[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@watson.ibm.com>
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Hollis Blanchard <hollisb@us.ibm.com>
date Tue Aug 29 13:20:31 2006 -0500 (2006-08-29)
parents af7c87d42bc6
children 47078e89e663
files xen/arch/powerpc/boot_of.c xen/arch/powerpc/setup.c
line diff
     1.1 --- a/xen/arch/powerpc/boot_of.c	Thu Aug 17 07:10:57 2006 -0400
     1.2 +++ b/xen/arch/powerpc/boot_of.c	Tue Aug 29 13:20:31 2006 -0500
     1.3 @@ -26,6 +26,7 @@
     1.4  #include <xen/spinlock.h>
     1.5  #include <xen/serial.h>
     1.6  #include <xen/time.h>
     1.7 +#include <xen/sched.h>
     1.8  #include <asm/page.h>
     1.9  #include <asm/io.h>
    1.10  #include "exceptions.h"
    1.11 @@ -322,17 +323,18 @@ static void __init of_test(const char *o
    1.12      }
    1.13  }
    1.14  
    1.15 -static int __init of_claim(void * virt, u32 size)
    1.16 +static int __init of_claim(u32 virt, u32 size, u32 align)
    1.17  {
    1.18      int rets[1] = { OF_FAILURE };
    1.19      
    1.20 -    of_call("claim", 3, 1, rets, virt, size, 0/*align*/);
    1.21 +    of_call("claim", 3, 1, rets, virt, size, align);
    1.22      if (rets[0] == OF_FAILURE) {
    1.23 -        DBG("%s 0x%p 0x%08x -> FAIL\n", __func__, virt, size);
    1.24 +        DBG("%s 0x%08x 0x%08x  0x%08x -> FAIL\n", __func__, virt, size, align);
    1.25          return OF_FAILURE;
    1.26      }
    1.27  
    1.28 -    DBG("%s 0x%p 0x%08x -> 0x%x\n", __func__, virt, size, rets[0]);
    1.29 +    DBG("%s 0x%08x 0x%08x  0x%08x -> 0x%08x\n", __func__, virt, size, align,
    1.30 +        rets[0]);
    1.31      return rets[0];
    1.32  }
    1.33  
    1.34 @@ -683,32 +685,47 @@ static int boot_of_fixup_chosen(void *me
    1.35  }
    1.36  
    1.37  static ulong space_base;
    1.38 -static ulong find_space(u32 size, ulong align, multiboot_info_t *mbi)
    1.39 +static int broken_claim;
    1.40 +
    1.41 +/*
    1.42 + * The following function is necessary because we cannot depend on all
    1.43 + * FW to actually allocate us any space, so we look for it _hoping_
    1.44 + * that at least is will fail if we try to claim something that
    1.45 + * belongs to FW.  This hope does not seem to be true on some version
    1.46 + * of PIBS.
    1.47 + */
    1.48 +static ulong find_space(u32 size, u32 align, multiboot_info_t *mbi)
    1.49  {
    1.50      memory_map_t *map = (memory_map_t *)((ulong)mbi->mmap_addr);
    1.51      ulong eomem = ((u64)map->length_high << 32) | (u64)map->length_low;
    1.52      ulong base;
    1.53  
    1.54 -    of_printf("%s base=0x%016lx  eomem=0x%016lx  size=0x%08x  align=0x%lx\n",
    1.55 +    if (size == 0) return base;
    1.56 +
    1.57 +    if (align == 0)
    1.58 +        of_panic("cannot call %s() with align of 0\n", __func__);
    1.59 +
    1.60 +    if (!broken_claim) {
    1.61 +        /* just try and claim it to the FW chosen address */
    1.62 +        base = of_claim(0, size, align);
    1.63 +        if (base != OF_FAILURE)
    1.64 +            return base;
    1.65 +        of_printf("%s: Firmware does not allocate memory for you\n", __func__);
    1.66 +        broken_claim = 1;
    1.67 +    }
    1.68 +
    1.69 +    of_printf("%s base=0x%016lx  eomem=0x%016lx  size=0x%08x  align=0x%x\n",
    1.70                      __func__, space_base, eomem, size, align);
    1.71      base = ALIGN_UP(space_base, PAGE_SIZE);
    1.72 -    if ((base + size) >= 0x4000000) return 0;
    1.73 -    if (base + size > eomem) of_panic("not enough RAM\n");
    1.74  
    1.75 -    if (size == 0) return base;
    1.76 -    if (of_claim((void*)base, size) != OF_FAILURE) {
    1.77 -        space_base = base + size;
    1.78 -        return base;
    1.79 -    } else {
    1.80 -        for(base += 0x100000; (base+size) < 0x4000000; base += 0x100000) {
    1.81 -            of_printf("Trying 0x%016lx\n", base);
    1.82 -            if (of_claim((void*)base, size) != OF_FAILURE) {
    1.83 -                space_base = base + size;
    1.84 -                return base;
    1.85 -            }
    1.86 +    while ((base + size) < rma_size(cpu_rma_order())) {
    1.87 +        if (of_claim(base, size, 0) != OF_FAILURE) {
    1.88 +            space_base = base + size;
    1.89 +            return base;
    1.90          }
    1.91 -        return 0;
    1.92 +        base += (PAGE_SIZE >  align) ? PAGE_SIZE : align;
    1.93      }
    1.94 +    of_panic("Cannot find memory in the RMA\n");
    1.95  }
    1.96  
    1.97  /* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges
    1.98 @@ -834,9 +851,8 @@ static void boot_of_module(ulong r3, ulo
    1.99      static module_t mods[3];
   1.100      void *oftree;
   1.101      ulong oftree_sz = 48 * PAGE_SIZE;
   1.102 -    char *mod0_start;
   1.103 +    ulong mod0_start;
   1.104      ulong mod0_size;
   1.105 -    ulong mod0;
   1.106      static const char sepr[] = " -- ";
   1.107      extern char dom0_start[] __attribute__ ((weak));
   1.108      extern char dom0_size[] __attribute__ ((weak));
   1.109 @@ -844,60 +860,49 @@ static void boot_of_module(ulong r3, ulo
   1.110  
   1.111      if ((r3 > 0) && (r4 > 0)) {
   1.112          /* was it handed to us in registers ? */
   1.113 -        mod0_start = (void *)r3;
   1.114 +        mod0_start = r3;
   1.115          mod0_size = r4;
   1.116 +            of_printf("%s: Dom0 was loaded and found using r3/r4:"
   1.117 +                      "0x%lx[size 0x%lx]\n",
   1.118 +                      __func__, mod0_start, mod0_size);
   1.119      } else {
   1.120          /* see if it is in the boot params */
   1.121          p = strstr((char *)((ulong)mbi->cmdline), "dom0_start=");
   1.122          if ( p != NULL) {
   1.123              p += 11;
   1.124 -            mod0_start = (char *)simple_strtoul(p, NULL, 0);
   1.125 +            mod0_start = simple_strtoul(p, NULL, 0);
   1.126  
   1.127              p = strstr((char *)((ulong)mbi->cmdline), "dom0_size=");
   1.128              p += 10;
   1.129              mod0_size = simple_strtoul(p, NULL, 0);
   1.130 -
   1.131 -            of_printf("mod0: %o %c %c %c\n",
   1.132 -                      mod0_start[0],
   1.133 -                      mod0_start[1],
   1.134 -                      mod0_start[2],
   1.135 -                      mod0_start[3]);
   1.136 -
   1.137 +            of_printf("%s: Dom0 was loaded and found using cmdline:"
   1.138 +                      "0x%lx[size 0x%lx]\n",
   1.139 +                      __func__, mod0_start, mod0_size);
   1.140          } else if ( ((ulong)dom0_start != 0) && ((ulong)dom0_size != 0) ) {
   1.141              /* was it linked in ? */
   1.142          
   1.143 -            mod0_start = dom0_start;
   1.144 +            mod0_start = (ulong)dom0_start;
   1.145              mod0_size = (ulong)dom0_size;
   1.146 -            of_printf("%s: linked in module copied after _end "
   1.147 -                      "(start 0x%p size 0x%lx)\n",
   1.148 +            of_printf("%s: Dom0 is linked in: 0x%lx[size 0x%lx]\n",
   1.149                        __func__, mod0_start, mod0_size);
   1.150          } else {
   1.151 -            mod0_start = _end;
   1.152 +            mod0_start = (ulong)_end;
   1.153              mod0_size = 0;
   1.154 +            of_printf("%s: FYI Dom0 is unknown, will be caught later\n",
   1.155 +                      __func__);
   1.156          }
   1.157      }
   1.158  
   1.159 -    space_base = (ulong)_end;
   1.160 -    mod0 = find_space(mod0_size, PAGE_SIZE, mbi);
   1.161 +    if (mod0_size > 0) {
   1.162 +        const char *c = (const char *)mod0_start;
   1.163  
   1.164 -    /* three cases
   1.165 -     * 1) mod0_size is not 0 and the image can be copied
   1.166 -     * 2) mod0_size is not 0 and the image cannot be copied
   1.167 -     * 3) mod0_size is 0
   1.168 -     */
   1.169 -    if (mod0_size > 0) {
   1.170 -        if (mod0 != 0) {
   1.171 -            memcpy((void *)mod0, mod0_start, mod0_size);
   1.172 -            mods[0].mod_start = mod0;
   1.173 -            mods[0].mod_end = mod0 + mod0_size;
   1.174 -        } else {
   1.175 -            of_panic("No space to copy mod0\n");
   1.176 -        }
   1.177 -    } else {
   1.178 -        mods[0].mod_start = mod0;
   1.179 -        mods[0].mod_end = mod0;
   1.180 +        of_printf("mod0: %o %c %c %c\n", c[0], c[1], c[2], c[3]);
   1.181      }
   1.182  
   1.183 +    space_base = (ulong)_end;
   1.184 +    mods[0].mod_start = mod0_start;
   1.185 +    mods[0].mod_end = mod0_start + mod0_size;
   1.186 +
   1.187      of_printf("%s: mod[0] @ 0x%016x[0x%x]\n", __func__,
   1.188                mods[0].mod_start, mods[0].mod_end);
   1.189      p = strstr((char *)(ulong)mbi->cmdline, sepr);
     2.1 --- a/xen/arch/powerpc/setup.c	Thu Aug 17 07:10:57 2006 -0400
     2.2 +++ b/xen/arch/powerpc/setup.c	Tue Aug 29 13:20:31 2006 -0500
     2.3 @@ -61,6 +61,7 @@ unsigned int watchdog_on;
     2.4  unsigned long wait_init_idle;
     2.5  ulong oftree;
     2.6  ulong oftree_len;
     2.7 +ulong oftree_end;
     2.8  
     2.9  cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
    2.10  cpumask_t cpu_online_map; /* missing ifdef in schedule.c */
    2.11 @@ -193,17 +194,37 @@ void startup_cpu_idle_loop(void)
    2.12      reset_stack_and_jump(idle_loop);
    2.13  }
    2.14  
    2.15 +static ulong free_xenheap(ulong start, ulong end)
    2.16 +{
    2.17 +    start = ALIGN_UP(start, PAGE_SIZE);
    2.18 +    end = ALIGN_DOWN(end, PAGE_SIZE);
    2.19 +
    2.20 +    printk("%s: 0x%lx - 0x%lx\n", __func__, start, end);
    2.21 +
    2.22 +    if (oftree <= end && oftree >= start) {
    2.23 +        printk("%s:     Go around the devtree: 0x%lx - 0x%lx\n",
    2.24 +                  __func__, oftree, oftree_end);
    2.25 +        init_xenheap_pages(start, ALIGN_DOWN(oftree, PAGE_SIZE));
    2.26 +        init_xenheap_pages(ALIGN_UP(oftree_end, PAGE_SIZE), end);
    2.27 +    } else {
    2.28 +        init_xenheap_pages(start, end);
    2.29 +    }
    2.30 +    return ALIGN_UP(end, PAGE_SIZE);
    2.31 +}
    2.32 +
    2.33  static void __init __start_xen(multiboot_info_t *mbi)
    2.34  {
    2.35      char *cmdline;
    2.36      module_t *mod = (module_t *)((ulong)mbi->mods_addr);
    2.37      ulong heap_start;
    2.38 -    ulong modules_start, modules_size;
    2.39      ulong eomem = 0;
    2.40      ulong heap_size = 0;
    2.41      ulong bytes = 0;
    2.42 -    ulong freemem = (ulong)_end;
    2.43 -    ulong oftree_end;
    2.44 +    ulong freemem;
    2.45 +    ulong dom0_start, dom0_len;
    2.46 +    ulong initrd_start, initrd_len;
    2.47 +    
    2.48 +    int i;
    2.49  
    2.50      memcpy(0, exception_vectors, exception_vectors_end - exception_vectors);
    2.51      synchronize_caches(0, exception_vectors_end - exception_vectors);
    2.52 @@ -235,10 +256,6 @@ static void __init __start_xen(multiboot
    2.53          panic("FATAL ERROR: Bootloader provided no memory information.\n");
    2.54      }
    2.55  
    2.56 -    /* mark the begining of images */
    2.57 -    modules_start = mod[0].mod_start;
    2.58 -    modules_size = mod[mbi->mods_count-1].mod_end - mod[0].mod_start;
    2.59 -
    2.60      /* OF dev tree is the last module */
    2.61      oftree = mod[mbi->mods_count-1].mod_start;
    2.62      oftree_end = mod[mbi->mods_count-1].mod_end;
    2.63 @@ -283,7 +300,15 @@ static void __init __start_xen(multiboot
    2.64  
    2.65      /* Architecturally the first 4 pages are exception hendlers, we
    2.66       * will also be copying down some code there */
    2.67 -    heap_start = init_boot_allocator(4 << PAGE_SHIFT);
    2.68 +    heap_start = 4 << PAGE_SHIFT;
    2.69 +    if (oftree < (ulong)_start)
    2.70 +        heap_start = ALIGN_UP(oftree_end, PAGE_SIZE);
    2.71 +
    2.72 +    heap_start = init_boot_allocator(heap_start);
    2.73 +    if (heap_start > (ulong)_start) {
    2.74 +        panic("space below _start (%p) is not enough memory "
    2.75 +              "for heap (0x%lx)\n", _start, heap_start);
    2.76 +    }
    2.77  
    2.78      /* we give the first RMA to the hypervisor */
    2.79      xenheap_phys_end = rma_size(cpu_rma_order());
    2.80 @@ -295,24 +320,28 @@ static void __init __start_xen(multiboot
    2.81  
    2.82      /* Add memory between the beginning of the heap and the beginning
    2.83       * of out text */
    2.84 -    init_xenheap_pages(heap_start, (ulong)_start);
    2.85 +    free_xenheap(heap_start, (ulong)_start);
    2.86 +    freemem = ALIGN_UP((ulong)_end, PAGE_SIZE);
    2.87 +
    2.88 +    for (i = 0; i < mbi->mods_count; i++) {
    2.89 +        u32 s;
    2.90 +
    2.91 +        s = ALIGN_DOWN(mod[i].mod_start, PAGE_SIZE);
    2.92  
    2.93 -    /* move the modules to just after _end */
    2.94 -    if (modules_start) {
    2.95 -        printk("modules at: %016lx - %016lx\n", modules_start,
    2.96 -                modules_start + modules_size);
    2.97 -        freemem = ALIGN_UP(freemem, PAGE_SIZE);
    2.98 -        memmove((void *)freemem, (void *)modules_start, modules_size);
    2.99 +        if (mod[i].mod_start > (ulong)_start &&
   2.100 +            mod[i].mod_start < (ulong)_end) {
   2.101 +            /* mod was linked in */
   2.102 +            continue;
   2.103 +        }
   2.104  
   2.105 -        oftree -= modules_start - freemem;
   2.106 -        modules_start = freemem;
   2.107 -        freemem += modules_size;
   2.108 -        printk("  moved to: %016lx - %016lx\n", modules_start,
   2.109 -                modules_start + modules_size);
   2.110 +        if (s < freemem) 
   2.111 +            panic("module addresses must assend\n");
   2.112 +
   2.113 +        freemem = free_xenheap(freemem, s);
   2.114      }
   2.115  
   2.116      /* the rest of the xenheap, starting at the end of modules */
   2.117 -    init_xenheap_pages(freemem, xenheap_phys_end);
   2.118 +    free_xenheap(freemem, xenheap_phys_end);
   2.119  
   2.120  
   2.121  #ifdef OF_DEBUG
   2.122 @@ -353,23 +382,27 @@ static void __init __start_xen(multiboot
   2.123      /* Scrub RAM that is still free and so may go to an unprivileged domain. */
   2.124      scrub_heap_pages();
   2.125  
   2.126 -    /*
   2.127 -     * We're going to setup domain0 using the module(s) that we
   2.128 -     * stashed safely above our heap. The second module, if present,
   2.129 -     * is an initrd ramdisk.  The last module is the OF devtree.
   2.130 -     */
   2.131 -    if (construct_dom0(dom0,
   2.132 -                       modules_start, 
   2.133 -                       mod[0].mod_end-mod[0].mod_start,
   2.134 -                       (mbi->mods_count == 1) ? 0 :
   2.135 -                       modules_start + 
   2.136 -                       (mod[1].mod_start-mod[0].mod_start),
   2.137 -                       (mbi->mods_count == 1) ? 0 :
   2.138 -                       mod[mbi->mods_count-1].mod_end - mod[1].mod_start,
   2.139 +    dom0_start = mod[0].mod_start;
   2.140 +    dom0_len = mod[0].mod_end - mod[0].mod_start;
   2.141 +    if (mbi->mods_count > 1) {
   2.142 +        initrd_start = mod[1].mod_start;
   2.143 +        initrd_len = mod[1].mod_end - mod[1].mod_start;
   2.144 +    } else {
   2.145 +        initrd_start = 0;
   2.146 +        initrd_len = 0;
   2.147 +    }
   2.148 +    if (construct_dom0(dom0, dom0_start, dom0_len,
   2.149 +                       initrd_start, initrd_len,
   2.150                         cmdline) != 0) {
   2.151          panic("Could not set up DOM0 guest OS\n");
   2.152      }
   2.153  
   2.154 +    free_xenheap(ALIGN_UP(dom0_start, PAGE_SIZE),
   2.155 +                 ALIGN_DOWN(dom0_start + dom0_len, PAGE_SIZE));
   2.156 +    if (initrd_start)
   2.157 +        free_xenheap(ALIGN_UP(initrd_start, PAGE_SIZE),
   2.158 +                     ALIGN_DOWN(initrd_start + initrd_len, PAGE_SIZE));
   2.159 +
   2.160      init_trace_bufs();
   2.161  
   2.162      console_endboot();