[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN][POWERPC] Find all of memory and feed all the heaps
# HG changeset patch # User Jimi Xenidis <jimix@xxxxxxxxxxxxxx> # Node ID 980ff112544672926aab7baa81381b4f6000eba0 # Parent a8c7ece9cccb8cd3dee3be28c891d6b7b7f9c6ee [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@xxxxxxxxxx>. Signed-off-by: Jimi Xenidis <jimix@xxxxxxxxxxxxxx> Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx> --- xen/arch/powerpc/Makefile | 1 xen/arch/powerpc/exceptions.h | 3 xen/arch/powerpc/memory.c | 210 ++++++++++++++++++++++++++++++++++++++++++ xen/arch/powerpc/oftree.h | 4 xen/arch/powerpc/setup.c | 118 ----------------------- 5 files changed, 219 insertions(+), 117 deletions(-) diff -r a8c7ece9cccb -r 980ff1125446 xen/arch/powerpc/Makefile --- a/xen/arch/powerpc/Makefile Tue Aug 22 11:17:09 2006 -0400 +++ b/xen/arch/powerpc/Makefile Tue Aug 22 17:20:58 2006 -0400 @@ -23,6 +23,7 @@ obj-y += iommu.o obj-y += iommu.o obj-y += irq.o obj-y += mambo.o +obj-y += memory.o obj-y += mm.o obj-y += mpic.o obj-y += mpic_init.o diff -r a8c7ece9cccb -r 980ff1125446 xen/arch/powerpc/exceptions.h --- a/xen/arch/powerpc/exceptions.h Tue Aug 22 11:17:09 2006 -0400 +++ b/xen/arch/powerpc/exceptions.h Tue Aug 22 17:20:58 2006 -0400 @@ -51,7 +51,4 @@ extern char exception_vectors[]; extern char exception_vectors[]; extern char exception_vectors_end[]; extern int spin_start[]; -extern int firmware_image_start[0]; -extern int firmware_image_size[0]; - #endif diff -r a8c7ece9cccb -r 980ff1125446 xen/arch/powerpc/oftree.h --- a/xen/arch/powerpc/oftree.h Tue Aug 22 11:17:09 2006 -0400 +++ b/xen/arch/powerpc/oftree.h Tue Aug 22 17:20:58 2006 -0400 @@ -20,9 +20,11 @@ #ifndef _OFTREE_H #define _OFTREE_H +#include <xen/multiboot.h> extern ulong oftree; extern ulong oftree_len; +extern ulong oftree_end; extern int ofd_dom0_fixup( struct domain *d, ulong mem, start_info_t *si, ulong dst); @@ -30,4 +32,6 @@ extern int firmware_image_start[0]; extern int firmware_image_start[0]; extern int firmware_image_size[0]; +extern void memory_init(module_t *mod, int mcount); + #endif /* #ifndef _OFTREE_H */ diff -r a8c7ece9cccb -r 980ff1125446 xen/arch/powerpc/setup.c --- a/xen/arch/powerpc/setup.c Tue Aug 22 11:17:09 2006 -0400 +++ b/xen/arch/powerpc/setup.c Tue Aug 22 17:20:58 2006 -0400 @@ -43,9 +43,9 @@ #include <asm/percpu.h> #include "exceptions.h" #include "of-devtree.h" +#include "oftree.h" #define DEBUG -unsigned long xenheap_phys_end; /* opt_noht: If true, Hyperthreading is ignored. */ int opt_noht = 0; @@ -220,24 +220,6 @@ 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_parea(int cpuid) { /* Be careful not to shadow the global variable. */ @@ -289,15 +271,8 @@ static void __init __start_xen(multiboot { char *cmdline; module_t *mod = (module_t *)((ulong)mbi->mods_addr); - ulong heap_start; - ulong eomem = 0; - ulong heap_size = 0; - ulong bytes = 0; - 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); @@ -339,98 +314,13 @@ static void __init __start_xen(multiboot mod[mbi->mods_count-1].mod_end = 0; --mbi->mods_count; - printk("Physical RAM map:\n"); - - /* lets find out how much memory there is */ - while (bytes < mbi->mmap_length) { - u64 end; - u64 addr; - u64 size; - - memory_map_t *map = (memory_map_t *)((ulong)mbi->mmap_addr + bytes); - addr = ((u64)map->base_addr_high << 32) | (u64)map->base_addr_low; - size = ((u64)map->length_high << 32) | (u64)map->length_low; - end = addr + size; - - printk(" %016lx - %016lx (usable)\n", addr, end); - - if (addr > eomem) { - printk("found a hole skipping remainder of memory at:\n" - " %016lx and beyond\n", addr); - break; - } - if (end > eomem) { - eomem = end; - } - bytes += map->size + 4; - } - - printk("System RAM: %luMB (%lukB)\n", eomem >> 20, eomem >> 10); - - /* top of memory */ - max_page = PFN_DOWN(ALIGN_DOWN(eomem, PAGE_SIZE)); - total_pages = max_page; - - /* Architecturally the first 4 pages are exception hendlers, we - * will also be copying down some code there */ - 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()); - - /* allow everything else to be allocated */ - init_boot_pages(xenheap_phys_end, eomem); - init_frametable(); - end_boot_allocator(); - - /* Add memory between the beginning of the heap and the beginning - * of out text */ - free_xenheap(heap_start, (ulong)_start); - freemem = ALIGN_UP((ulong)_end, PAGE_SIZE); - - for (i = 0; i < mbi->mods_count; i++) { - u32 s; - - if(mod[i].mod_end == mod[i].mod_start) - continue; - - 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"); - - free_xenheap(freemem, s); - freemem = ALIGN_UP(mod[i].mod_end, PAGE_SIZE); - - } - - /* the rest of the xenheap, starting at the end of modules */ - free_xenheap(freemem, xenheap_phys_end); - + memory_init(mod, mbi->mods_count); #ifdef OF_DEBUG printk("ofdump:\n"); /* make sure the OF devtree is good */ ofd_walk((void *)oftree, OFD_ROOT, ofd_dump_props, OFD_DUMP_ALL); #endif - - heap_size = xenheap_phys_end - heap_start; - - printk("Xen heap: %luMB (%lukB)\n", heap_size >> 20, heap_size >> 10); percpu_init_areas(); @@ -484,10 +374,10 @@ static void __init __start_xen(multiboot panic("Could not set up DOM0 guest OS\n"); } - free_xenheap(ALIGN_UP(dom0_start, PAGE_SIZE), + init_xenheap_pages(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), + init_xenheap_pages(ALIGN_UP(initrd_start, PAGE_SIZE), ALIGN_DOWN(initrd_start + initrd_len, PAGE_SIZE)); init_trace_bufs(); diff -r a8c7ece9cccb -r 980ff1125446 xen/arch/powerpc/memory.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/powerpc/memory.c Tue Aug 22 17:20:58 2006 -0400 @@ -0,0 +1,210 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright (C) IBM Corp. 2006 + * + * Authors: Dan Poff <poff@xxxxxxxxxx> + * Jimi Xenidis <jimix@xxxxxxxxxxxxxx> + */ +#include <xen/sched.h> +#include <xen/mm.h> +#include "of-devtree.h" +#include "oftree.h" + +unsigned long xenheap_phys_end; +struct membuf { + ulong start; + ulong size; +}; + +typedef void (*walk_mem_fn)(struct membuf *, uint); + +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 set_max_page(struct membuf *mb, uint entries) +{ + int i; + + for (i = 0; i < entries; i++) { + ulong end_page; + + end_page = (mb[i].start + mb[i].size) >> PAGE_SHIFT; + + if (end_page > max_page) + max_page = end_page; + } +} + +/* mark all memory from modules onward as unused, skipping hole(s), + * and returning size of hole(s) */ +static void heap_init(struct membuf *mb, uint entries) +{ + int i; + ulong start_blk; + ulong end_blk = 0; + + for (i = 0; i < entries; i++) { + start_blk = mb[i].start; + end_blk = start_blk + mb[i].size; + + if (start_blk < xenheap_phys_end) { + if (xenheap_phys_end > end_blk) { + panic("xenheap spans LMB\n"); + } + if (xenheap_phys_end == end_blk) + continue; + + start_blk = xenheap_phys_end; + } + + init_boot_pages(start_blk, end_blk); + total_pages += (end_blk - start_blk) >> PAGE_SHIFT; + } +} + +static void ofd_walk_mem(void *m, walk_mem_fn fn) +{ + ofdn_t n; + uint p_len; + struct membuf mb[8]; + static char name[] = "memory"; + + n = ofd_node_find_by_prop(m, OFD_ROOT, "device_type", name, sizeof(name)); + while (n > 0) { + + p_len = ofd_getprop(m, n, "reg", mb, sizeof (mb)); + if (p_len <= 0) { + panic("ofd_getprop(): failed\n"); + } + if (p_len > sizeof(mb)) + panic("%s: buffer is not big enuff for this firmware: " + "0x%lx < 0x%x\n", __func__, sizeof(mb), p_len); + + fn(mb, p_len / sizeof(mb[0])); + n = ofd_node_find_next(m, n); + } +} + +static void setup_xenheap(module_t *mod, int mcount) +{ + int i; + ulong freemem; + + freemem = ALIGN_UP((ulong)_end, PAGE_SIZE); + + for (i = 0; i < mcount; i++) { + u32 s; + + if(mod[i].mod_end == mod[i].mod_start) + continue; + + 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"); + + free_xenheap(freemem, s); + freemem = ALIGN_UP(mod[i].mod_end, PAGE_SIZE); + + } + + /* the rest of the xenheap, starting at the end of modules */ + free_xenheap(freemem, xenheap_phys_end); +} + +void memory_init(module_t *mod, int mcount) +{ + ulong eomem; + ulong heap_start, heap_size; + + printk("Physical RAM map:\n"); + + /* lets find out how much memory there is and set max_page */ + max_page = 0; + ofd_walk_mem((void *)oftree, set_max_page); + eomem = max_page << PAGE_SHIFT; + + if (eomem == 0){ + panic("ofd_walk_mem() failed\n"); + } + printk("End of RAM: %luMB (%lukB)\n", eomem >> 20, eomem >> 10); + + /* Architecturally the first 4 pages are exception hendlers, we + * will also be copying down some code there */ + 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()); + + /* allow everything else to be allocated */ + total_pages = 0; + ofd_walk_mem((void *)oftree, heap_init); + if (total_pages == 0) + panic("heap_init: failed"); + + if (total_pages > max_page) + panic("total_pages > max_page: 0x%lx > 0x%lx\n", + total_pages, max_page); + + printk("total_pages: 0x%016lx\n", total_pages); + + init_frametable(); + end_boot_allocator(); + + /* Add memory between the beginning of the heap and the beginning + * of out text */ + free_xenheap(heap_start, (ulong)_start); + + heap_size = xenheap_phys_end - heap_start; + printk("Xen heap: %luMB (%lukB)\n", heap_size >> 20, heap_size >> 10); + + setup_xenheap(mod, mcount); + + eomem = avail_domheap_pages(); + printk("Domheap pages: 0x%lx %luMB (%lukB)\n", eomem, + (eomem << PAGE_SHIFT) >> 20, + (eomem << PAGE_SHIFT) >> 10); +} _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |