# 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
|