

* create boot_abs_to_virt() and boot_virt_to_abs() to use __boot_pa()
  and __boot_va() for early boot code.

* change a lot of code to use __boot variants in early boot.  nonlinear
  won't work when relocation is on anyway

* switch rtas_call() and create_pte_mapping() to use __boot or nonlinear
  variants based on system_state variable

* compute first page on the node in show_mem() with pfn_to_page(), not
  node_mem_map


Signed-off-by: Dave Hansen <haveblue@us.ibm.com>


---

 memhotplug-dave/arch/ppc64/kernel/prom.c           |   20 ++++++++--------
 memhotplug-dave/arch/ppc64/kernel/rtas.c           |   25 ++++++++++++---------
 memhotplug-dave/arch/ppc64/kernel/smp.c            |    5 ++--
 memhotplug-dave/arch/ppc64/mm/hash_utils.c         |   15 ++++++++----
 memhotplug-dave/arch/ppc64/mm/init.c               |   21 +++++++++++------
 memhotplug-dave/include/asm-ppc64/abs_addr.h       |    6 +++--
 memhotplug-dave/include/asm-ppc64/memory_hotplug.h |   10 ++++++++
 memhotplug-dave/include/asm-ppc64/nonlinear.h      |    8 ++++++
 memhotplug-dave/include/asm-ppc64/page.h           |   19 +++++++++++----
 mm/page_alloc.c                                    |    0 
 10 files changed, 88 insertions(+), 41 deletions(-)

diff -puN arch/ppc64/Kconfig~H-nonlinear-ppc64-daveh arch/ppc64/Kconfig
diff -puN arch/ppc64/kernel/prom.c~H-nonlinear-ppc64-daveh arch/ppc64/kernel/prom.c
--- memhotplug/arch/ppc64/kernel/prom.c~H-nonlinear-ppc64-daveh	Thu Aug  5 09:41:13 2004
+++ memhotplug-dave/arch/ppc64/kernel/prom.c	Thu Aug  5 09:41:13 2004
@@ -826,7 +826,7 @@ static void __init prom_initialize_tce_t
 			prom_panic("ERROR, cannot find space for TCE table.\n");
 		}
 
-		vbase = (unsigned long)abs_to_virt(base);
+		vbase = (unsigned long)boot_abs_to_virt(base);
 
 		/* Save away the TCE table attributes for later use. */
 		prom_tce_table[table].node = node;
