

Here's a follow on nonlinear port for x86_64.  I've cleaned 
things up a bit and ported to the latest patchset.  I do have 
this working on my local x86_64 system, so things are looking
pretty good. 

Dave, can you roll this into the overall patchset?   I've got
more to add to this, but I'd prefer to send in smaller patches
against this...

matt

Signed-off-by: Matt Tolentino <matthew.e.tolentino@intel.com)
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
---

 memhotplug-dave/arch/x86_64/Kconfig            |   17 ++++++++++++
 memhotplug-dave/arch/x86_64/kernel/apic.c      |    4 +--
 memhotplug-dave/arch/x86_64/kernel/pci-gart.c  |    4 +--
 memhotplug-dave/arch/x86_64/kernel/setup.c     |   11 +++++---
 memhotplug-dave/arch/x86_64/kernel/setup64.c   |    2 -
 memhotplug-dave/arch/x86_64/mm/init.c          |   33 ++++++++++++++++++++++---
 memhotplug-dave/include/asm-x86_64/io.h        |    3 +-
 memhotplug-dave/include/asm-x86_64/nonlinear.h |    8 ++++++
 memhotplug-dave/include/asm-x86_64/page.h      |   33 ++++++++++++++++---------
 memhotplug-dave/include/asm-x86_64/pgtable.h   |    1 
 memhotplug-dave/include/linux/nonlinear.h      |    2 -
 memhotplug-dave/mm/page_alloc.c                |   12 ++++++++-
 12 files changed, 104 insertions(+), 26 deletions(-)

diff -puN arch/x86_64/Kconfig~H-nonlinear-x86_64 arch/x86_64/Kconfig
--- memhotplug/arch/x86_64/Kconfig~H-nonlinear-x86_64	2004-09-27 10:32:30.000000000 -0700
+++ memhotplug-dave/arch/x86_64/Kconfig	2004-09-27 10:32:30.000000000 -0700
@@ -285,6 +285,23 @@ config NUMA
        depends on K8_NUMA
        default y
 
+config NONLINEAR
+       bool "Allow for nonlinear physical memory"
+       default y
+
+config ARCH_HAS_MEM_MAP
+       bool
+       depends on !DISCONTIGMEM && !NONLINEAR
+       default y
+
+config ARCH_HAS_BOOTPA
+       bool
+       default y
+
+config MEMORY_HOTPLUG
+       bool "Allow memory hotplug"
+       depends on NONLINEAR && HOTPLUG
+
 config HAVE_DEC_LOCK
 	bool
 	depends on SMP
diff -puN arch/x86_64/kernel/apic.c~H-nonlinear-x86_64 arch/x86_64/kernel/apic.c
--- memhotplug/arch/x86_64/kernel/apic.c~H-nonlinear-x86_64	2004-09-27 10:32:30.000000000 -0700
+++ memhotplug-dave/arch/x86_64/kernel/apic.c	2004-09-27 10:32:30.000000000 -0700
@@ -643,7 +643,7 @@ void __init init_apic_mappings(void)
 	 */
 	if (!smp_found_config && detect_init_APIC()) {
 		apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
-		apic_phys = __pa(apic_phys);
+		apic_phys = __boot_pa(apic_phys);
 	} else
 		apic_phys = mp_lapic_addr;
 
