[PATCH] add x86-64 specific support for sparsemem
authorMatt Tolentino <metolent@snoqualmie.dp.intel.com>
Thu, 23 Jun 2005 07:08:07 +0000 (00:08 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Thu, 23 Jun 2005 16:45:07 +0000 (09:45 -0700)
This patch adds in the necessary support for sparsemem such that x86-64
kernels may use sparsemem as an alternative to discontigmem for NUMA
kernels.  Note that this does no preclude one from continuing to build NUMA
kernels using discontigmem, but merely allows the option to build NUMA
kernels with sparsemem.

Interestingly, the use of sparsemem in lieu of discontigmem in NUMA kernels
results in reduced text size for otherwise equivalent kernels as shown in
the example builds below:

   text    data     bss     dec     hex filename
2371036  765884 1237108 4374028  42be0c vmlinux.discontig
2366549  776484 1302772 4445805  43d66d vmlinux.sparse

Signed-off-by: Matt Tolentino <matthew.e.tolentino@intel.com>
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/x86_64/kernel/setup.c
arch/x86_64/mm/numa.c
include/asm-x86_64/bitops.h
include/asm-x86_64/sparsemem.h [new file with mode: 0644]

index dd8419b37a7e5296a806a7c701339242e97a3942..000015dd5a8be5770bb3d845cda66b716d6fe5a8 100644 (file)
@@ -40,6 +40,8 @@
 #include <linux/acpi.h>
 #include <linux/kallsyms.h>
 #include <linux/edd.h>
+#include <linux/mmzone.h>
+
 #include <asm/mtrr.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -378,16 +380,19 @@ static __init void parse_cmdline_early (char ** cmdline_p)
 }
 
 #ifndef CONFIG_NUMA
-static void __init contig_initmem_init(void)
+static void __init
+contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
 {
-        unsigned long bootmap_size, bootmap; 
-        bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
-        bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size);
-        if (bootmap == -1L) 
-                panic("Cannot find bootmem map of size %ld\n",bootmap_size);
-        bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
-        e820_bootmem_free(NODE_DATA(0), 0, end_pfn << PAGE_SHIFT);
-        reserve_bootmem(bootmap, bootmap_size);
+       unsigned long bootmap_size, bootmap;
+
+       memory_present(0, start_pfn, end_pfn);
+       bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
+       bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size);
+       if (bootmap == -1L)
+               panic("Cannot find bootmem map of size %ld\n",bootmap_size);
+       bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
+       e820_bootmem_free(NODE_DATA(0), 0, end_pfn << PAGE_SHIFT);
+       reserve_bootmem(bootmap, bootmap_size);
 } 
 #endif
 
@@ -557,7 +562,7 @@ void __init setup_arch(char **cmdline_p)
 #ifdef CONFIG_NUMA
        numa_initmem_init(0, end_pfn); 
 #else
-       contig_initmem_init(); 
+       contig_initmem_init(0, end_pfn);
 #endif
 
        /* Reserve direct mapping */
@@ -618,6 +623,8 @@ void __init setup_arch(char **cmdline_p)
                }
        }
 #endif
+
+       sparse_init();
        paging_init();
 
        check_ioapic();
index fd9f25d7a6c4c2d6d3d48c4057a00e2c725ddff0..84cde796ecb133ebfaf145262323d7ab20379482 100644 (file)
@@ -66,6 +66,13 @@ int __init compute_hash_shift(struct node *nodes, int numnodes)
        return -1; 
 }
 
+#ifdef CONFIG_SPARSEMEM
+int early_pfn_to_nid(unsigned long pfn)
+{
+       return phys_to_nid(pfn << PAGE_SHIFT);
+}
+#endif
+
 /* Initialize bootmem allocator for a node */
 void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
 { 
@@ -80,6 +87,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
        start_pfn = start >> PAGE_SHIFT;
        end_pfn = end >> PAGE_SHIFT;
 
+       memory_present(nodeid, start_pfn, end_pfn);
        nodedata_phys = find_e820_area(start, end, pgdat_size); 
        if (nodedata_phys == -1L) 
                panic("Cannot find memory pgdat in node %d\n", nodeid);
index 5dd7727c756b492a2af0510b2d44a0c804180310..a31bb99be53ff0dfc531cb1ac0e849c43062466c 100644 (file)
@@ -411,8 +411,6 @@ static __inline__ int ffs(int x)
 /* find last set bit */
 #define fls(x) generic_fls(x)
 
-#define ARCH_HAS_ATOMIC_UNSIGNED 1
-
 #endif /* __KERNEL__ */
 
 #endif /* _X86_64_BITOPS_H */
diff --git a/include/asm-x86_64/sparsemem.h b/include/asm-x86_64/sparsemem.h
new file mode 100644 (file)
index 0000000..dabb167
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _ASM_X86_64_SPARSEMEM_H
+#define _ASM_X86_64_SPARSEMEM_H 1
+
+#ifdef CONFIG_SPARSEMEM
+
+/*
+ * generic non-linear memory support:
+ *
+ * 1) we will not split memory into more chunks than will fit into the flags
+ *    field of the struct page
+ *
+ * SECTION_SIZE_BITS           2^n: size of each section
+ * MAX_PHYSADDR_BITS           2^n: max size of physical address space
+ * MAX_PHYSMEM_BITS            2^n: how much memory we can have in that space
+ *
+ */
+
+#define SECTION_SIZE_BITS      27 /* matt - 128 is convenient right now */
+#define MAX_PHYSADDR_BITS      40
+#define MAX_PHYSMEM_BITS       40
+
+extern int early_pfn_to_nid(unsigned long pfn);
+
+#endif /* CONFIG_SPARSEMEM */
+
+#endif /* _ASM_X86_64_SPARSEMEM_H */