[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [XenPPC] [PATCH] Move lots of memory logic earlier
# HG changeset patch # User Hollis Blanchard <hollisb@xxxxxxxxxx> # Date 1168293789 21600 # Node ID e1ee8b26c15de7afd7dec2d604b00d607e1307f4 # Parent dbc74db14a4b39d359365fcf8257216d968fa269 Move lots of memory logic earlier. - We now require the common boot allocator has been initialized before __start_xen(), and we use that in boot_of.c instead of managing our own. Removing our custom allocator is important to simplify the upcoming multiboot2 conversion. - We also handle arbitrary-sized properties now, instead of probably-large-enough fixed-sized buffers. - This will also be needed to support non-Open Firmware systems (though the firmware-specific interface was not the focus of this patch). Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx> diff -r dbc74db14a4b -r e1ee8b26c15d xen/arch/powerpc/boot_of.c --- a/xen/arch/powerpc/boot_of.c Tue Dec 12 14:35:07 2006 -0600 +++ b/xen/arch/powerpc/boot_of.c Mon Jan 08 16:03:09 2007 -0600 @@ -13,13 +13,14 @@ * 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. 2005, 2006 + * Copyright IBM Corp. 2005, 2006, 2007 * * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx> * Hollis Blanchard <hollisb@xxxxxxxxxx> */ #include <xen/config.h> +#include <alloca.h> #include <xen/init.h> #include <xen/lib.h> #include <xen/multiboot.h> @@ -35,19 +36,32 @@ #include "oftree.h" #include "rtas.h" +typedef ulong (*of_walk_fn)(int node, void *arg); + /* Secondary processors use this for handshaking with main processor. */ volatile unsigned int __spin_ack; static ulong of_vec; static ulong of_msr; static int of_out; -static ulong eomem; - -#define MEM_AVAILABLE_PAGES ((32 << 20) >> PAGE_SHIFT) -static DECLARE_BITMAP(mem_available_pages, MEM_AVAILABLE_PAGES); +static uint addr_cells; +static uint size_cells; + +ulong xenheap_size; +ulong xenheap_phys_end; extern char builtin_cmdline[]; extern struct ns16550_defaults ns16550; + +extern ulong nr_pages; +extern ulong bitmap_addr; + +/* + * opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the + * page_info table and allocation bitmap. + */ +static unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB; +integer_param("xenheap_megabytes", opt_xenheap_megabytes); #undef OF_DEBUG #undef OF_DEBUG_LOW @@ -72,6 +86,11 @@ struct of_service { u32 ofs_nargs; u32 ofs_nrets; u32 ofs_args[10]; +}; + +struct membuf { + ulong start; + ulong size; }; static int bof_chosen; @@ -377,234 +396,204 @@ static int __init of_open(const char *de return rets[0]; } -static void boot_of_alloc_init(int m, uint addr_cells, uint size_cells) -{ - int rc; - uint pg; - uint a[64]; - int tst; - u64 start; - u64 size; - - rc = of_getprop(m, "available", a, sizeof (a)); - if (rc > 0) { - int l = rc / sizeof(a[0]); - int r = 0; - -#ifdef OF_DEBUG - { - int i; - of_printf("avail:\n"); - for (i = 0; i < l; i += 4) - of_printf(" 0x%x%x, 0x%x%x\n", - a[i], a[i + 1], - a[i + 2] ,a[i + 3]); - } -#endif - - pg = 0; - while (pg < MEM_AVAILABLE_PAGES && r < l) { - ulong end; - - start = a[r++]; - if (addr_cells == 2 && (r < l) ) - start = (start << 32) | a[r++]; - - size = a[r++]; - if (size_cells == 2 && (r < l) ) - size = (size << 32) | a[r++]; - - end = ALIGN_DOWN(start + size, PAGE_SIZE); - - start = ALIGN_UP(start, PAGE_SIZE); - - DBG("%s: marking 0x%x - 0x%lx\n", __func__, - pg << PAGE_SHIFT, start); - - start >>= PAGE_SHIFT; - while (pg < MEM_AVAILABLE_PAGES && pg < start) { - set_bit(pg, mem_available_pages); - pg++; + +static ulong boot_of_alloc(ulong size) +{ + return alloc_boot_pages(size >> PAGE_SHIFT, 1) << PAGE_SHIFT; +} + +static ulong of_walk_type(int root, const char *type, of_walk_fn fn, void *arg) +{ + int child; + ulong rc; + + child = of_getchild(root); + while (child > 0) { + int proplen; + char *propval; + + proplen = of_getprop(child, "device_type", NULL, 0); + if (proplen > 0) { + propval = alloca(proplen); + proplen = of_getprop(child, "device_type", propval, proplen); + if (!strcmp(propval, type)) { + /* if the type matches, call the callback */ + rc = fn(child, arg); + if (rc) + return rc; } - - pg = end >> PAGE_SHIFT; - } - } - - /* Now make sure we mark our own memory */ - pg = (ulong)_start >> PAGE_SHIFT; - start = (ulong)_end >> PAGE_SHIFT; - - DBG("%s: marking 0x%x - 0x%lx\n", __func__, - pg << PAGE_SHIFT, start << PAGE_SHIFT); - - /* Lets try and detect if our image has stepped on something. It - * is possible that FW has already subtracted our image from - * available memory so we must make sure that the previous bits - * are the same for the whole image */ - tst = test_and_set_bit(pg, mem_available_pages); - ++pg; - while (pg <= start) { - if (test_and_set_bit(pg, mem_available_pages) != tst) - of_panic("%s: pg :0x%x of our image is different\n", - __func__, pg); - ++pg; - } - - DBG("%s: marking 0x%x - 0x%x\n", __func__, - 0 << PAGE_SHIFT, 3 << PAGE_SHIFT); - /* First for pages (where the vectors are) should be left alone as well */ - set_bit(0, mem_available_pages); - set_bit(1, mem_available_pages); - set_bit(2, mem_available_pages); - set_bit(3, mem_available_pages); -} - -#ifdef BOOT_OF_FREE -/* this is here in case we ever need a free call at a later date */ -static void boot_of_free(ulong addr, ulong size) -{ - ulong bits; - ulong pos; - ulong i; - - size = ALIGN_UP(size, PAGE_SIZE); - bits = size >> PAGE_SHIFT; - pos = addr >> PAGE_SHIFT; - - for (i = 0; i < bits; i++) { - if (!test_and_clear_bit(pos + i, mem_available_pages)) - of_panic("%s: pg :0x%lx was never allocated\n", - __func__, pos + i); - } -} -#endif - -static ulong boot_of_alloc(ulong size) -{ - ulong bits; - ulong pos; - - if (size == 0) + } + + /* recurse */ + rc = of_walk_type(child, type, fn, arg); + if (rc) + return rc; + + child = of_getpeer(child); + } + return 0; +} + +/* Initialise boot-time allocator with all RAM after the Xen heap. */ +static ulong mem_mark_free(int memnode, void *arg) +{ + static ulong skipped; + uint32_t *reg; + int proplen; + int nr_cells; + int i = 0; + + proplen = of_getprop(memnode, "available", NULL, 0); + if (proplen <= 0) return 0; - DBG("%s(0x%lx)\n", __func__, size); - - size = ALIGN_UP(size, PAGE_SIZE); - bits = size >> PAGE_SHIFT; - pos = 0; - for (;;) { - ulong i; - - pos = find_next_zero_bit(mem_available_pages, - MEM_AVAILABLE_PAGES, pos); - DBG("%s: found start bit at: 0x%lx\n", __func__, pos); - - /* found nothing */ - if ((pos + bits) > MEM_AVAILABLE_PAGES) { - of_printf("%s: allocation of size: 0x%lx failed\n", - __func__, size); - return 0; - } - - /* find a set that fits */ - DBG("%s: checking for 0x%lx bits: 0x%lx\n", __func__, bits, pos); - - i = find_next_bit(mem_available_pages, MEM_AVAILABLE_PAGES, pos); - if (i - pos >= bits) { - uint addr = pos << PAGE_SHIFT; - - /* make sure OF is happy with our choice */ - if (of_claim(addr, size, 0) != OF_FAILURE) { - for (i = 0; i < bits; i++) - set_bit(pos + i, mem_available_pages); - - DBG("%s: 0x%lx is good returning 0x%x\n", - __func__, pos, addr); - return addr; - } - /* if OF did not like the address then simply start from - * the next bit */ - i = 1; - } - - pos = pos + i; - } + reg = alloca(proplen); + proplen = of_getprop(memnode, "available", reg, proplen); + nr_cells = proplen / sizeof(uint32_t); + + while (i < nr_cells) { + struct membuf mb; + ulong start; + ulong chunk; + ulong size; + + /* decode start and size */ + mb.start = reg[i++]; + if (addr_cells == 2 && (i < nr_cells) ) + mb.start = (mb.start << 32) | reg[i++]; + mb.size = reg[i++]; + if (size_cells == 2 && (i < nr_cells) ) + mb.size = (mb.size << 32) | reg[i++]; + + start = mb.start; + size = mb.size; + + chunk = min(xenheap_size - skipped, size); + start += chunk; + size -= chunk; + skipped += chunk; + + if (size) { + if (skipped == xenheap_size && xenheap_phys_end == 0) + xenheap_phys_end = start; + of_printf(" %016lx: %016lx\n", start, size); + init_boot_pages(start, start + size); + } + } + return 0; +} + +/* find space in a memory node */ +static ulong mem_find_space(int memnode, void *arg) +{ + ulong size = (ulong)arg; + uint32_t *reg; + int proplen; + int nr_cells; + int i = 0; + + proplen = of_getprop(memnode, "available", NULL, 0); + if (proplen <= 0) + return 0; + + reg = alloca(proplen); + proplen = of_getprop(memnode, "available", reg, proplen); + nr_cells = proplen / sizeof(uint32_t); + + while (i < nr_cells) { + struct membuf mb; + + /* decode start and size */ + mb.start = reg[i++]; + if (addr_cells == 2 && (i < nr_cells) ) + mb.start = (mb.start << 32) | reg[i++]; + mb.size = reg[i++]; + if (size_cells == 2 && (i < nr_cells) ) + mb.size = (mb.size << 32) | reg[i++]; + + of_printf(" %016lx: %016lx", mb.start, mb.size); + if (mb.size > size) { + of_printf(" -- found\n"); + return mb.start; + } + of_printf("\n"); + } + return 0; +} + +/* set @nr_pages and @max_page based on the device tree */ +static ulong mem_count_pages(int memnode, void *arg) +{ + uint32_t *reg; + int proplen; + int nr_cells; + int i = 0; + + proplen = of_getprop(memnode, "reg", NULL, 0); + if (proplen <= 0) + return 0; + + reg = alloca(proplen); + proplen = of_getprop(memnode, "reg", reg, proplen); + nr_cells = proplen / sizeof(uint32_t); + + while (i < nr_cells) { + struct membuf mb; + ulong end_page; + + /* decode start and size */ + mb.start = reg[i++]; + if (addr_cells == 2 && (i < nr_cells) ) + mb.start = (mb.start << 32) | reg[i++]; + mb.size = reg[i++]; + if (size_cells == 2 && (i < nr_cells) ) + mb.size = (mb.size << 32) | reg[i++]; + + of_printf(" %016lx: %016lx\n", mb.start, mb.size); + + nr_pages += mb.size >> PAGE_SHIFT; + + end_page = (mb.start + mb.size) >> PAGE_SHIFT; + if (end_page > max_page) + max_page = end_page; + } + return 0; } static ulong boot_of_mem_init(void) { + ulong bitmap_size; int root; - int p; - int rc; - uint addr_cells; - uint size_cells; root = of_finddevice("/"); - p = of_getchild(root); - - /* code is writen to assume sizes of 1 */ - of_getprop(root, "#address-cells", &addr_cells, - sizeof (addr_cells)); - of_getprop(root, "#size-cells", &size_cells, - sizeof (size_cells)); - DBG("%s: address_cells=%d size_cells=%d\n", - __func__, addr_cells, size_cells); - - /* We do ream memory discovery later, for now we only want to find - * the first LMB */ - do { - const char memory[] = "memory"; - char type[32]; - - type[0] = '\0'; - - of_getprop(p, "device_type", type, sizeof (type)); - if (strncmp(type, memory, sizeof (memory)) == 0) { - uint reg[48]; - u64 start; - u64 size; - int r; - int l; - - rc = of_getprop(p, "reg", reg, sizeof (reg)); - if (rc == OF_FAILURE) { - of_panic("no reg property for memory node: 0x%x.\n", p); - } - - l = rc / sizeof(reg[0]); /* number reg element */ - DBG("%s: number of bytes in property 'reg' %d\n", - __func__, rc); - - r = 0; - while (r < l) { - start = reg[r++]; - if (addr_cells == 2 && (r < l) ) - start = (start << 32) | reg[r++]; - - if (r >= l) - break; /* partial line. Skip */ - - if (start > 0) { - /* this is not the first LMB so we skip it */ - break; - } - - size = reg[r++]; - if (size_cells == 2 && (r < l) ) - size = (size << 32) | reg[r++]; - - if (r > l) - break; /* partial line. Skip */ - - boot_of_alloc_init(p, addr_cells, size_cells); - - eomem = size; - return size; - } - } - p = of_getpeer(p); - } while (p != OF_FAILURE && p != 0); + of_getprop(root, "#address-cells", &addr_cells, sizeof(addr_cells)); + of_getprop(root, "#size-cells", &size_cells, sizeof(size_cells)); + + of_printf("Physical RAM map:\n"); + of_walk_type(root, "memory", mem_count_pages, 0); + of_printf("max_page: 0x%lx\n", max_page); + of_printf("nr_pages: 0x%lx\n", nr_pages); + of_printf("Total memory: %lu KiB\n", nr_pages << PAGE_SHIFT >> 10); + + /* install the boot allocator bitmap */ + bitmap_size = max_page / 8; + of_printf("searching for 0x%lx bytes for bitmap:\n", bitmap_size); + bitmap_addr = of_walk_type(root, "memory", mem_find_space, + (void *)bitmap_size); + if (bitmap_addr == 0) + of_panic("couldn't find space for allocator bitmap"); + if (of_claim(bitmap_addr, bitmap_size, 0) == OF_FAILURE) + of_panic("couldn't claim allocator bitmap at 0x%lx[0x%lx]\n", + bitmap_addr, bitmap_size); + init_boot_allocator(bitmap_addr); + + xenheap_size = opt_xenheap_megabytes << 20; + /* need room to allocate HTABs from the xen heap. */ + xenheap_size += nr_pages << PAGE_SHIFT >> 5; + of_printf("Xen heap: %lu KiB\n", xenheap_size >> 10); + + of_printf("marking unused memory:\n"); + of_walk_type(root, "memory", mem_mark_free, 0); return 0; } @@ -1283,7 +1272,6 @@ multiboot_info_t __init *boot_of_init( { static multiboot_info_t mbi; void *oft; - int r; of_vec = vec; of_msr = orig_msr; @@ -1310,9 +1298,7 @@ multiboot_info_t __init *boot_of_init( of_printf("%s: _start %p _end %p 0x%lx\n", __func__, _start, _end, r6); boot_of_fix_maple(); - r = boot_of_mem_init(); - if (r == 0) - of_panic("failure to initialize memory allocator"); + boot_of_mem_init(); boot_of_bootargs(&mbi); oft = boot_of_module(r3, r4, &mbi); boot_of_cpus(); diff -r dbc74db14a4b -r e1ee8b26c15d xen/arch/powerpc/memory.c --- a/xen/arch/powerpc/memory.c Tue Dec 12 14:35:07 2006 -0600 +++ b/xen/arch/powerpc/memory.c Mon Jan 08 16:03:09 2007 -0600 @@ -13,7 +13,7 @@ * 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 + * Copyright IBM Corp. 2006, 2007 * * Authors: Dan Poff <poff@xxxxxxxxxx> * Jimi Xenidis <jimix@xxxxxxxxxxxxxx> @@ -32,18 +32,13 @@ #define DBG(fmt...) #endif -/* - * opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the - * page_info table and allocation bitmap. - */ -static unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB; -integer_param("xenheap_megabytes", opt_xenheap_megabytes); +ulong bitmap_addr; +ulong nr_pages; -unsigned long xenheap_phys_end; -static uint nr_pages; -static ulong xenheap_size; static ulong save_start; static ulong save_end; + +extern ulong xenheap_size; struct membuf { ulong start; @@ -74,71 +69,6 @@ static ulong free_xenheap(ulong start, u } 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; - - printk(" %016lx: %016lx\n", mb[i].start, mb[i].size); - nr_pages += mb[i].size >> PAGE_SHIFT; - - 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 */ -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) @@ -176,22 +106,10 @@ static void setup_xenheap(module_t *mod, void memory_init(module_t *mod, int mcount) { - ulong eomem; - ulong heap_start; - ulong xh_pages; - - /* lets find out how much memory there is and set max_page */ - max_page = 0; - printk("Physical RAM map:\n"); - ofd_walk_mem((void *)oftree, set_max_page); - eomem = max_page << PAGE_SHIFT; - - if (eomem == 0){ - panic("ofd_walk_mem() failed\n"); - } + ulong domheap; /* find the portion of memory we need to keep safe */ - save_start = oftree; + save_start = bitmap_addr; save_end = oftree_end; if (rtas_base) { if (save_start > rtas_base) @@ -199,44 +117,6 @@ void memory_init(module_t *mod, int mcou if (save_end < rtas_end) save_end = rtas_end; } - - /* minimum heap has to reach to the end of all Xen required memory */ - xh_pages = ALIGN_UP(save_end, PAGE_SIZE) >> PAGE_SHIFT; - xh_pages += opt_xenheap_megabytes << (20 - PAGE_SHIFT); - - /* While we are allocating HTABS from The Xen Heap we need it to - * be larger */ - xh_pages += nr_pages >> 5; - - xenheap_phys_end = xh_pages << PAGE_SHIFT; - printk("End of Xen Area: %luMiB (%luKiB)\n", - xenheap_phys_end >> 20, xenheap_phys_end >> 10); - - printk("End of RAM: %luMiB (%luKiB)\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); - } - - /* 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); - - DBG("total_pages: 0x%016lx\n", total_pages); init_frametable(); @@ -246,13 +126,11 @@ void memory_init(module_t *mod, int mcou /* Add memory between the beginning of the heap and the beginning * of our text */ - free_xenheap(heap_start, (ulong)_start); + free_xenheap(bitmap_addr, (ulong)_start); setup_xenheap(mod, mcount); - printk("Xen Heap: %luMiB (%luKiB)\n", - xenheap_size >> 20, xenheap_size >> 10); - eomem = avail_domheap_pages(); + domheap = avail_domheap_pages(); printk("Dom Heap: %luMiB (%luKiB)\n", - (eomem << PAGE_SHIFT) >> 20, - (eomem << PAGE_SHIFT) >> 10); + (domheap << PAGE_SHIFT) >> 20, + (domheap << PAGE_SHIFT) >> 10); } _______________________________________________ Xen-ppc-devel mailing list Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-ppc-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |