[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN][POWERPC] Early boot memory avoidance improvemnts
# HG changeset patch # User Jimi Xenidis <jimix@xxxxxxxxxxxxxx> # Node ID 5909f57c8c399daf7d93fdef957c772f32a1a751 # Parent d6b44cb7d2c967b5ae00a6a61f4a005e7859c74e [XEN][POWERPC] Early boot memory avoidance improvemnts This patch add a simple memory allocator that can be used to: - repect our loaded image - repect firmware suggestions on "availble" memory - avoid memory we know to have issues with various different FW Also cleans up a lot of the previous logic and no longer updates the multipboot memory map since that is no longer used anyway. Signed-off-by: Jimi Xenidis <jimix@xxxxxxxxxxxxxx> Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx> --- xen/arch/powerpc/boot_of.c | 369 +++++++++++++++++++++++++++++---------------- xen/arch/powerpc/setup.c | 4 2 files changed, 243 insertions(+), 130 deletions(-) diff -r d6b44cb7d2c9 -r 5909f57c8c39 xen/arch/powerpc/boot_of.c --- a/xen/arch/powerpc/boot_of.c Tue Nov 21 15:25:02 2006 -0600 +++ b/xen/arch/powerpc/boot_of.c Wed Nov 22 14:35:09 2006 -0500 @@ -41,16 +41,27 @@ static ulong of_vec; 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); extern char builtin_cmdline[]; extern struct ns16550_defaults ns16550; #undef OF_DEBUG +#undef OF_DEBUG_LOW #ifdef OF_DEBUG #define DBG(args...) of_printf(args) #else #define DBG(args...) +#endif + +#ifdef OF_DEBUG_LOW +#define DBG_LOW(args...) of_printf(args) +#else +#define DBG_LOW(args...) #endif #define of_panic(MSG...) \ @@ -75,7 +86,6 @@ static int __init of_call( if (of_vec != 0) { va_list args; int i; - memset(&s, 0, sizeof (s)); s.ofs_service = (ulong)service; s.ofs_nargs = nargs; @@ -186,7 +196,7 @@ static int __init of_finddevice(const ch DBG("finddevice %s -> FAILURE %d\n",devspec,rets[0]); return OF_FAILURE; } - DBG("finddevice %s -> %d\n",devspec, rets[0]); + DBG_LOW("finddevice %s -> %d\n",devspec, rets[0]); return rets[0]; } @@ -197,11 +207,11 @@ static int __init of_getprop(int ph, con of_call("getprop", 4, 1, rets, ph, name, buf, buflen); if (rets[0] == OF_FAILURE) { - DBG("getprop 0x%x %s -> FAILURE\n", ph, name); + DBG_LOW("getprop 0x%x %s -> FAILURE\n", ph, name); return OF_FAILURE; } - DBG("getprop 0x%x %s -> 0x%x (%s)\n", ph, name, rets[0], (char *)buf); + DBG_LOW("getprop 0x%x %s -> 0x%x (%s)\n", ph, name, rets[0], (char *)buf); return rets[0]; } @@ -217,7 +227,7 @@ static int __init of_setprop( return OF_FAILURE; } - DBG("setprop 0x%x %s -> %s\n", ph, name, (char *)buf); + DBG_LOW("setprop 0x%x %s -> %s\n", ph, name, (char *)buf); return rets[0]; } @@ -229,7 +239,7 @@ static int __init of_getchild(int ph) int rets[1] = { OF_FAILURE }; of_call("child", 1, 1, rets, ph); - DBG("getchild 0x%x -> 0x%x\n", ph, rets[0]); + DBG_LOW("getchild 0x%x -> 0x%x\n", ph, rets[0]); return rets[0]; } @@ -242,7 +252,7 @@ static int __init of_getpeer(int ph) int rets[1] = { OF_FAILURE }; of_call("peer", 1, 1, rets, ph); - DBG("getpeer 0x%x -> 0x%x\n", ph, rets[0]); + DBG_LOW("getpeer 0x%x -> 0x%x\n", ph, rets[0]); return rets[0]; } @@ -256,7 +266,7 @@ static int __init of_getproplen(int ph, DBG("getproplen 0x%x %s -> FAILURE\n", ph, name); return OF_FAILURE; } - DBG("getproplen 0x%x %s -> 0x%x\n", ph, name, rets[0]); + DBG_LOW("getproplen 0x%x %s -> 0x%x\n", ph, name, rets[0]); return rets[0]; } @@ -269,7 +279,7 @@ static int __init of_package_to_path(int DBG("%s 0x%x -> FAILURE\n", __func__, ph); return OF_FAILURE; } - DBG("%s 0x%x %s -> 0x%x\n", __func__, ph, buffer, rets[0]); + DBG_LOW("%s 0x%x %s -> 0x%x\n", __func__, ph, buffer, rets[0]); if (rets[0] <= buflen) buffer[rets[0]] = '\0'; return rets[0]; @@ -286,7 +296,7 @@ static int __init of_nextprop(int ph, co return OF_FAILURE; } - DBG("nextprop 0x%x %s -> %s\n", ph, name, (char *)buf); + DBG_LOW("nextprop 0x%x %s -> %s\n", ph, name, (char *)buf); return rets[0]; } @@ -333,7 +343,7 @@ static int __init of_claim(u32 virt, u32 return OF_FAILURE; } - DBG("%s 0x%08x 0x%08x 0x%08x -> 0x%08x\n", __func__, virt, size, align, + DBG_LOW("%s 0x%08x 0x%08x 0x%08x -> 0x%08x\n", __func__, virt, size, align, rets[0]); return rets[0]; } @@ -355,7 +365,7 @@ static int __init of_getparent(int ph) of_call("parent", 1, 1, rets, ph); - DBG("getparent 0x%x -> 0x%x\n", ph, rets[0]); + DBG_LOW("getparent 0x%x -> 0x%x\n", ph, rets[0]); return rets[0]; } @@ -367,25 +377,196 @@ static int __init of_open(const char *de return rets[0]; } -static void boot_of_probemem(multiboot_info_t *mbi) +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++; + } + + pg = end >> PAGE_SHIFT; + } + } + + /* FW is incorrect in that the space below our image is not safe + * either */ + start = (ulong)_start >> PAGE_SHIFT; + pg = 0; + DBG("%s: marking 0x%x - 0x%lx\n", __func__, + pg << PAGE_SHIFT, start); + while (pg < start - 1) { + set_bit(pg, mem_available_pages); + ++pg; + } + + /* Now make sure we mark our own memory */ + pg = start; + 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) + 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 = 1; + while (i < bits && !test_bit(pos + i, mem_available_pages)) + ++i; + + if (i == 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; + } +} + +static ulong boot_of_mem_init(void) { int root; int p; - u32 addr_cells = 1; - u32 size_cells = 1; int rc; - int mcount = 0; - static memory_map_t mmap[16]; + 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)); + 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]; @@ -394,67 +575,52 @@ static void boot_of_probemem(multiboot_i of_getprop(p, "device_type", type, sizeof (type)); if (strncmp(type, memory, sizeof (memory)) == 0) { - u32 reg[48]; - u32 al, ah, ll, lh; + 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); } - int l = rc/sizeof(u32); /* number reg element */ + + 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) { - al = ah = ll = lh = 0; - if (addr_cells == 2) { - ah = reg[r++]; - if (r >= l) - break; /* partial line. Skip */ - al = reg[r++]; - if (r >= l) - break; /* partial line. Skip */ - } else { - al = reg[r++]; - if (r >= l) - break; /* partial line. Skip */ + 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; } - if (size_cells == 2) { - lh = reg[r++]; - if (r >= l) - break; /* partial line. Skip */ - ll = reg[r++]; - } else { - ll = reg[r++]; - } - - if ((ll != 0) || (lh != 0)) { - mmap[mcount].size = 20; /* - size field */ - mmap[mcount].type = 1; /* Regular ram */ - mmap[mcount].length_high = lh; - mmap[mcount].length_low = ll; - mmap[mcount].base_addr_high = ah; - mmap[mcount].base_addr_low = al; - of_printf("%s: memory 0x%016lx[0x%08lx]\n", - __func__, - (u64)(((u64)mmap[mcount].base_addr_high << 32) - | mmap[mcount].base_addr_low), - (u64)(((u64)mmap[mcount].length_high << 32) - | mmap[mcount].length_low)); - ++mcount; - } + + 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); - if (mcount > 0) { - mbi->flags |= MBI_MEMMAP; - mbi->mmap_length = sizeof (mmap[0]) * mcount; - mbi->mmap_addr = (ulong)mmap; - } + return 0; } static void boot_of_bootargs(multiboot_info_t *mbi) @@ -571,7 +737,7 @@ retry: } } -static int pkg_save(void *mem) +static long pkg_save(void *mem) { int root; char path[256]; @@ -587,7 +753,7 @@ static int pkg_save(void *mem) do_pkg(mem, OFD_ROOT, root, path, sizeof(path)); - r = (((ofdn_t *)mem)[1] + 1) * sizeof (u64); + r = ofd_size(mem); of_printf("%s: saved device tree in 0x%x bytes\n", __func__, r); @@ -707,56 +873,6 @@ static int boot_of_fixup_chosen(void *me return rc; } -static ulong space_base; - -/* - * 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; - - if (size == 0) - return 0; - - if (align == 0) - of_panic("cannot call %s() with align of 0\n", __func__); - -#ifdef BROKEN_CLAIM_WORKAROUND - { - static int broken_claim; - 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; - } - } -#endif - - 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); - - while ((base + size) < rma_size(cpu_default_rma_order_pages())) { - 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 * property. The values are bad, and it doesn't even have the * right number of cells. */ @@ -896,7 +1012,7 @@ static int __init boot_of_rtas(module_t if (size == 0) { of_printf("RTAS, has no size\n"); return 0; - } + } rtas_instance = of_open("/rtas"); if (rtas_instance == OF_FAILURE) { @@ -906,9 +1022,11 @@ static int __init boot_of_rtas(module_t size = ALIGN_UP(size, PAGE_SIZE); - mem = find_space(size, PAGE_SIZE, mbi); + mem = boot_of_alloc(size); if (mem == 0) of_panic("Could not allocate RTAS tree\n"); + + of_printf("instantiating RTAS at: 0x%x\n", mem); ret = of_call("call-method", 3, 2, res, "instantiate-rtas", rtas_instance, mem); @@ -933,11 +1051,11 @@ static void * __init boot_of_devtree(mod ulong oft_sz = 48 * PAGE_SIZE; /* snapshot the tree */ - oft = (void*)find_space(oft_sz, PAGE_SIZE, mbi); - if (oft == 0) + oft = (void *)boot_of_alloc(oft_sz); + if (oft == NULL) of_panic("Could not allocate OFD tree\n"); - of_printf("creating oftree\n"); + of_printf("creating oftree at: 0x%p\n", oft); of_test("package-to-path"); oft = ofd_create(oft, oft_sz); pkg_save(oft); @@ -1014,8 +1132,6 @@ static void * __init boot_of_module(ulon of_printf("mod0: %o %c %c %c\n", c[0], c[1], c[2], c[3]); } - space_base = (ulong)_end; - mod = 0; mods[mod].mod_start = mod0_start; mods[mod].mod_end = mod0_start + mod0_size; @@ -1036,6 +1152,7 @@ static void * __init boot_of_module(ulon ++mod; oft = boot_of_devtree(&mods[mod], mbi); + of_printf("hello\n"); if (oft == NULL) of_panic("%s: boot_of_devtree failed\n", __func__); @@ -1192,14 +1309,14 @@ multiboot_info_t __init *boot_of_init( r3, r4, vec, r6, r7, orig_msr); if ((vec >= (ulong)_start) && (vec <= (ulong)_end)) { - of_printf("Hmm.. OF[0x%lx] seems to have stepped on our image " - "that ranges: %p .. %p.\n HANG!\n", + of_panic("Hmm.. OF[0x%lx] seems to have stepped on our image " + "that ranges: %p .. %p.\n", vec, _start, _end); } of_printf("%s: _start %p _end %p 0x%lx\n", __func__, _start, _end, r6); boot_of_fix_maple(); - boot_of_probemem(&mbi); + boot_of_mem_init(); boot_of_bootargs(&mbi); oft = boot_of_module(r3, r4, &mbi); boot_of_cpus(); diff -r d6b44cb7d2c9 -r 5909f57c8c39 xen/arch/powerpc/setup.c --- a/xen/arch/powerpc/setup.c Tue Nov 21 15:25:02 2006 -0600 +++ b/xen/arch/powerpc/setup.c Wed Nov 22 14:35:09 2006 -0500 @@ -301,10 +301,6 @@ static void __init __start_xen(multiboot panic("FATAL ERROR: Require at least one Multiboot module.\n"); } - if (!(mbi->flags & MBI_MEMMAP)) { - panic("FATAL ERROR: Bootloader provided no memory information.\n"); - } - /* OF dev tree is the last module */ oftree = mod[mbi->mods_count-1].mod_start; oftree_end = mod[mbi->mods_count-1].mod_end; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |