aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/Kconfig24
-rw-r--r--arch/i386/kernel/setup.c8
-rw-r--r--arch/i386/mm/Makefile2
-rw-r--r--arch/i386/mm/discontig.c36
-rw-r--r--arch/i386/mm/init.c18
-rw-r--r--include/asm-i386/mmzone.h89
-rw-r--r--include/asm-i386/page.h4
-rw-r--r--include/asm-i386/pgtable.h4
-rw-r--r--include/asm-i386/sparsemem.h31
9 files changed, 135 insertions, 81 deletions
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index f0064b5e3702..bfdcedef06e1 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -68,7 +68,6 @@ config X86_VOYAGER
68 68
69config X86_NUMAQ 69config X86_NUMAQ
70 bool "NUMAQ (IBM/Sequent)" 70 bool "NUMAQ (IBM/Sequent)"
71 select DISCONTIGMEM
72 select NUMA 71 select NUMA
73 help 72 help
74 This option is used for getting Linux to run on a (IBM/Sequent) NUMA 73 This option is used for getting Linux to run on a (IBM/Sequent) NUMA
@@ -783,11 +782,6 @@ comment "NUMA (NUMA-Q) requires SMP, 64GB highmem support"
783comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI" 782comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI"
784 depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI) 783 depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI)
785 784
786config ARCH_DISCONTIGMEM_ENABLE
787 bool
788 depends on NUMA
789 default y
790
791config HAVE_ARCH_BOOTMEM_NODE 785config HAVE_ARCH_BOOTMEM_NODE
792 bool 786 bool
793 depends on NUMA 787 depends on NUMA
@@ -800,7 +794,7 @@ config ARCH_HAVE_MEMORY_PRESENT
800 794
801config NEED_NODE_MEMMAP_SIZE 795config NEED_NODE_MEMMAP_SIZE
802 bool 796 bool
803 depends on DISCONTIGMEM 797 depends on DISCONTIGMEM || SPARSEMEM
804 default y 798 default y
805 799
806config HAVE_ARCH_ALLOC_REMAP 800config HAVE_ARCH_ALLOC_REMAP
@@ -808,6 +802,22 @@ config HAVE_ARCH_ALLOC_REMAP
808 depends on NUMA 802 depends on NUMA
809 default y 803 default y
810 804
805config ARCH_DISCONTIGMEM_ENABLE
806 def_bool y
807 depends on NUMA
808
809config ARCH_DISCONTIGMEM_DEFAULT
810 def_bool y
811 depends on NUMA
812
813config ARCH_SPARSEMEM_ENABLE
814 def_bool y
815 depends on NUMA
816
817config ARCH_SELECT_MEMORY_MODEL
818 def_bool y
819 depends on ARCH_SPARSEMEM_ENABLE
820
811source "mm/Kconfig" 821source "mm/Kconfig"
812 822
813config HAVE_ARCH_EARLY_PFN_TO_NID 823config HAVE_ARCH_EARLY_PFN_TO_NID
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 2bfbddebdbf8..0d689335c8d6 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -25,6 +25,7 @@
25 25
26#include <linux/sched.h> 26#include <linux/sched.h>
27#include <linux/mm.h> 27#include <linux/mm.h>
28#include <linux/mmzone.h>
28#include <linux/tty.h> 29#include <linux/tty.h>
29#include <linux/ioport.h> 30#include <linux/ioport.h>
30#include <linux/acpi.h> 31#include <linux/acpi.h>
@@ -1022,7 +1023,7 @@ static void __init reserve_ebda_region(void)
1022 reserve_bootmem(addr, PAGE_SIZE); 1023 reserve_bootmem(addr, PAGE_SIZE);
1023} 1024}
1024 1025
1025#ifndef CONFIG_DISCONTIGMEM 1026#ifndef CONFIG_NEED_MULTIPLE_NODES
1026void __init setup_bootmem_allocator(void); 1027void __init setup_bootmem_allocator(void);
1027static unsigned long __init setup_memory(void) 1028static unsigned long __init setup_memory(void)
1028{ 1029{
@@ -1072,9 +1073,9 @@ void __init zone_sizes_init(void)
1072 free_area_init(zones_size); 1073 free_area_init(zones_size);
1073} 1074}
1074#else 1075#else
1075extern unsigned long setup_memory(void); 1076extern unsigned long __init setup_memory(void);
1076extern void zone_sizes_init(void); 1077extern void zone_sizes_init(void);
1077#endif /* !CONFIG_DISCONTIGMEM */ 1078#endif /* !CONFIG_NEED_MULTIPLE_NODES */
1078 1079
1079void __init setup_bootmem_allocator(void) 1080void __init setup_bootmem_allocator(void)
1080{ 1081{
@@ -1475,6 +1476,7 @@ void __init setup_arch(char **cmdline_p)
1475#endif 1476#endif
1476 paging_init(); 1477 paging_init();
1477 remapped_pgdat_init(); 1478 remapped_pgdat_init();
1479 sparse_init();
1478 zone_sizes_init(); 1480 zone_sizes_init();
1479 1481
1480 /* 1482 /*
diff --git a/arch/i386/mm/Makefile b/arch/i386/mm/Makefile
index fc3272506846..80908b5aa60f 100644
--- a/arch/i386/mm/Makefile
+++ b/arch/i386/mm/Makefile
@@ -4,7 +4,7 @@
4 4
5obj-y := init.o pgtable.o fault.o ioremap.o extable.o pageattr.o mmap.o 5obj-y := init.o pgtable.o fault.o ioremap.o extable.o pageattr.o mmap.o
6 6
7obj-$(CONFIG_DISCONTIGMEM) += discontig.o 7obj-$(CONFIG_NUMA) += discontig.o
8obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o 8obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
9obj-$(CONFIG_HIGHMEM) += highmem.o 9obj-$(CONFIG_HIGHMEM) += highmem.o
10obj-$(CONFIG_BOOT_IOREMAP) += boot_ioremap.o 10obj-$(CONFIG_BOOT_IOREMAP) += boot_ioremap.o
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
index 088ca4722183..0efeb96ba5d4 100644
--- a/arch/i386/mm/discontig.c
+++ b/arch/i386/mm/discontig.c
@@ -42,12 +42,16 @@ bootmem_data_t node0_bdata;
42 * populated the following initialisation. 42 * populated the following initialisation.
43 * 43 *
44 * 1) node_online_map - the map of all nodes configured (online) in the system 44 * 1) node_online_map - the map of all nodes configured (online) in the system
45 * 2) physnode_map - the mapping between a pfn and owning node 45 * 2) node_start_pfn - the starting page frame number for a node
46 * 3) node_start_pfn - the starting page frame number for a node
47 * 3) node_end_pfn - the ending page fram number for a node 46 * 3) node_end_pfn - the ending page fram number for a node
48 */ 47 */
48unsigned long node_start_pfn[MAX_NUMNODES];
49unsigned long node_end_pfn[MAX_NUMNODES];
50
49 51
52#ifdef CONFIG_DISCONTIGMEM
50/* 53/*
54 * 4) physnode_map - the mapping between a pfn and owning node
51 * physnode_map keeps track of the physical memory layout of a generic 55 * physnode_map keeps track of the physical memory layout of a generic
52 * numa node on a 256Mb break (each element of the array will 56 * numa node on a 256Mb break (each element of the array will
53 * represent 256Mb of memory and will be marked by the node id. so, 57 * represent 256Mb of memory and will be marked by the node id. so,
@@ -85,9 +89,7 @@ unsigned long node_memmap_size_bytes(int nid, unsigned long start_pfn,
85 89
86 return (nr_pages + 1) * sizeof(struct page); 90 return (nr_pages + 1) * sizeof(struct page);
87} 91}
88 92#endif
89unsigned long node_start_pfn[MAX_NUMNODES];
90unsigned long node_end_pfn[MAX_NUMNODES];
91 93
92extern unsigned long find_max_low_pfn(void); 94extern unsigned long find_max_low_pfn(void);
93extern void find_max_pfn(void); 95extern void find_max_pfn(void);
@@ -390,24 +392,26 @@ void __init set_highmem_pages_init(int bad_ppro)
390{ 392{
391#ifdef CONFIG_HIGHMEM 393#ifdef CONFIG_HIGHMEM
392 struct zone *zone; 394 struct zone *zone;
395 struct page *page;
393 396
394 for_each_zone(zone) { 397 for_each_zone(zone) {
395 unsigned long node_pfn, node_high_size, zone_start_pfn; 398 unsigned long node_pfn, zone_start_pfn, zone_end_pfn;
396 struct page * zone_mem_map; 399
397
398 if (!is_highmem(zone)) 400 if (!is_highmem(zone))
399 continue; 401 continue;
400 402
401 printk("Initializing %s for node %d\n", zone->name,
402 zone->zone_pgdat->node_id);
403
404 node_high_size = zone->spanned_pages;
405 zone_mem_map = zone->zone_mem_map;
406 zone_start_pfn = zone->zone_start_pfn; 403 zone_start_pfn = zone->zone_start_pfn;
404 zone_end_pfn = zone_start_pfn + zone->spanned_pages;
405
406 printk("Initializing %s for node %d (%08lx:%08lx)\n",
407 zone->name, zone->zone_pgdat->node_id,
408 zone_start_pfn, zone_end_pfn);
407 409
408 for (node_pfn = 0; node_pfn < node_high_size; node_pfn++) { 410 for (node_pfn = zone_start_pfn; node_pfn < zone_end_pfn; node_pfn++) {
409 one_highpage_init((struct page *)(zone_mem_map + node_pfn), 411 if (!pfn_valid(node_pfn))
410 zone_start_pfn + node_pfn, bad_ppro); 412 continue;
413 page = pfn_to_page(node_pfn);
414 one_highpage_init(page, node_pfn, bad_ppro);
411 } 415 }
412 } 416 }
413 totalram_pages += totalhigh_pages; 417 totalram_pages += totalhigh_pages;
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 666ca79fb50a..48ebfab77a3c 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -276,7 +276,9 @@ void __init one_highpage_init(struct page *page, int pfn, int bad_ppro)
276 SetPageReserved(page); 276 SetPageReserved(page);
277} 277}
278 278
279#ifndef CONFIG_DISCONTIGMEM 279#ifdef CONFIG_NUMA
280extern void set_highmem_pages_init(int);
281#else
280static void __init set_highmem_pages_init(int bad_ppro) 282static void __init set_highmem_pages_init(int bad_ppro)
281{ 283{
282 int pfn; 284 int pfn;
@@ -284,9 +286,7 @@ static void __init set_highmem_pages_init(int bad_ppro)
284 one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro); 286 one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro);
285 totalram_pages += totalhigh_pages; 287 totalram_pages += totalhigh_pages;
286} 288}
287#else 289#endif /* CONFIG_FLATMEM */
288extern void set_highmem_pages_init(int);
289#endif /* !CONFIG_DISCONTIGMEM */
290 290
291#else 291#else
292#define kmap_init() do { } while (0) 292#define kmap_init() do { } while (0)
@@ -297,10 +297,10 @@ extern void set_highmem_pages_init(int);
297unsigned long long __PAGE_KERNEL = _PAGE_KERNEL; 297unsigned long long __PAGE_KERNEL = _PAGE_KERNEL;
298unsigned long long __PAGE_KERNEL_EXEC = _PAGE_KERNEL_EXEC; 298unsigned long long __PAGE_KERNEL_EXEC = _PAGE_KERNEL_EXEC;
299 299
300#ifndef CONFIG_DISCONTIGMEM 300#ifdef CONFIG_NUMA
301#define remap_numa_kva() do {} while (0)
302#else
303extern void __init remap_numa_kva(void); 301extern void __init remap_numa_kva(void);
302#else
303#define remap_numa_kva() do {} while (0)
304#endif 304#endif
305 305
306static void __init pagetable_init (void) 306static void __init pagetable_init (void)
@@ -525,7 +525,7 @@ static void __init set_max_mapnr_init(void)
525#else 525#else
526 num_physpages = max_low_pfn; 526 num_physpages = max_low_pfn;
527#endif 527#endif
528#ifndef CONFIG_DISCONTIGMEM 528#ifdef CONFIG_FLATMEM
529 max_mapnr = num_physpages; 529 max_mapnr = num_physpages;
530#endif 530#endif
531} 531}
@@ -539,7 +539,7 @@ void __init mem_init(void)
539 int tmp; 539 int tmp;
540 int bad_ppro; 540 int bad_ppro;
541 541
542#ifndef CONFIG_DISCONTIGMEM 542#ifdef CONFIG_FLATMEM
543 if (!mem_map) 543 if (!mem_map)
544 BUG(); 544 BUG();
545#endif 545#endif
diff --git a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h
index 48e46d403aa6..33ce5d37e894 100644
--- a/include/asm-i386/mmzone.h
+++ b/include/asm-i386/mmzone.h
@@ -8,7 +8,9 @@
8 8
9#include <asm/smp.h> 9#include <asm/smp.h>
10 10
11#ifdef CONFIG_DISCONTIGMEM 11#if CONFIG_NUMA
12extern struct pglist_data *node_data[];
13#define NODE_DATA(nid) (node_data[nid])
12 14
13#ifdef CONFIG_NUMA 15#ifdef CONFIG_NUMA
14 #ifdef CONFIG_X86_NUMAQ 16 #ifdef CONFIG_X86_NUMAQ
@@ -21,8 +23,28 @@
21 #define get_zholes_size(n) (0) 23 #define get_zholes_size(n) (0)
22#endif /* CONFIG_NUMA */ 24#endif /* CONFIG_NUMA */
23 25
24extern struct pglist_data *node_data[]; 26extern int get_memcfg_numa_flat(void );
25#define NODE_DATA(nid) (node_data[nid]) 27/*
28 * This allows any one NUMA architecture to be compiled
29 * for, and still fall back to the flat function if it
30 * fails.
31 */
32static inline void get_memcfg_numa(void)
33{
34#ifdef CONFIG_X86_NUMAQ
35 if (get_memcfg_numaq())
36 return;
37#elif CONFIG_ACPI_SRAT
38 if (get_memcfg_from_srat())
39 return;
40#endif
41
42 get_memcfg_numa_flat();
43}
44
45#endif /* CONFIG_NUMA */
46
47#ifdef CONFIG_DISCONTIGMEM
26 48
27/* 49/*
28 * generic node memory support, the following assumptions apply: 50 * generic node memory support, the following assumptions apply:
@@ -48,26 +70,6 @@ static inline int pfn_to_nid(unsigned long pfn)
48#endif 70#endif
49} 71}
50 72
51/*
52 * Following are macros that are specific to this numa platform.
53 */
54#define reserve_bootmem(addr, size) \
55 reserve_bootmem_node(NODE_DATA(0), (addr), (size))
56#define alloc_bootmem(x) \
57 __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
58#define alloc_bootmem_low(x) \
59 __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, 0)
60#define alloc_bootmem_pages(x) \
61 __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
62#define alloc_bootmem_low_pages(x) \
63 __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
64#define alloc_bootmem_node(ignore, x) \
65 __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
66#define alloc_bootmem_pages_node(ignore, x) \
67 __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
68#define alloc_bootmem_low_pages_node(ignore, x) \
69 __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
70
71#define node_localnr(pfn, nid) ((pfn) - node_data[nid]->node_start_pfn) 73#define node_localnr(pfn, nid) ((pfn) - node_data[nid]->node_start_pfn)
72 74
73/* 75/*
@@ -121,28 +123,33 @@ static inline int pfn_valid(int pfn)
121 return (pfn < node_end_pfn(nid)); 123 return (pfn < node_end_pfn(nid));
122 return 0; 124 return 0;
123} 125}
124#endif 126#endif /* CONFIG_X86_NUMAQ */
127
128#endif /* CONFIG_DISCONTIGMEM */
129
130#ifdef CONFIG_NEED_MULTIPLE_NODES
125 131
126extern int get_memcfg_numa_flat(void );
127/* 132/*
128 * This allows any one NUMA architecture to be compiled 133 * Following are macros that are specific to this numa platform.
129 * for, and still fall back to the flat function if it
130 * fails.
131 */ 134 */
132static inline void get_memcfg_numa(void) 135#define reserve_bootmem(addr, size) \
133{ 136 reserve_bootmem_node(NODE_DATA(0), (addr), (size))
134#ifdef CONFIG_X86_NUMAQ 137#define alloc_bootmem(x) \
135 if (get_memcfg_numaq()) 138 __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
136 return; 139#define alloc_bootmem_low(x) \
137#elif CONFIG_ACPI_SRAT 140 __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, 0)
138 if (get_memcfg_from_srat()) 141#define alloc_bootmem_pages(x) \
139 return; 142 __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
140#endif 143#define alloc_bootmem_low_pages(x) \
141 144 __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
142 get_memcfg_numa_flat(); 145#define alloc_bootmem_node(ignore, x) \
143} 146 __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
147#define alloc_bootmem_pages_node(ignore, x) \
148 __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
149#define alloc_bootmem_low_pages_node(ignore, x) \
150 __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
144 151
145#endif /* CONFIG_DISCONTIGMEM */ 152#endif /* CONFIG_NEED_MULTIPLE_NODES */
146 153
147extern int early_pfn_to_nid(unsigned long pfn); 154extern int early_pfn_to_nid(unsigned long pfn);
148 155
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index 8f3dded01bff..dea8f8e6d86e 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -137,11 +137,11 @@ extern int page_is_ram(unsigned long pagenr);
137#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) 137#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
138#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) 138#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
139#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) 139#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
140#ifndef CONFIG_DISCONTIGMEM 140#ifdef CONFIG_FLATMEM
141#define pfn_to_page(pfn) (mem_map + (pfn)) 141#define pfn_to_page(pfn) (mem_map + (pfn))
142#define page_to_pfn(page) ((unsigned long)((page) - mem_map)) 142#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
143#define pfn_valid(pfn) ((pfn) < max_mapnr) 143#define pfn_valid(pfn) ((pfn) < max_mapnr)
144#endif /* !CONFIG_DISCONTIGMEM */ 144#endif /* CONFIG_FLATMEM */
145#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) 145#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
146 146
147#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) 147#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index e9efe148fdf7..77c6497f416e 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -398,9 +398,9 @@ extern void noexec_setup(const char *str);
398 398
399#endif /* !__ASSEMBLY__ */ 399#endif /* !__ASSEMBLY__ */
400 400
401#ifndef CONFIG_DISCONTIGMEM 401#ifdef CONFIG_FLATMEM
402#define kern_addr_valid(addr) (1) 402#define kern_addr_valid(addr) (1)
403#endif /* !CONFIG_DISCONTIGMEM */ 403#endif /* CONFIG_FLATMEM */
404 404
405#define io_remap_page_range(vma, vaddr, paddr, size, prot) \ 405#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
406 remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot) 406 remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
diff --git a/include/asm-i386/sparsemem.h b/include/asm-i386/sparsemem.h
new file mode 100644
index 000000000000..cfeed990585f
--- /dev/null
+++ b/include/asm-i386/sparsemem.h
@@ -0,0 +1,31 @@
1#ifndef _I386_SPARSEMEM_H
2#define _I386_SPARSEMEM_H
3#ifdef CONFIG_SPARSEMEM
4
5/*
6 * generic non-linear memory support:
7 *
8 * 1) we will not split memory into more chunks than will fit into the
9 * flags field of the struct page
10 */
11
12/*
13 * SECTION_SIZE_BITS 2^N: how big each section will be
14 * MAX_PHYSADDR_BITS 2^N: how much physical address space we have
15 * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space
16 */
17#ifdef CONFIG_X86_PAE
18#define SECTION_SIZE_BITS 30
19#define MAX_PHYSADDR_BITS 36
20#define MAX_PHYSMEM_BITS 36
21#else
22#define SECTION_SIZE_BITS 26
23#define MAX_PHYSADDR_BITS 32
24#define MAX_PHYSMEM_BITS 32
25#endif
26
27/* XXX: FIXME -- wli */
28#define kern_addr_valid(kaddr) (0)
29
30#endif /* CONFIG_SPARSEMEM */
31#endif /* _I386_SPARSEMEM_H */