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 | { |
