From: Rusty Russell finish_device_tree simply allocates nodes by incrementing klimit (ie. using memory on top of the kernel). Change it to figure out how much memory it needs, then use lmb_alloc to allocate that, then fill it in. This gets rid of the only manipulation of klimit after prom_init. --- 25-akpm/arch/ppc64/kernel/btext.c | 2 25-akpm/arch/ppc64/kernel/prom.c | 79 +++++++++++++++++++++----------------- 2 files changed, 45 insertions(+), 36 deletions(-) diff -puN arch/ppc64/kernel/btext.c~ppc64-make-finish_device_tree-use-lmb_alloc-not-klimit arch/ppc64/kernel/btext.c --- 25/arch/ppc64/kernel/btext.c~ppc64-make-finish_device_tree-use-lmb_alloc-not-klimit Fri Apr 23 13:30:15 2004 +++ 25-akpm/arch/ppc64/kernel/btext.c Fri Apr 23 13:30:15 2004 @@ -47,8 +47,6 @@ int force_printk_to_btext = 0; boot_infos_t disp_bi; -extern char *klimit; - /* This function will enable the early boot text when doing OF booting. This * way, xmon output should work too */ diff -puN arch/ppc64/kernel/prom.c~ppc64-make-finish_device_tree-use-lmb_alloc-not-klimit arch/ppc64/kernel/prom.c --- 25/arch/ppc64/kernel/prom.c~ppc64-make-finish_device_tree-use-lmb_alloc-not-klimit Fri Apr 23 13:30:15 2004 +++ 25-akpm/arch/ppc64/kernel/prom.c Fri Apr 23 13:30:15 2004 @@ -123,7 +123,7 @@ struct pci_intr_map { typedef unsigned long interpret_func(struct device_node *, unsigned long, - int, int); + int, int, int); #ifndef FB_MAX /* avoid pulling in all of the fb stuff */ #define FB_MAX 8 @@ -2064,7 +2064,8 @@ map_interrupt(unsigned int **irq, struct } static unsigned long __init -finish_node_interrupts(struct device_node *np, unsigned long mem_start) +finish_node_interrupts(struct device_node *np, unsigned long mem_start, + int measure_only) { unsigned int *ints; int intlen, intrcells; @@ -2081,6 +2082,9 @@ finish_node_interrupts(struct device_nod np->intrs = (struct interrupt_info *) mem_start; mem_start += intlen * sizeof(struct interrupt_info); + if (measure_only) + return mem_start; + for (i = 0; i < intlen; ++i) { np->intrs[i].line = 0; np->intrs[i].sense = 1; @@ -2117,7 +2121,7 @@ finish_node_interrupts(struct device_nod static unsigned long __init interpret_pci_props(struct device_node *np, unsigned long mem_start, - int naddrc, int nsizec) + int naddrc, int nsizec, int measure_only) { struct address_range *adr; struct pci_reg_property *pci_addrs; @@ -2129,9 +2133,11 @@ interpret_pci_props(struct device_node * i = 0; adr = (struct address_range *) mem_start; while ((l -= sizeof(struct pci_reg_property)) >= 0) { - adr[i].space = pci_addrs[i].addr.a_hi; - adr[i].address = pci_addrs[i].addr.a_lo; - adr[i].size = pci_addrs[i].size_lo; + if (!measure_only) { + adr[i].space = pci_addrs[i].addr.a_hi; + adr[i].address = pci_addrs[i].addr.a_lo; + adr[i].size = pci_addrs[i].size_lo; + } ++i; } np->addrs = adr; @@ -2143,7 +2149,7 @@ interpret_pci_props(struct device_node * static unsigned long __init interpret_dbdma_props(struct device_node *np, unsigned long mem_start, - int naddrc, int nsizec) + int naddrc, int nsizec, int measure_only) { struct reg_property32 *rp; struct address_range *adr; @@ -2164,9 +2170,11 @@ interpret_dbdma_props(struct device_node i = 0; adr = (struct address_range *) mem_start; while ((l -= sizeof(struct reg_property32)) >= 0) { - adr[i].space = 2; - adr[i].address = rp[i].address + base_address; - adr[i].size = rp[i].size; + if (!measure_only) { + adr[i].space = 2; + adr[i].address = rp[i].address + base_address; + adr[i].size = rp[i].size; + } ++i; } np->addrs = adr; @@ -2179,7 +2187,7 @@ interpret_dbdma_props(struct device_node static unsigned long __init interpret_macio_props(struct device_node *np, unsigned long mem_start, - int naddrc, int nsizec) + int naddrc, int nsizec, int measure_only) { struct reg_property32 *rp; struct address_range *adr; @@ -2200,9 +2208,11 @@ interpret_macio_props(struct device_node i = 0; adr = (struct address_range *) mem_start; while ((l -= sizeof(struct reg_property32)) >= 0) { - adr[i].space = 2; - adr[i].address = rp[i].address + base_address; - adr[i].size = rp[i].size; + if (!measure_only) { + adr[i].space = 2; + adr[i].address = rp[i].address + base_address; + adr[i].size = rp[i].size; + } ++i; } np->addrs = adr; @@ -2215,7 +2225,7 @@ interpret_macio_props(struct device_node static unsigned long __init interpret_isa_props(struct device_node *np, unsigned long mem_start, - int naddrc, int nsizec) + int naddrc, int nsizec, int measure_only) { struct isa_reg_property *rp; struct address_range *adr; @@ -2226,9 +2236,11 @@ interpret_isa_props(struct device_node * i = 0; adr = (struct address_range *) mem_start; while ((l -= sizeof(struct reg_property)) >= 0) { - adr[i].space = rp[i].space; - adr[i].address = rp[i].address; - adr[i].size = rp[i].size; + if (!measure_only) { + adr[i].space = rp[i].space; + adr[i].address = rp[i].address; + adr[i].size = rp[i].size; + } ++i; } np->addrs = adr; @@ -2241,7 +2253,7 @@ interpret_isa_props(struct device_node * static unsigned long __init interpret_root_props(struct device_node *np, unsigned long mem_start, - int naddrc, int nsizec) + int naddrc, int nsizec, int measure_only) { struct address_range *adr; int i, l; @@ -2253,9 +2265,11 @@ interpret_root_props(struct device_node i = 0; adr = (struct address_range *) mem_start; while ((l -= rpsize) >= 0) { - adr[i].space = 0; - adr[i].address = rp[naddrc - 1]; - adr[i].size = rp[naddrc + nsizec - 1]; + if (!measure_only) { + adr[i].space = 0; + adr[i].address = rp[naddrc - 1]; + adr[i].size = rp[naddrc + nsizec - 1]; + } ++i; rp += naddrc + nsizec; } @@ -2269,7 +2283,7 @@ interpret_root_props(struct device_node static unsigned long __init finish_node(struct device_node *np, unsigned long mem_start, - interpret_func *ifunc, int naddrc, int nsizec) + interpret_func *ifunc, int naddrc, int nsizec, int measure_only) { struct device_node *child; int *ip; @@ -2284,9 +2298,9 @@ finish_node(struct device_node *np, unsi /* get the device addresses and interrupts */ if (ifunc != NULL) - mem_start = ifunc(np, mem_start, naddrc, nsizec); + mem_start = ifunc(np, mem_start, naddrc, nsizec, measure_only); - mem_start = finish_node_interrupts(np, mem_start); + mem_start = finish_node_interrupts(np, mem_start, measure_only); /* Look for #address-cells and #size-cells properties. */ ip = (int *) get_property(np, "#address-cells", 0); @@ -2324,7 +2338,7 @@ finish_node(struct device_node *np, unsi for (child = np->child; child != NULL; child = child->sibling) mem_start = finish_node(child, mem_start, ifunc, - naddrc, nsizec); + naddrc, nsizec, measure_only); return mem_start; } @@ -2342,14 +2356,11 @@ finish_device_tree(void) virt_irq_init(); - mem = finish_node(allnodes, mem, NULL, 0, 0); - dev_tree_size = mem - (unsigned long) allnodes; - - mem = _ALIGN(mem, PAGE_SIZE); - lmb_reserve(__pa(klimit), mem-klimit); - - klimit = mem; - + dev_tree_size = finish_node(allnodes, 0, NULL, 0, 0, 1); + mem = (long)abs_to_virt(lmb_alloc(dev_tree_size, + __alignof__(struct device_node))); + if (finish_node(allnodes, mem, NULL, 0, 0, 0) != mem + dev_tree_size) + BUG(); rtas.dev = of_find_node_by_name(NULL, "rtas"); } _