@@ -667,7 +667,7 @@ void __init init_apic_mappings(void)
 				ioapic_phys = mp_ioapics[i].mpc_apicaddr;
 			} else {
 				ioapic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
-				ioapic_phys = __pa(ioapic_phys);
+				ioapic_phys = __boot_pa(ioapic_phys);
 			}
 			set_fixmap_nocache(idx, ioapic_phys);
 			apic_printk(APIC_VERBOSE,"mapped IOAPIC to %016lx (%016lx)\n",
diff -puN arch/x86_64/kernel/pci-gart.c~H-nonlinear-x86_64 arch/x86_64/kernel/pci-gart.c
--- memhotplug/arch/x86_64/kernel/pci-gart.c~H-nonlinear-x86_64	2004-09-27 10:32:30.000000000 -0700
+++ memhotplug-dave/arch/x86_64/kernel/pci-gart.c	2004-09-27 10:32:30.000000000 -0700
@@ -736,7 +736,7 @@ static __init int init_k8_gatt(struct ag
 		u32 ctl; 
 		u32 gatt_reg; 
 
-		gatt_reg = __pa(gatt) >> 12; 
+		gatt_reg = __boot_pa(gatt) >> 12;
 		gatt_reg <<= 4; 
 		pci_write_config_dword(dev, 0x98, gatt_reg);
 		pci_read_config_dword(dev, 0x90, &ctl); 
@@ -862,7 +862,7 @@ static int __init pci_iommu_init(void)
 	scratch = get_zeroed_page(GFP_KERNEL); 
 	if (!scratch) 
 		panic("Cannot allocate iommu scratch page");
-	gart_unmapped_entry = GPTE_ENCODE(__pa(scratch));
+	gart_unmapped_entry = GPTE_ENCODE(__boot_pa(scratch));
 	for (i = EMERGENCY_PAGES; i < iommu_pages; i++) 
 		iommu_gatt_base[i] = gart_unmapped_entry;
 
diff -puN arch/x86_64/kernel/setup.c~H-nonlinear-x86_64 arch/x86_64/kernel/setup.c
--- memhotplug/arch/x86_64/kernel/setup.c~H-nonlinear-x86_64	2004-09-27 10:32:30.000000000 -0700
+++ memhotplug-dave/arch/x86_64/kernel/setup.c	2004-09-27 10:32:30.000000000 -0700
@@ -467,10 +467,10 @@ void __init setup_arch(char **cmdline_p)
 	init_mm.end_data = (unsigned long) &_edata;
 	init_mm.brk = (unsigned long) &_end;
 
-	code_resource.start = virt_to_phys(&_text);
-	code_resource.end = virt_to_phys(&_etext)-1;
-	data_resource.start = virt_to_phys(&_etext);
-	data_resource.end = virt_to_phys(&_edata)-1;
+	code_resource.start = __boot_pa(&_text);
+	code_resource.end = __boot_pa(&_etext)-1;
+	data_resource.start = __boot_pa(&_etext);
+	data_resource.end = __boot_pa(&_edata)-1;
 
 	parse_cmdline_early(cmdline_p);
 
@@ -480,6 +480,9 @@ void __init setup_arch(char **cmdline_p)
 	 */
 	end_pfn = e820_end_of_ram();
 
+	setup_memsections();
+	alloc_memsections(0, 0, end_pfn);
+
 	check_efer();
 
 	init_memory_mapping(); 
diff -puN arch/x86_64/kernel/setup64.c~H-nonlinear-x86_64 arch/x86_64/kernel/setup64.c
--- memhotplug/arch/x86_64/kernel/setup64.c~H-nonlinear-x86_64	2004-09-27 10:32:30.000000000 -0700
+++ memhotplug-dave/arch/x86_64/kernel/setup64.c	2004-09-27 10:32:30.000000000 -0700
@@ -134,7 +134,7 @@ void pda_init(int cpu)
 	if (level4 != init_level4_pgt)
 		memcpy(level4, &init_level4_pgt, PAGE_SIZE); 
 	set_pml4(level4 + 510, mk_kernel_pml4(__pa_symbol(boot_vmalloc_pgt)));
-	asm volatile("movq %0,%%cr3" :: "r" (__pa(level4))); 
+	asm volatile("movq %0,%%cr3" :: "r" (__boot_pa(level4)));
 
 	pda->irqstackptr += IRQSTACKSIZE-64;
 } 
diff -puN arch/x86_64/mm/init.c~H-nonlinear-x86_64 arch/x86_64/mm/init.c
--- memhotplug/arch/x86_64/mm/init.c~H-nonlinear-x86_64	2004-09-27 10:32:30.000000000 -0700
+++ memhotplug-dave/arch/x86_64/mm/init.c	2004-09-27 10:32:30.000000000 -0700
@@ -22,6 +22,7 @@
 #include <linux/pagemap.h>
 #include <linux/bootmem.h>
 #include <linux/proc_fs.h>
+#include <linux/memory_hotplug.h>
 
 #include <asm/processor.h>
 #include <asm/system.h>
@@ -68,8 +69,8 @@ void show_mem(void)
 
 	for_each_pgdat(pgdat) {
                for (i = 0; i < pgdat->node_spanned_pages; ++i) {
-                       page = pgdat->node_mem_map + i;
-		total++;
+			page = lpfn_to_page(pgdat->node_start_pfn + i);
+			total++;
                        if (PageReserved(page))
 			reserved++;
                        else if (PageSwapCache(page))
@@ -403,6 +404,29 @@ static inline int page_is_ram (unsigned 
 extern int swiotlb_force;
 
 /*
+ * Placeholder for arch specific functions for memory
+ * hotplug....
+ */
+
+void online_page(struct page *page)
+{
+	printk("%s: not quite yet....\n", __func__);
+}
+
+int add_memory(u64 start, u64 size, unsigned long attr)
+{
+	printk("%s: not quite yet....\n", __func__);
+	return -ENOSYS;
+}
+
+int remove_memory(u64 start, u64 size, unsigned long attr)
+{
+	printk("%s: not quite yet....\n", __func__);
+	return -ENOSYS;
+}
+
+
+/*
  * devmem_is_allowed() checks to see if /dev/mem access to a certain address is
  * valid. The argument is a physical page number.
  *
@@ -458,7 +482,10 @@ void __init mem_init(void)
 	/* should count reserved pages here for all nodes */ 
 #else
 	max_mapnr = end_pfn;
+
+#ifdef CONFIG_ARCH_HAS_MEM_MAP
 	if (!mem_map) BUG();
+#endif
 
 	totalram_pages += free_all_bootmem();
 
@@ -466,7 +493,7 @@ void __init mem_init(void)
 		/*
 		 * Only count reserved RAM pages
 		 */
-		if (page_is_ram(tmp) && PageReserved(mem_map+tmp))
+		if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp)))
 			reservedpages++;
 #endif
 
diff -puN include/asm-x86_64/io.h~H-nonlinear-x86_64 include/asm-x86_64/io.h
--- memhotplug/include/asm-x86_64/io.h~H-nonlinear-x86_64	2004-09-27 10:32:30.000000000 -0700
+++ memhotplug-dave/include/asm-x86_64/io.h	2004-09-27 10:32:30.000000000 -0700
@@ -108,6 +108,7 @@ __OUTS(l)
 #if defined(__KERNEL__) && __x86_64__
 
 #include <linux/vmalloc.h>
+#include <linux/nonlinear.h>
 
 #ifndef __i386__
 /*
@@ -116,7 +117,7 @@ __OUTS(l)
  */
 extern inline unsigned long virt_to_phys(volatile void * address)
 {
-	return __pa(address);
+	return __pa((void *)address);
 }
 
 extern inline void * phys_to_virt(unsigned long address)
diff -puN /dev/null include/asm-x86_64/nonlinear.h
--- /dev/null	2004-08-06 10:20:23.000000000 -0700
+++ memhotplug-dave/include/asm-x86_64/nonlinear.h	2004-09-27 10:32:30.000000000 -0700
@@ -0,0 +1,8 @@
+#ifndef __X86_64_NONLINEAR_H_
+#define __X64_64_NONLINEAR_H_
+
+#define SECTION_SHIFT		27	/* Size of section - 128 Mbytes */
+#define	MAX_MEM_SHIFT		40
+#define	MAX_PHYS_SHIFT		40
+
+#endif /* __X86_64_NONLINEAR_H_ */
diff -puN include/asm-x86_64/page.h~H-nonlinear-x86_64 include/asm-x86_64/page.h
--- memhotplug/include/asm-x86_64/page.h~H-nonlinear-x86_64	2004-09-27 10:32:30.000000000 -0700
+++ memhotplug-dave/include/asm-x86_64/page.h	2004-09-27 10:32:30.000000000 -0700
@@ -105,21 +105,32 @@ extern __inline__ int get_order(unsigned
 	return order;
 }
 
-#endif /* __ASSEMBLY__ */
-
 #define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET)
 
-/* Note: __pa(&symbol_visible_to_c) should be always replaced with __pa_symbol.
-   Otherwise you risk miscompilation. */ 
-#define __pa(x)			(((unsigned long)(x)>=__START_KERNEL_map)?(unsigned long)(x) - (unsigned long)__START_KERNEL_map:(unsigned long)(x) - PAGE_OFFSET)
-/* __pa_symbol should be used for C visible symbols.
-   This seems to be the official gcc blessed way to do such arithmetic. */ 
-#define __pa_symbol(x)		\
-	({unsigned long v;  \
+/*
+ * Note: __pa(&symbol_visible_to_c) should be always replaced with __pa_symbol.
+ * Otherwise you risk miscompilation.
+ */
+#define __boot_pa(x)  (((unsigned long)(x)>=__START_KERNEL_map)?(unsigned long)(x) - (unsigned long)__START_KERNEL_map:(unsigned long)(x) - PAGE_OFFSET)
+#define __boot_va(x)  ((void *)((unsigned long)(x)+PAGE_OFFSET))
+
+#ifndef CONFIG_NONLINEAR
+#define __pa(x)	__boot_pa(x)
+#define __va(x)	__boot_va(x)
+#else
+#include <linux/nonlinear.h>
+#endif
++
+/*
+ * __pa_symbol should be used for C visible symbols.
+ * This seems to be the official gcc blessed way to do
+ * such arithmetic.
+ */
+#define __pa_symbol(x)			\
+	({unsigned long v;		\
 	  asm("" : "=r" (v) : "0" (x)); \
-	  __pa(v); })
+	__boot_pa(v); })
 
-#define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
 #ifndef CONFIG_DISCONTIGMEM
 #define pfn_to_page(pfn)	(mem_map + (pfn))
 #define page_to_pfn(page)	((unsigned long)((page) - mem_map))
diff -puN include/asm-x86_64/pgtable.h~H-nonlinear-x86_64 include/asm-x86_64/pgtable.h
--- memhotplug/include/asm-x86_64/pgtable.h~H-nonlinear-x86_64	2004-09-27 10:32:30.000000000 -0700
+++ memhotplug-dave/include/asm-x86_64/pgtable.h	2004-09-27 10:32:30.000000000 -0700
@@ -15,6 +15,7 @@
 #include <asm/fixmap.h>
 #include <asm/bitops.h>
 #include <linux/threads.h>
+#include <linux/nonlinear.h>
 #include <asm/pda.h>
 
 extern pgd_t level3_kernel_pgt[512];
diff -puN include/linux/nonlinear.h~H-nonlinear-x86_64 include/linux/nonlinear.h
--- memhotplug/include/linux/nonlinear.h~H-nonlinear-x86_64	2004-09-27 10:32:30.000000000 -0700
+++ memhotplug-dave/include/linux/nonlinear.h	2004-09-27 10:32:30.000000000 -0700
@@ -90,7 +90,7 @@ static inline unsigned long
 __pa(const void *ptr_addr)
 {
 	unsigned long addr = (unsigned long)ptr_addr;
-	return section_to_addr(mem_section[addr_to_section(addr-PAGE_OFFSET)].phys_section) |
+	return section_to_addr(mem_section[addr_to_section(__boot_pa(addr))].phys_section) |
 		section_offset(addr);
 }
 
diff -puN mm/page_alloc.c~H-nonlinear-x86_64 mm/page_alloc.c
--- memhotplug/mm/page_alloc.c~H-nonlinear-x86_64	2004-09-27 10:32:30.000000000 -0700
+++ memhotplug-dave/mm/page_alloc.c	2004-09-27 10:32:30.000000000 -0700
@@ -1718,7 +1718,17 @@ static void __init alloc_node_mem_map(st
 #endif
 }
 #else
-static void __init alloc_node_mem_map(struct pglist_data *pgdat) {}
+static void __init alloc_node_mem_map(struct pglist_data *pgdat)
+{
+	struct page *lmem_map;
+
+	if (!pgdat->node_spanned_pages) {
+		printk("%s: Crap, no node_spanned_pages??\n", __func__);
+		while(1);
+	}
+	lmem_map = alloc_bootmem(pgdat->node_spanned_pages * sizeof(struct page));
+	alloc_memmap(lmem_map, 0, pgdat->node_spanned_pages);
+}
 #endif
 
 void __init free_area_init_node(int nid, struct pglist_data *pgdat,
_
