aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/Kconfig1
-rw-r--r--include/linux/mmzone.h40
-rw-r--r--mm/Kconfig19
-rw-r--r--mm/sparse.c26
4 files changed, 49 insertions, 37 deletions
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index 619d843ba231..dcb0ad098c60 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -754,6 +754,7 @@ config NUMA
754 depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI)) 754 depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI))
755 default n if X86_PC 755 default n if X86_PC
756 default y if (X86_NUMAQ || X86_SUMMIT) 756 default y if (X86_NUMAQ || X86_SUMMIT)
757 select SPARSEMEM_STATIC
757 758
758# Need comments to help the hapless user trying to turn on NUMA support 759# Need comments to help the hapless user trying to turn on NUMA support
759comment "NUMA (NUMA-Q) requires SMP, 64GB highmem support" 760comment "NUMA (NUMA-Q) requires SMP, 64GB highmem support"
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index b97054bbc394..79cf578e21b9 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -487,39 +487,29 @@ struct mem_section {
487 unsigned long section_mem_map; 487 unsigned long section_mem_map;
488}; 488};
489 489
490#ifdef CONFIG_ARCH_SPARSEMEM_EXTREME 490#ifdef CONFIG_SPARSEMEM_EXTREME
491/* 491#define SECTIONS_PER_ROOT (PAGE_SIZE / sizeof (struct mem_section))
492 * Should we ever require GCC 4 or later then the flat array scheme 492#else
493 * can be eliminated and a uniform solution for EXTREME and !EXTREME can 493#define SECTIONS_PER_ROOT 1
494 * be arrived at. 494#endif
495 */
496#define SECTION_ROOT_SHIFT (PAGE_SHIFT-3)
497#define SECTION_ROOT_MASK ((1UL<<SECTION_ROOT_SHIFT) - 1)
498#define SECTION_TO_ROOT(_sec) ((_sec) >> SECTION_ROOT_SHIFT)
499#define NR_SECTION_ROOTS (NR_MEM_SECTIONS >> SECTION_ROOT_SHIFT)
500 495
501extern struct mem_section *mem_section[NR_SECTION_ROOTS]; 496#define SECTION_NR_TO_ROOT(sec) ((sec) / SECTIONS_PER_ROOT)
502 497#define NR_SECTION_ROOTS (NR_MEM_SECTIONS / SECTIONS_PER_ROOT)
503static inline struct mem_section *__nr_to_section(unsigned long nr) 498#define SECTION_ROOT_MASK (SECTIONS_PER_ROOT - 1)
504{
505 if (!mem_section[SECTION_TO_ROOT(nr)])
506 return NULL;
507 return &mem_section[SECTION_TO_ROOT(nr)][nr & SECTION_ROOT_MASK];
508}
509 499
500#ifdef CONFIG_SPARSEMEM_EXTREME
501extern struct mem_section *mem_section[NR_SECTION_ROOTS];
510#else 502#else
511 503extern struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT];
512extern struct mem_section mem_section[NR_MEM_SECTIONS]; 504#endif
513 505
514static inline struct mem_section *__nr_to_section(unsigned long nr) 506static inline struct mem_section *__nr_to_section(unsigned long nr)
515{ 507{
516 return &mem_section[nr]; 508 if (!mem_section[SECTION_NR_TO_ROOT(nr)])
509 return NULL;
510 return &mem_section[SECTION_NR_TO_ROOT(nr)][nr & SECTION_ROOT_MASK];
517} 511}
518 512
519#define sparse_index_init(_sec, _nid) do {} while (0)
520
521#endif
522
523/* 513/*
524 * We use the lower bits of the mem_map pointer to store 514 * We use the lower bits of the mem_map pointer to store
525 * a little bit of information. There should be at least 515 * a little bit of information. There should be at least
diff --git a/mm/Kconfig b/mm/Kconfig
index fc644c5c065d..4e9937ac3529 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -91,10 +91,23 @@ config HAVE_MEMORY_PRESENT
91 depends on ARCH_HAVE_MEMORY_PRESENT || SPARSEMEM 91 depends on ARCH_HAVE_MEMORY_PRESENT || SPARSEMEM
92 92
93# 93#
94# SPARSEMEM_EXTREME (which is the default) does some bootmem
95# allocations when memory_present() is called. If this can not
96# be done on your architecture, select this option. However,
97# statically allocating the mem_section[] array can potentially
98# consume vast quantities of .bss, so be careful.
99#
100# This option will also potentially produce smaller runtime code
101# with gcc 3.4 and later.
102#
103config SPARSEMEM_STATIC
104 def_bool n
105
106#
94# Architectecture platforms which require a two level mem_section in SPARSEMEM 107# Architectecture platforms which require a two level mem_section in SPARSEMEM
95# must select this option. This is usually for architecture platforms with 108# must select this option. This is usually for architecture platforms with
96# an extremely sparse physical address space. 109# an extremely sparse physical address space.
97# 110#
98config ARCH_SPARSEMEM_EXTREME 111config SPARSEMEM_EXTREME
99 def_bool n 112 def_bool y
100 depends on SPARSEMEM && 64BIT 113 depends on SPARSEMEM && !SPARSEMEM_STATIC
diff --git a/mm/sparse.c b/mm/sparse.c
index b2b456bf0a5d..fa01292157a9 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -13,28 +13,36 @@
13 * 13 *
14 * 1) mem_section - memory sections, mem_map's for valid memory 14 * 1) mem_section - memory sections, mem_map's for valid memory
15 */ 15 */
16#ifdef CONFIG_ARCH_SPARSEMEM_EXTREME 16#ifdef CONFIG_SPARSEMEM_EXTREME
17struct mem_section *mem_section[NR_SECTION_ROOTS] 17struct mem_section *mem_section[NR_SECTION_ROOTS]
18 ____cacheline_maxaligned_in_smp; 18 ____cacheline_maxaligned_in_smp;
19#else
20struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT]
21 ____cacheline_maxaligned_in_smp;
22#endif
23EXPORT_SYMBOL(mem_section);
24
25static void sparse_alloc_root(unsigned long root, int nid)
26{
27#ifdef CONFIG_SPARSEMEM_EXTREME
28 mem_section[root] = alloc_bootmem_node(NODE_DATA(nid), PAGE_SIZE);
29#endif
30}
19 31
20static void sparse_index_init(unsigned long section, int nid) 32static void sparse_index_init(unsigned long section, int nid)
21{ 33{
22 unsigned long root = SECTION_TO_ROOT(section); 34 unsigned long root = SECTION_NR_TO_ROOT(section);
23 35
24 if (mem_section[root]) 36 if (mem_section[root])
25 return; 37 return;
26 mem_section[root] = alloc_bootmem_node(NODE_DATA(nid), PAGE_SIZE); 38
39 sparse_alloc_root(root, nid);
40
27 if (mem_section[root]) 41 if (mem_section[root])
28 memset(mem_section[root], 0, PAGE_SIZE); 42 memset(mem_section[root], 0, PAGE_SIZE);
29 else 43 else
30 panic("memory_present: NO MEMORY\n"); 44 panic("memory_present: NO MEMORY\n");
31} 45}
32#else
33struct mem_section mem_section[NR_MEM_SECTIONS]
34 ____cacheline_maxaligned_in_smp;
35#endif
36EXPORT_SYMBOL(mem_section);
37
38/* Record a memory area against a node. */ 46/* Record a memory area against a node. */
39void memory_present(int nid, unsigned long start, unsigned long end) 47void memory_present(int nid, unsigned long start, unsigned long end)
40{ 48{