@@ -913,11 +913,11 @@ static void __init prom_hold_cpus(unsign
 	extern unsigned long __secondary_hold_spinloop;
 	extern unsigned long __secondary_hold_acknowledge;
 	unsigned long *spinloop
-		= (void *)virt_to_abs(&__secondary_hold_spinloop);
+		= (void *)boot_virt_to_abs(&__secondary_hold_spinloop);
 	unsigned long *acknowledge
-		= (void *)virt_to_abs(&__secondary_hold_acknowledge);
+		= (void *)boot_virt_to_abs(&__secondary_hold_acknowledge);
 	unsigned long secondary_hold
-		= virt_to_abs(*PTRRELOC((unsigned long *)__secondary_hold));
+		= boot_virt_to_abs(*PTRRELOC((unsigned long *)__secondary_hold));
 	struct systemcfg *_systemcfg = RELOC(systemcfg);
 	struct paca_struct *lpaca = PTRRELOC(&paca[0]);
 	struct prom_t *_prom = PTRRELOC(&prom);
@@ -1699,7 +1699,7 @@ prom_init(unsigned long r3, unsigned lon
 	 */
 #ifdef CONFIG_BLK_DEV_INITRD
 	if ( _prom->bi_recs == NULL && r3 && r4 && r4 != 0xdeadbeef) {
-		RELOC(initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3;
+		RELOC(initrd_start) = (r3 >= KERNELBASE) ? __boot_pa(r3) : r3;
 		RELOC(initrd_end) = RELOC(initrd_start) + r4;
 		RELOC(initrd_below_start_ok) = 1;
 	}
@@ -1799,7 +1799,7 @@ prom_init(unsigned long r3, unsigned lon
 	prom_debug("klimit=0x%x\n", RELOC(klimit));
 	prom_debug(" ->mem=0x%x\n", mem);
 
-	lmb_reserve(0, __pa(RELOC(klimit)));
+	lmb_reserve(0, __boot_pa(RELOC(klimit)));
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (RELOC(initrd_start)) {
@@ -1807,7 +1807,7 @@ prom_init(unsigned long r3, unsigned lon
 		initrd_len = RELOC(initrd_end) - RELOC(initrd_start);
 
 		/* Move initrd if it's where we're going to copy kernel. */
-		if (RELOC(initrd_start) < __pa(RELOC(klimit))) {
+		if (RELOC(initrd_start) < __boot_pa(RELOC(klimit))) {
 			memmove((void *)mem, (void *)RELOC(initrd_start),
 				initrd_len);
 			RELOC(initrd_start) = mem;
@@ -1840,8 +1840,8 @@ prom_init(unsigned long r3, unsigned lon
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* If we had an initrd, we convert its address to virtual */
 	if (RELOC(initrd_start)) {
-		RELOC(initrd_start) = (unsigned long)__va(RELOC(initrd_start));
-		RELOC(initrd_end) = (unsigned long)__va(RELOC(initrd_end));
+		RELOC(initrd_start) = (unsigned long)__boot_va(RELOC(initrd_start));
+		RELOC(initrd_end) = (unsigned long)__boot_va(RELOC(initrd_end));
 	}
 #endif /* CONFIG_BLK_DEV_INITRD */
 
@@ -2309,7 +2309,7 @@ finish_device_tree(void)
 	virt_irq_init();
 
 	dev_tree_size = finish_node(allnodes, 0, NULL, 0, 0, 1);
-	mem = (long)abs_to_virt(lmb_alloc(dev_tree_size,
+	mem = (long)boot_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();
diff -puN arch/ppc64/kernel/rtas.c~H-nonlinear-ppc64-daveh arch/ppc64/kernel/rtas.c
--- memhotplug/arch/ppc64/kernel/rtas.c~H-nonlinear-ppc64-daveh	Thu Aug  5 09:41:13 2004
+++ memhotplug-dave/arch/ppc64/kernel/rtas.c	Thu Aug  5 09:41:13 2004
@@ -56,7 +56,7 @@ call_rtas_display_status(char c)
 	args->rets  = (rtas_arg_t *)&(args->args[1]);
 	args->args[0] = (int)c;
 
-	enter_rtas(__pa(args));
+	enter_rtas(virt_to_phys(args));
 
 	spin_unlock_irqrestore(&rtas.lock, s);
 }
@@ -90,7 +90,7 @@ __fetch_rtas_last_error(void)
 	err_args.nret = 1;
 	err_args.rets = (rtas_arg_t *)&(err_args.args[2]);
 
-	err_args.args[0] = (rtas_arg_t)__pa(rtas_err_buf);
+	err_args.args[0] = (rtas_arg_t)virt_to_phys(rtas_err_buf);
 	err_args.args[1] = RTAS_ERROR_LOG_MAX;
 	err_args.args[2] = 0;
 
@@ -99,7 +99,7 @@ __fetch_rtas_last_error(void)
 
 	PPCDBG(PPCDBG_RTAS, "\tentering rtas with 0x%lx\n",
 	       __pa(&err_args));
-	enter_rtas(__pa(&rtas.args));
+	enter_rtas(virt_to_phys(&rtas.args));
 	PPCDBG(PPCDBG_RTAS, "\treturned from rtas ...\n");
 
 	err_args = rtas.args;
@@ -116,6 +116,7 @@ int rtas_call(int token, int nargs, int 
 	struct rtas_args *rtas_args;
 	char * buff_copy = NULL;
 	int ret;
+	unsigned long rtas_args_paddr;
 
 	PPCDBG(PPCDBG_RTAS, "Entering rtas_call\n");
 	PPCDBG(PPCDBG_RTAS, "\ttoken    = 0x%x\n", token);
@@ -143,9 +144,13 @@ int rtas_call(int token, int nargs, int 
 	for (i = 0; i < nret; ++i)
 		rtas_args->rets[i] = 0;
 
-	PPCDBG(PPCDBG_RTAS, "\tentering rtas with 0x%lx\n",
-		__pa(rtas_args));
-	enter_rtas(__pa(rtas_args));
+	if (likely(system_state >= SYSTEM_RUNNING))
+		rtas_args_paddr = virt_to_phys(rtas_args);
+	else
+		rtas_args_paddr = __boot_pa(rtas_args);
+
+	PPCDBG(PPCDBG_RTAS, "\tentering rtas with 0x%lx\n", rtas_args_paddr);
+	enter_rtas(rtas_args_paddr);
 	PPCDBG(PPCDBG_RTAS, "\treturned from rtas ...\n");
 
 	/* A -1 return code indicates that the last command couldn't
@@ -309,7 +314,7 @@ rtas_flash_firmware(void)
 	 */
 	rtas_firmware_flash_list.num_blocks = 0;
 	flist = (struct flash_block_list *)&rtas_firmware_flash_list;
-	rtas_block_list = virt_to_abs(flist);
+	rtas_block_list = boot_virt_to_abs(flist);
 	if (rtas_block_list >= 4UL*1024*1024*1024) {
 		printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n");
 		return;
@@ -321,13 +326,13 @@ rtas_flash_firmware(void)
 	for (f = flist; f; f = next) {
 		/* Translate data addrs to absolute */
 		for (i = 0; i < f->num_blocks; i++) {
-			f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data);
+			f->blocks[i].data = (char *)boot_virt_to_abs(f->blocks[i].data);
 			image_size += f->blocks[i].length;
 		}
 		next = f->next;
 		/* Don't translate NULL pointer for last entry */
 		if (f->next)
-			f->next = (struct flash_block_list *)virt_to_abs(f->next);
+			f->next = (struct flash_block_list *)boot_virt_to_abs(f->next);
 		else
 			f->next = NULL;
 		/* make num_blocks into the version/length field */
@@ -407,7 +412,7 @@ void rtas_os_term(char *str)
 
 	do {
 		status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL,
-				   __pa(rtas_os_term_buf));
+				   virt_to_phys(rtas_os_term_buf));
 
 		if (status == RTAS_BUSY)
 			udelay(1);
diff -puN arch/ppc64/kernel/smp.c~H-nonlinear-ppc64-daveh arch/ppc64/kernel/smp.c
--- memhotplug/arch/ppc64/kernel/smp.c~H-nonlinear-ppc64-daveh	Thu Aug  5 09:41:13 2004
+++ memhotplug-dave/arch/ppc64/kernel/smp.c	Thu Aug  5 09:41:13 2004
@@ -504,7 +504,7 @@ void vpa_init(int cpu)
 
 	/* Register the Virtual Processor Area (VPA) */
 	flags = 1UL << (63 - 18);
-	register_vpa(flags, cpu, __pa((unsigned long)&(paca[cpu].lppaca)));
+	register_vpa(flags, cpu, __boot_pa((unsigned long)&(paca[cpu].lppaca)));
 }
 
 static inline void smp_xics_do_message(int cpu, int msg)
@@ -888,6 +888,7 @@ void __devinit smp_prepare_boot_cpu(void
 	current_set[boot_cpuid] = current->thread_info;
 }
 
+void dump_cpustuff(void);
 int __devinit __cpu_up(unsigned int cpu)
 {
 	int c;
@@ -910,7 +911,7 @@ int __devinit __cpu_up(unsigned int cpu)
 		tmp = &stab_array[PAGE_SIZE * cpu];
 		memset(tmp, 0, PAGE_SIZE); 
 		paca[cpu].stab_addr = (unsigned long)tmp;
-		paca[cpu].stab_real = virt_to_abs(tmp);
+		paca[cpu].stab_real = boot_virt_to_abs(tmp);
 	}
 
 	/* The information for processor bringup must
diff -puN arch/ppc64/kernel/vio.c~H-nonlinear-ppc64-daveh arch/ppc64/kernel/vio.c
diff -puN arch/ppc64/mm/hash_utils.c~H-nonlinear-ppc64-daveh arch/ppc64/mm/hash_utils.c
--- memhotplug/arch/ppc64/mm/hash_utils.c~H-nonlinear-ppc64-daveh	Thu Aug  5 09:41:13 2004
+++ memhotplug-dave/arch/ppc64/mm/hash_utils.c	Thu Aug  5 09:41:13 2004
@@ -96,8 +96,15 @@ static inline void create_pte_mapping(un
 		unsigned long vpn, hash, hpteg;
 		unsigned long vsid = get_kernel_vsid(addr);
 		unsigned long va = (vsid << 28) | (addr & 0xfffffff);
+		unsigned long abs_page_nr, abs_page_addr;
 		int ret;
 
+		if (system_state >= SYSTEM_RUNNING)
+			abs_page_addr = virt_to_abs((void *)addr);
+		else
+			abs_page_addr = boot_virt_to_abs(addr);
+		abs_page_nr = abs_page_addr >> PAGE_SHIFT;
+
 		if (large)
 			vpn = va >> LARGE_PAGE_SHIFT;
 		else
@@ -109,12 +116,10 @@ static inline void create_pte_mapping(un
 
 		if (systemcfg->platform == PLATFORM_PSERIES_LPAR)
 			ret = pSeries_lpar_hpte_insert(hpteg, va,
-				virt_to_abs(addr) >> PAGE_SHIFT,
-				0, mode, 1, large);
+				abs_page_nr, 0, mode, 1, large);
 		else
 			ret = pSeries_hpte_insert(hpteg, va,
-				virt_to_abs(addr) >> PAGE_SHIFT,
-				0, mode, 1, large);
+				abs_page_nr, 0, mode, 1, large);
 
 		if (ret == -1) {
 			ppc64_terminate_msg(0x20, "create_pte_mapping");
@@ -156,7 +161,7 @@ void __init htab_initialize(void)
 			ppc64_terminate_msg(0x20, "hpt space");
 			loop_forever();
 		}
-		htab_data.htab = abs_to_virt(table);
+		htab_data.htab = boot_abs_to_virt(table);
 
 		/* htab absolute addr + encoded htabsize */
 		_SDR1 = table + __ilog2(pteg_count) - 11;
diff -puN arch/ppc64/mm/init.c~H-nonlinear-ppc64-daveh arch/ppc64/mm/init.c
--- memhotplug/arch/ppc64/mm/init.c~H-nonlinear-ppc64-daveh	Thu Aug  5 09:41:13 2004
+++ memhotplug-dave/arch/ppc64/mm/init.c	Thu Aug  5 09:41:13 2004
@@ -100,7 +100,7 @@ void show_mem(void)
 	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 	for_each_pgdat(pgdat) {
 		for (i = 0; i < pgdat->node_spanned_pages; i++) {
-			page = pgdat->node_mem_map + i;
+			page = pfn_to_page(i);
 			total++;
 			if (PageReserved(page))
 				reserved++;
@@ -424,8 +424,8 @@ void free_initmem(void)
 
 	addr = (unsigned long)__init_begin;
 	for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(addr));
-		set_page_count(virt_to_page(addr), 1);
+		ClearPageReserved(virt_to_page((void *)addr));
+		set_page_count(virt_to_page((void *)addr), 1);
 		free_page(addr);
 		totalram_pages++;
 	}
@@ -533,6 +533,11 @@ void __init do_init_bootmem(void)
 	unsigned long total_pages = lmb_end_of_DRAM() >> PAGE_SHIFT;
 	int boot_mapsize;
 
+#ifdef CONFIG_NONLINEAR
+	setup_memsections();
+	alloc_memsections(0, 0, total_pages);
+#endif
+
 	/*
 	 * Find an area to use for the bootmem bitmap.  Calculate the size of
 	 * bitmap required as (Total Memory) / PAGE_SIZE / BITS_PER_BYTE.
@@ -588,7 +593,7 @@ void __init paging_init(void)
 	memset(zones_size, 0, sizeof(zones_size));
 	memset(zholes_size, 0, sizeof(zholes_size));
 
-	zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
+	zones_size[ZONE_DMA] = top_pfn;
 	zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT;
 
 	free_area_init_node(0, &contig_page_data, zones_size,
@@ -652,7 +657,8 @@ void __init mem_init(void)
 	       (unsigned long)nr_free_pages()<< (PAGE_SHIFT-10),
 	       codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10),
 	       initpages<< (PAGE_SHIFT-10),
-	       PAGE_OFFSET, (unsigned long)__va(lmb_end_of_DRAM()));
+	       PAGE_OFFSET, (unsigned long)__boot_va(lmb_end_of_DRAM()));
+	/* lmb_end_of_DRAM() is not a valid phsical address.  hack around it for now */
 }
 #else
 	max_mapnr = num_physpages;
@@ -661,7 +667,7 @@ void __init mem_init(void)
 
 	for (addr = KERNELBASE; addr < (unsigned long)__va(lmb_end_of_DRAM());
 	     addr += PAGE_SIZE) {
-		if (!PageReserved(virt_to_page(addr)))
+		if (!PageReserved(virt_to_page((void *)addr)))
 			continue;
 		if (addr < (unsigned long)_etext)
 			codepages++;
@@ -677,7 +683,7 @@ void __init mem_init(void)
 	       (unsigned long)nr_free_pages()<< (PAGE_SHIFT-10),
 	       codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10),
 	       initpages<< (PAGE_SHIFT-10),
-	       PAGE_OFFSET, (unsigned long)__va(lmb_end_of_DRAM()));
+	       PAGE_OFFSET, (unsigned long)__boot_va(lmb_end_of_DRAM()));
 #endif
 	mem_init_done = 1;
 
@@ -841,3 +847,4 @@ void pgtable_cache_init(void)
 	if (!zero_cache)
 		panic("pgtable_cache_init(): could not create zero_cache!\n");
 }
+
diff -puN arch/ppc64/xmon/xmon.c~H-nonlinear-ppc64-daveh arch/ppc64/xmon/xmon.c
diff -puN include/asm-ppc64/abs_addr.h~H-nonlinear-ppc64-daveh include/asm-ppc64/abs_addr.h
--- memhotplug/include/asm-ppc64/abs_addr.h~H-nonlinear-ppc64-daveh	Thu Aug  5 09:41:13 2004
+++ memhotplug-dave/include/asm-ppc64/abs_addr.h	Thu Aug  5 09:41:13 2004
@@ -102,7 +102,9 @@ physRpn_to_absRpn(unsigned long rpn)
 #endif /* !CONFIG_MSCHUNKS */
 
 /* Convenience macros */
-#define virt_to_abs(va) phys_to_abs(__pa(va))
-#define abs_to_virt(aa) __va(abs_to_phys(aa))
+#define virt_to_abs(va) phys_to_abs(virt_to_phys(va))
+#define abs_to_virt(aa) phys_to_virt(abs_to_phys(aa))
+#define boot_virt_to_abs(va) phys_to_abs(__boot_pa(va))
+#define boot_abs_to_virt(aa) __boot_va(abs_to_phys(aa))
 
 #endif /* _ABS_ADDR_H */
diff -puN /dev/null include/asm-ppc64/memory_hotplug.h
--- /dev/null	Tue Mar 30 06:13:35 2004
+++ memhotplug-dave/include/asm-ppc64/memory_hotplug.h	Thu Aug  5 09:41:13 2004
@@ -0,0 +1,10 @@
+#ifndef __ASM_MEMORY_HOTPLUG_H
+#define __ASM_MEMORY_HOTPLUG_H
+
+/* copied from i386 version.  Can they be shared? */
+
+/* VM interface that may be used by firmware interface */
+extern int add_pages(u64 start, u64 size, unsigned long attr);
+extern int remove_pages(u64 start, u64 size, unsigned long attr);
+
+#endif
diff -puN /dev/null include/asm-ppc64/nonlinear.h
--- /dev/null	Tue Mar 30 06:13:35 2004
+++ memhotplug-dave/include/asm-ppc64/nonlinear.h	Thu Aug  5 09:41:13 2004
@@ -0,0 +1,8 @@
+#ifndef __PPC64_NONLINEAR_H_
+#define __PPC64_NONLINEAR_H_
+
+#define SECTION_SHIFT		28	/* Size of section - 256 Mbytes */
+#define	MAX_MEM_SHIFT		40
+#define	MAX_PHYS_SHIFT		40
+
+#endif /* __PPC64_NONLINEAR_H_ */
diff -puN include/asm-ppc64/page.h~H-nonlinear-ppc64-daveh include/asm-ppc64/page.h
--- memhotplug/include/asm-ppc64/page.h~H-nonlinear-ppc64-daveh	Thu Aug  5 09:41:13 2004
+++ memhotplug-dave/include/asm-ppc64/page.h	Thu Aug  5 09:41:13 2004
@@ -229,23 +229,32 @@ extern int page_is_ram(unsigned long phy
 #define IS_VALID_EA(x) \
         ((!((x) & INVALID_EA_BITS)) && IS_VALID_REGION_ID(REGION_ID(x)))
 
-#define __bpn_to_ba(x) ((((unsigned long)(x))<<PAGE_SHIFT) + KERNELBASE)
+#define __bpn_to_ba(x) __va(((unsigned long)(x))<<PAGE_SHIFT)
 #define __ba_to_bpn(x) ((((unsigned long)(x)) & ~REGION_MASK) >> PAGE_SHIFT)
 
+#ifndef __ASSEMBLY__
 #ifdef CONFIG_DISCONTIGMEM
 #define page_to_pfn(page)	discontigmem_page_to_pfn(page)
 #define pfn_to_page(pfn)	discontigmem_pfn_to_page(pfn)
 #define pfn_valid(pfn)		discontigmem_pfn_valid(pfn)
-#else
+#elif defined CONFIG_NONLINEAR
+extern unsigned long page_to_pfn(struct page *page);
+extern struct page *pfn_to_page(unsigned long);
+#else /* !CONFIG_NONLINEAR && !CONFIG_DISCONTIGMEM */
 #define pfn_to_page(pfn)	(mem_map + (pfn))
 #define page_to_pfn(page)	((unsigned long)((page) - mem_map))
 #define pfn_valid(pfn)		((pfn) < max_mapnr)
 #endif
 
-#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
-#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
+#include <linux/nonlinear.h>
+#include <asm/io.h>
 
-#define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+#define pfn_to_kaddr(pfn)	phys_to_virt((pfn) << PAGE_SHIFT)
+#define virt_to_page(kaddr)	pfn_to_page(virt_to_phys(kaddr) >> PAGE_SHIFT)
+
+#define virt_addr_valid(kaddr)	pfn_valid(virt_to_phys(kaddr) >> PAGE_SHIFT)
+
+#endif /* __ASSEMBLY__ */
 
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
diff -puN include/linux/nonlinear.h~H-nonlinear-ppc64-daveh include/linux/nonlinear.h
diff -puN mm/nonlinear.c~H-nonlinear-ppc64-daveh mm/nonlinear.c
diff -puN mm/page_alloc.c~H-nonlinear-ppc64-daveh mm/page_alloc.c
diff -L I-nonlinear-ppc64-dave-hmore -puN /dev/null /dev/null

_
