ia64/xen-unstable

changeset 11376:980ff1125446

[XEN][POWERPC] Find all of memory and feed all the heaps

This code walks the OF dev tree, finding end-of-memory and memory holes.
All memory beyond the hypervisor's RMA is added to domheap. (Previously
only memory upto 1st hole was used.) Finally, parts of setup.c have been
swept into memory.c as cleanup.

Based on a patch by Dan Poff <poff@us.ibm.com>.

Signed-off-by: Jimi Xenidis <jimix@watson.ibm.com>
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Jimi Xenidis <jimix@watson.ibm.com>
date Tue Aug 22 17:20:58 2006 -0400 (2006-08-22)
parents a8c7ece9cccb
children 20c988c92bee
files xen/arch/powerpc/Makefile xen/arch/powerpc/exceptions.h xen/arch/powerpc/memory.c xen/arch/powerpc/oftree.h xen/arch/powerpc/setup.c
line diff
     1.1 --- a/xen/arch/powerpc/Makefile	Tue Aug 22 11:17:09 2006 -0400
     1.2 +++ b/xen/arch/powerpc/Makefile	Tue Aug 22 17:20:58 2006 -0400
     1.3 @@ -23,6 +23,7 @@ obj-y += htab.o
     1.4  obj-y += iommu.o
     1.5  obj-y += irq.o
     1.6  obj-y += mambo.o
     1.7 +obj-y += memory.o
     1.8  obj-y += mm.o
     1.9  obj-y += mpic.o
    1.10  obj-y += mpic_init.o
     2.1 --- a/xen/arch/powerpc/exceptions.h	Tue Aug 22 11:17:09 2006 -0400
     2.2 +++ b/xen/arch/powerpc/exceptions.h	Tue Aug 22 17:20:58 2006 -0400
     2.3 @@ -51,7 +51,4 @@ extern ulong *__hypercall_table[];
     2.4  extern char exception_vectors[];
     2.5  extern char exception_vectors_end[];
     2.6  extern int spin_start[];
     2.7 -extern int firmware_image_start[0];
     2.8 -extern int firmware_image_size[0];
     2.9 -
    2.10  #endif
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/xen/arch/powerpc/memory.c	Tue Aug 22 17:20:58 2006 -0400
     3.3 @@ -0,0 +1,210 @@
     3.4 +/*
     3.5 + * This program is free software; you can redistribute it and/or modify
     3.6 + * it under the terms of the GNU General Public License as published by
     3.7 + * the Free Software Foundation; either version 2 of the License, or
     3.8 + * (at your option) any later version.
     3.9 + *
    3.10 + * This program is distributed in the hope that it will be useful,
    3.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.13 + * GNU General Public License for more details.
    3.14 + *
    3.15 + * You should have received a copy of the GNU General Public License
    3.16 + * along with this program; if not, write to the Free Software
    3.17 + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    3.18 + *
    3.19 + * Copyright (C) IBM Corp. 2006
    3.20 + *
    3.21 + * Authors: Dan Poff <poff@us.ibm.com>
    3.22 + *          Jimi Xenidis <jimix@watson.ibm.com>
    3.23 + */
    3.24 +#include <xen/sched.h>
    3.25 +#include <xen/mm.h>
    3.26 +#include "of-devtree.h"
    3.27 +#include "oftree.h"
    3.28 +
    3.29 +unsigned long xenheap_phys_end;
    3.30 +struct membuf {
    3.31 +    ulong start;
    3.32 +    ulong size;
    3.33 +};
    3.34 +
    3.35 +typedef void (*walk_mem_fn)(struct membuf *, uint);
    3.36 +
    3.37 +static ulong free_xenheap(ulong start, ulong end)
    3.38 +{
    3.39 +    start = ALIGN_UP(start, PAGE_SIZE);
    3.40 +    end = ALIGN_DOWN(end, PAGE_SIZE);
    3.41 +
    3.42 +    printk("%s: 0x%lx - 0x%lx\n", __func__, start, end);
    3.43 +
    3.44 +    if (oftree <= end && oftree >= start) {
    3.45 +        printk("%s:     Go around the devtree: 0x%lx - 0x%lx\n",
    3.46 +               __func__, oftree, oftree_end);
    3.47 +        init_xenheap_pages(start, ALIGN_DOWN(oftree, PAGE_SIZE));
    3.48 +        init_xenheap_pages(ALIGN_UP(oftree_end, PAGE_SIZE), end);
    3.49 +    } else {
    3.50 +        init_xenheap_pages(start, end);
    3.51 +    }
    3.52 +
    3.53 +    return ALIGN_UP(end, PAGE_SIZE);
    3.54 +}
    3.55 +
    3.56 +static void set_max_page(struct membuf *mb, uint entries)
    3.57 +{
    3.58 +    int i;
    3.59 +
    3.60 +    for (i = 0; i < entries; i++) {
    3.61 +        ulong end_page;
    3.62 +
    3.63 +        end_page = (mb[i].start + mb[i].size) >> PAGE_SHIFT;
    3.64 +
    3.65 +        if (end_page > max_page)
    3.66 +            max_page = end_page;
    3.67 +    }
    3.68 +}
    3.69 +
    3.70 +/* mark all memory from modules onward as unused, skipping hole(s),
    3.71 + * and returning size of hole(s) */
    3.72 +static void heap_init(struct membuf *mb, uint entries)
    3.73 +{
    3.74 +    int i;
    3.75 +    ulong start_blk;
    3.76 +    ulong end_blk = 0;
    3.77 +
    3.78 +	for (i = 0; i < entries; i++) {
    3.79 +	    start_blk = mb[i].start;
    3.80 +	    end_blk = start_blk + mb[i].size;
    3.81 +
    3.82 +	    if (start_blk < xenheap_phys_end) {
    3.83 +            if (xenheap_phys_end > end_blk) {
    3.84 +                panic("xenheap spans LMB\n");
    3.85 +            }
    3.86 +            if (xenheap_phys_end == end_blk)
    3.87 +                continue;
    3.88 +
    3.89 +            start_blk = xenheap_phys_end;
    3.90 +        }
    3.91 +
    3.92 +        init_boot_pages(start_blk, end_blk);
    3.93 +        total_pages += (end_blk - start_blk) >> PAGE_SHIFT;
    3.94 +	}
    3.95 +}
    3.96 +
    3.97 +static void ofd_walk_mem(void *m, walk_mem_fn fn)
    3.98 +{
    3.99 +    ofdn_t n;
   3.100 +    uint p_len;
   3.101 +    struct membuf mb[8];
   3.102 +    static char name[] = "memory";
   3.103 +
   3.104 +    n = ofd_node_find_by_prop(m, OFD_ROOT, "device_type", name, sizeof(name));
   3.105 +    while (n > 0) {
   3.106 +
   3.107 +        p_len = ofd_getprop(m, n, "reg", mb, sizeof (mb));
   3.108 +        if (p_len <= 0) {
   3.109 +            panic("ofd_getprop(): failed\n");
   3.110 +        }
   3.111 +        if (p_len > sizeof(mb))
   3.112 +            panic("%s: buffer is not big enuff for this firmware: "
   3.113 +                  "0x%lx < 0x%x\n", __func__, sizeof(mb), p_len);
   3.114 +
   3.115 +        fn(mb, p_len / sizeof(mb[0]));
   3.116 +        n = ofd_node_find_next(m, n);
   3.117 +    }
   3.118 +}
   3.119 +
   3.120 +static void setup_xenheap(module_t *mod, int mcount)
   3.121 +{
   3.122 +    int i;
   3.123 +    ulong freemem;
   3.124 +
   3.125 +    freemem = ALIGN_UP((ulong)_end, PAGE_SIZE);
   3.126 +
   3.127 +    for (i = 0; i < mcount; i++) {
   3.128 +        u32 s;
   3.129 +
   3.130 +        if(mod[i].mod_end == mod[i].mod_start)
   3.131 +            continue;
   3.132 +
   3.133 +        s = ALIGN_DOWN(mod[i].mod_start, PAGE_SIZE);
   3.134 +
   3.135 +        if (mod[i].mod_start > (ulong)_start &&
   3.136 +            mod[i].mod_start < (ulong)_end) {
   3.137 +            /* mod was linked in */
   3.138 +            continue;
   3.139 +        }
   3.140 +
   3.141 +        if (s < freemem) 
   3.142 +            panic("module addresses must assend\n");
   3.143 +
   3.144 +        free_xenheap(freemem, s);
   3.145 +        freemem = ALIGN_UP(mod[i].mod_end, PAGE_SIZE);
   3.146 +        
   3.147 +    }
   3.148 +
   3.149 +    /* the rest of the xenheap, starting at the end of modules */
   3.150 +    free_xenheap(freemem, xenheap_phys_end);
   3.151 +}
   3.152 +
   3.153 +void memory_init(module_t *mod, int mcount)
   3.154 +{
   3.155 +    ulong eomem;
   3.156 +    ulong heap_start, heap_size;
   3.157 +
   3.158 +    printk("Physical RAM map:\n");
   3.159 +
   3.160 +    /* lets find out how much memory there is and set max_page */
   3.161 +    max_page = 0;
   3.162 +    ofd_walk_mem((void *)oftree, set_max_page);
   3.163 +    eomem = max_page << PAGE_SHIFT;
   3.164 +
   3.165 +    if (eomem == 0){
   3.166 +        panic("ofd_walk_mem() failed\n");
   3.167 +    }
   3.168 +    printk("End of RAM: %luMB (%lukB)\n", eomem >> 20, eomem >> 10);
   3.169 +
   3.170 +    /* Architecturally the first 4 pages are exception hendlers, we
   3.171 +     * will also be copying down some code there */
   3.172 +    heap_start = 4 << PAGE_SHIFT;
   3.173 +    if (oftree < (ulong)_start)
   3.174 +        heap_start = ALIGN_UP(oftree_end, PAGE_SIZE);
   3.175 +
   3.176 +    heap_start = init_boot_allocator(heap_start);
   3.177 +    if (heap_start > (ulong)_start) {
   3.178 +        panic("space below _start (%p) is not enough memory "
   3.179 +              "for heap (0x%lx)\n", _start, heap_start);
   3.180 +    }
   3.181 +
   3.182 +    /* we give the first RMA to the hypervisor */
   3.183 +    xenheap_phys_end = rma_size(cpu_rma_order());
   3.184 +
   3.185 +    /* allow everything else to be allocated */
   3.186 +    total_pages = 0;
   3.187 +    ofd_walk_mem((void *)oftree, heap_init);
   3.188 +    if (total_pages == 0)
   3.189 +        panic("heap_init: failed");
   3.190 +
   3.191 +    if (total_pages > max_page)
   3.192 +        panic("total_pages > max_page: 0x%lx > 0x%lx\n",
   3.193 +              total_pages, max_page);
   3.194 +
   3.195 +    printk("total_pages: 0x%016lx\n", total_pages);
   3.196 +
   3.197 +    init_frametable();
   3.198 +    end_boot_allocator();
   3.199 +
   3.200 +    /* Add memory between the beginning of the heap and the beginning
   3.201 +     * of out text */
   3.202 +    free_xenheap(heap_start, (ulong)_start);
   3.203 +
   3.204 +    heap_size = xenheap_phys_end - heap_start;
   3.205 +    printk("Xen heap: %luMB (%lukB)\n", heap_size >> 20, heap_size >> 10);
   3.206 +
   3.207 +    setup_xenheap(mod, mcount);
   3.208 +
   3.209 +    eomem = avail_domheap_pages();
   3.210 +    printk("Domheap pages: 0x%lx %luMB (%lukB)\n", eomem,
   3.211 +           (eomem << PAGE_SHIFT) >> 20,
   3.212 +           (eomem << PAGE_SHIFT) >> 10);
   3.213 +}
     4.1 --- a/xen/arch/powerpc/oftree.h	Tue Aug 22 11:17:09 2006 -0400
     4.2 +++ b/xen/arch/powerpc/oftree.h	Tue Aug 22 17:20:58 2006 -0400
     4.3 @@ -20,9 +20,11 @@
     4.4  
     4.5  #ifndef _OFTREE_H
     4.6  #define _OFTREE_H
     4.7 +#include <xen/multiboot.h>
     4.8  
     4.9  extern ulong oftree;
    4.10  extern ulong oftree_len;
    4.11 +extern ulong oftree_end;
    4.12  
    4.13  extern int ofd_dom0_fixup(
    4.14      struct domain *d, ulong mem, start_info_t *si, ulong dst);
    4.15 @@ -30,4 +32,6 @@ extern int ofd_dom0_fixup(
    4.16  extern int firmware_image_start[0];
    4.17  extern int firmware_image_size[0];
    4.18  
    4.19 +extern void memory_init(module_t *mod, int mcount);
    4.20 +
    4.21  #endif  /* #ifndef _OFTREE_H */
     5.1 --- a/xen/arch/powerpc/setup.c	Tue Aug 22 11:17:09 2006 -0400
     5.2 +++ b/xen/arch/powerpc/setup.c	Tue Aug 22 17:20:58 2006 -0400
     5.3 @@ -43,9 +43,9 @@
     5.4  #include <asm/percpu.h>
     5.5  #include "exceptions.h"
     5.6  #include "of-devtree.h"
     5.7 +#include "oftree.h"
     5.8  
     5.9  #define DEBUG
    5.10 -unsigned long xenheap_phys_end;
    5.11  
    5.12  /* opt_noht: If true, Hyperthreading is ignored. */
    5.13  int opt_noht = 0;
    5.14 @@ -220,24 +220,6 @@ void startup_cpu_idle_loop(void)
    5.15      reset_stack_and_jump(idle_loop);
    5.16  }
    5.17  
    5.18 -static ulong free_xenheap(ulong start, ulong end)
    5.19 -{
    5.20 -    start = ALIGN_UP(start, PAGE_SIZE);
    5.21 -    end = ALIGN_DOWN(end, PAGE_SIZE);
    5.22 -
    5.23 -    printk("%s: 0x%lx - 0x%lx\n", __func__, start, end);
    5.24 -
    5.25 -    if (oftree <= end && oftree >= start) {
    5.26 -        printk("%s:     Go around the devtree: 0x%lx - 0x%lx\n",
    5.27 -                  __func__, oftree, oftree_end);
    5.28 -        init_xenheap_pages(start, ALIGN_DOWN(oftree, PAGE_SIZE));
    5.29 -        init_xenheap_pages(ALIGN_UP(oftree_end, PAGE_SIZE), end);
    5.30 -    } else {
    5.31 -        init_xenheap_pages(start, end);
    5.32 -    }
    5.33 -    return ALIGN_UP(end, PAGE_SIZE);
    5.34 -}
    5.35 -
    5.36  static void init_parea(int cpuid)
    5.37  {
    5.38      /* Be careful not to shadow the global variable.  */
    5.39 @@ -289,15 +271,8 @@ static void __init __start_xen(multiboot
    5.40  {
    5.41      char *cmdline;
    5.42      module_t *mod = (module_t *)((ulong)mbi->mods_addr);
    5.43 -    ulong heap_start;
    5.44 -    ulong eomem = 0;
    5.45 -    ulong heap_size = 0;
    5.46 -    ulong bytes = 0;
    5.47 -    ulong freemem;
    5.48      ulong dom0_start, dom0_len;
    5.49      ulong initrd_start, initrd_len;
    5.50 -    
    5.51 -    int i;
    5.52  
    5.53      memcpy(0, exception_vectors, exception_vectors_end - exception_vectors);
    5.54      synchronize_caches(0, exception_vectors_end - exception_vectors);
    5.55 @@ -339,88 +314,7 @@ static void __init __start_xen(multiboot
    5.56      mod[mbi->mods_count-1].mod_end = 0;
    5.57      --mbi->mods_count;
    5.58  
    5.59 -    printk("Physical RAM map:\n");
    5.60 -
    5.61 -    /* lets find out how much memory there is */
    5.62 -    while (bytes < mbi->mmap_length) {
    5.63 -        u64 end;
    5.64 -        u64 addr;
    5.65 -        u64 size;
    5.66 -
    5.67 -        memory_map_t *map = (memory_map_t *)((ulong)mbi->mmap_addr + bytes);
    5.68 -        addr = ((u64)map->base_addr_high << 32) | (u64)map->base_addr_low;
    5.69 -        size = ((u64)map->length_high << 32) | (u64)map->length_low;
    5.70 -        end = addr + size;
    5.71 -
    5.72 -        printk(" %016lx - %016lx (usable)\n", addr, end);
    5.73 -
    5.74 -        if (addr > eomem) {
    5.75 -            printk("found a hole skipping remainder of memory at:\n"
    5.76 -                   " %016lx and beyond\n", addr);
    5.77 -            break;
    5.78 -        }
    5.79 -        if (end > eomem) {
    5.80 -            eomem = end;
    5.81 -        }
    5.82 -        bytes += map->size + 4;
    5.83 -    }
    5.84 -
    5.85 -    printk("System RAM: %luMB (%lukB)\n", eomem >> 20, eomem >> 10);
    5.86 -
    5.87 -    /* top of memory */
    5.88 -    max_page = PFN_DOWN(ALIGN_DOWN(eomem, PAGE_SIZE));
    5.89 -    total_pages = max_page;
    5.90 -
    5.91 -    /* Architecturally the first 4 pages are exception hendlers, we
    5.92 -     * will also be copying down some code there */
    5.93 -    heap_start = 4 << PAGE_SHIFT;
    5.94 -    if (oftree < (ulong)_start)
    5.95 -        heap_start = ALIGN_UP(oftree_end, PAGE_SIZE);
    5.96 -
    5.97 -    heap_start = init_boot_allocator(heap_start);
    5.98 -    if (heap_start > (ulong)_start) {
    5.99 -        panic("space below _start (%p) is not enough memory "
   5.100 -              "for heap (0x%lx)\n", _start, heap_start);
   5.101 -    }
   5.102 -
   5.103 -    /* we give the first RMA to the hypervisor */
   5.104 -    xenheap_phys_end = rma_size(cpu_rma_order());
   5.105 -
   5.106 -    /* allow everything else to be allocated */
   5.107 -    init_boot_pages(xenheap_phys_end, eomem);
   5.108 -    init_frametable();
   5.109 -    end_boot_allocator();
   5.110 -
   5.111 -    /* Add memory between the beginning of the heap and the beginning
   5.112 -     * of out text */
   5.113 -    free_xenheap(heap_start, (ulong)_start);
   5.114 -    freemem = ALIGN_UP((ulong)_end, PAGE_SIZE);
   5.115 -
   5.116 -    for (i = 0; i < mbi->mods_count; i++) {
   5.117 -        u32 s;
   5.118 -
   5.119 -        if(mod[i].mod_end == mod[i].mod_start)
   5.120 -            continue;
   5.121 -
   5.122 -        s = ALIGN_DOWN(mod[i].mod_start, PAGE_SIZE);
   5.123 -
   5.124 -        if (mod[i].mod_start > (ulong)_start &&
   5.125 -            mod[i].mod_start < (ulong)_end) {
   5.126 -            /* mod was linked in */
   5.127 -            continue;
   5.128 -        }
   5.129 -
   5.130 -        if (s < freemem) 
   5.131 -            panic("module addresses must assend\n");
   5.132 -
   5.133 -        free_xenheap(freemem, s);
   5.134 -        freemem = ALIGN_UP(mod[i].mod_end, PAGE_SIZE);
   5.135 -        
   5.136 -    }
   5.137 -
   5.138 -    /* the rest of the xenheap, starting at the end of modules */
   5.139 -    free_xenheap(freemem, xenheap_phys_end);
   5.140 -
   5.141 +    memory_init(mod, mbi->mods_count);
   5.142  
   5.143  #ifdef OF_DEBUG
   5.144      printk("ofdump:\n");
   5.145 @@ -428,10 +322,6 @@ static void __init __start_xen(multiboot
   5.146      ofd_walk((void *)oftree, OFD_ROOT, ofd_dump_props, OFD_DUMP_ALL);
   5.147  #endif
   5.148  
   5.149 -    heap_size = xenheap_phys_end - heap_start;
   5.150 -
   5.151 -    printk("Xen heap: %luMB (%lukB)\n", heap_size >> 20, heap_size >> 10);
   5.152 -
   5.153      percpu_init_areas();
   5.154  
   5.155      init_parea(0);
   5.156 @@ -484,10 +374,10 @@ static void __init __start_xen(multiboot
   5.157          panic("Could not set up DOM0 guest OS\n");
   5.158      }
   5.159  
   5.160 -    free_xenheap(ALIGN_UP(dom0_start, PAGE_SIZE),
   5.161 +    init_xenheap_pages(ALIGN_UP(dom0_start, PAGE_SIZE),
   5.162                   ALIGN_DOWN(dom0_start + dom0_len, PAGE_SIZE));
   5.163      if (initrd_start)
   5.164 -        free_xenheap(ALIGN_UP(initrd_start, PAGE_SIZE),
   5.165 +        init_xenheap_pages(ALIGN_UP(initrd_start, PAGE_SIZE),
   5.166                       ALIGN_DOWN(initrd_start + initrd_len, PAGE_SIZE));
   5.167  
   5.168      init_trace_bufs();