diff options
-rw-r--r-- | arch/i386/Kconfig | 1 | ||||
-rw-r--r-- | include/linux/mmzone.h | 40 | ||||
-rw-r--r-- | mm/Kconfig | 19 | ||||
-rw-r--r-- | mm/sparse.c | 26 |
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 |
759 | comment "NUMA (NUMA-Q) requires SMP, 64GB highmem support" | 760 | comment "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 | ||
501 | extern 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) | |
503 | static 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 | ||
501 | extern struct mem_section *mem_section[NR_SECTION_ROOTS]; | ||
510 | #else | 502 | #else |
511 | 503 | extern struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT]; | |
512 | extern struct mem_section mem_section[NR_MEM_SECTIONS]; | 504 | #endif |
513 | 505 | ||
514 | static inline struct mem_section *__nr_to_section(unsigned long nr) | 506 | static 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 | # | ||
103 | config 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 | # |
98 | config ARCH_SPARSEMEM_EXTREME | 111 | config 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 |
17 | struct mem_section *mem_section[NR_SECTION_ROOTS] | 17 | struct mem_section *mem_section[NR_SECTION_ROOTS] |
18 | ____cacheline_maxaligned_in_smp; | 18 | ____cacheline_maxaligned_in_smp; |
19 | #else | ||
20 | struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT] | ||
21 | ____cacheline_maxaligned_in_smp; | ||
22 | #endif | ||
23 | EXPORT_SYMBOL(mem_section); | ||
24 | |||
25 | static 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 | ||
20 | static void sparse_index_init(unsigned long section, int nid) | 32 | static 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 | ||
33 | struct mem_section mem_section[NR_MEM_SECTIONS] | ||
34 | ____cacheline_maxaligned_in_smp; | ||
35 | #endif | ||
36 | EXPORT_SYMBOL(mem_section); | ||
37 | |||
38 | /* Record a memory area against a node. */ | 46 | /* Record a memory area against a node. */ |
39 | void memory_present(int nid, unsigned long start, unsigned long end) | 47 | void memory_present(int nid, unsigned long start, unsigned long end) |
40 | { | 48 | { |