diff options
author | Suresh Siddha <suresh.b.siddha@intel.com> | 2008-03-25 13:14:35 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-04-19 13:19:55 -0400 |
commit | 6ec6e0d9f2fd7cb6ca6bc3bfab5ae7b5cdd8c36f (patch) | |
tree | bf05991fd8ecf8acd76fc48f5613ddc7bcb6926f /arch/x86/mm/srat_64.c | |
parent | 8705a49c35be088a50b8d5fc5e1aa24d6711fd5b (diff) |
srat, x86: add support for nodes spanning other nodes
For example, If the physical address layout on a two node system with 8 GB
memory is something like:
node 0: 0-2GB, 4-6GB
node 1: 2-4GB, 6-8GB
Current kernels fail to boot/detect this NUMA topology.
ACPI SRAT tables can expose such a topology which needs to be supported.
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/mm/srat_64.c')
-rw-r--r-- | arch/x86/mm/srat_64.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index 1bae9c855ceb..fb43d89f46f3 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c | |||
@@ -32,6 +32,10 @@ static struct bootnode nodes_add[MAX_NUMNODES]; | |||
32 | static int found_add_area __initdata; | 32 | static int found_add_area __initdata; |
33 | int hotadd_percent __initdata = 0; | 33 | int hotadd_percent __initdata = 0; |
34 | 34 | ||
35 | static int num_node_memblks __initdata; | ||
36 | static struct bootnode node_memblk_range[NR_NODE_MEMBLKS] __initdata; | ||
37 | static int memblk_nodeid[NR_NODE_MEMBLKS] __initdata; | ||
38 | |||
35 | /* Too small nodes confuse the VM badly. Usually they result | 39 | /* Too small nodes confuse the VM badly. Usually they result |
36 | from BIOS bugs. */ | 40 | from BIOS bugs. */ |
37 | #define NODE_MIN_SIZE (4*1024*1024) | 41 | #define NODE_MIN_SIZE (4*1024*1024) |
@@ -41,17 +45,17 @@ static __init int setup_node(int pxm) | |||
41 | return acpi_map_pxm_to_node(pxm); | 45 | return acpi_map_pxm_to_node(pxm); |
42 | } | 46 | } |
43 | 47 | ||
44 | static __init int conflicting_nodes(unsigned long start, unsigned long end) | 48 | static __init int conflicting_memblks(unsigned long start, unsigned long end) |
45 | { | 49 | { |
46 | int i; | 50 | int i; |
47 | for_each_node_mask(i, nodes_parsed) { | 51 | for (i = 0; i < num_node_memblks; i++) { |
48 | struct bootnode *nd = &nodes[i]; | 52 | struct bootnode *nd = &node_memblk_range[i]; |
49 | if (nd->start == nd->end) | 53 | if (nd->start == nd->end) |
50 | continue; | 54 | continue; |
51 | if (nd->end > start && nd->start < end) | 55 | if (nd->end > start && nd->start < end) |
52 | return i; | 56 | return memblk_nodeid[i]; |
53 | if (nd->end == end && nd->start == start) | 57 | if (nd->end == end && nd->start == start) |
54 | return i; | 58 | return memblk_nodeid[i]; |
55 | } | 59 | } |
56 | return -1; | 60 | return -1; |
57 | } | 61 | } |
@@ -258,7 +262,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) | |||
258 | bad_srat(); | 262 | bad_srat(); |
259 | return; | 263 | return; |
260 | } | 264 | } |
261 | i = conflicting_nodes(start, end); | 265 | i = conflicting_memblks(start, end); |
262 | if (i == node) { | 266 | if (i == node) { |
263 | printk(KERN_WARNING | 267 | printk(KERN_WARNING |
264 | "SRAT: Warning: PXM %d (%lx-%lx) overlaps with itself (%Lx-%Lx)\n", | 268 | "SRAT: Warning: PXM %d (%lx-%lx) overlaps with itself (%Lx-%Lx)\n", |
@@ -283,10 +287,10 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) | |||
283 | nd->end = end; | 287 | nd->end = end; |
284 | } | 288 | } |
285 | 289 | ||
286 | printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm, | 290 | printk(KERN_INFO "SRAT: Node %u PXM %u %lx-%lx\n", node, pxm, |
287 | nd->start, nd->end); | 291 | start, end); |
288 | e820_register_active_regions(node, nd->start >> PAGE_SHIFT, | 292 | e820_register_active_regions(node, start >> PAGE_SHIFT, |
289 | nd->end >> PAGE_SHIFT); | 293 | end >> PAGE_SHIFT); |
290 | push_node_boundaries(node, nd->start >> PAGE_SHIFT, | 294 | push_node_boundaries(node, nd->start >> PAGE_SHIFT, |
291 | nd->end >> PAGE_SHIFT); | 295 | nd->end >> PAGE_SHIFT); |
292 | 296 | ||
@@ -298,6 +302,11 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) | |||
298 | if ((nd->start | nd->end) == 0) | 302 | if ((nd->start | nd->end) == 0) |
299 | node_clear(node, nodes_parsed); | 303 | node_clear(node, nodes_parsed); |
300 | } | 304 | } |
305 | |||
306 | node_memblk_range[num_node_memblks].start = start; | ||
307 | node_memblk_range[num_node_memblks].end = end; | ||
308 | memblk_nodeid[num_node_memblks] = node; | ||
309 | num_node_memblks++; | ||
301 | } | 310 | } |
302 | 311 | ||
303 | /* Sanity check to catch more bad SRATs (they are amazingly common). | 312 | /* Sanity check to catch more bad SRATs (they are amazingly common). |
@@ -368,7 +377,8 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) | |||
368 | return -1; | 377 | return -1; |
369 | } | 378 | } |
370 | 379 | ||
371 | memnode_shift = compute_hash_shift(nodes, MAX_NUMNODES); | 380 | memnode_shift = compute_hash_shift(node_memblk_range, num_node_memblks, |
381 | memblk_nodeid); | ||
372 | if (memnode_shift < 0) { | 382 | if (memnode_shift < 0) { |
373 | printk(KERN_ERR | 383 | printk(KERN_ERR |
374 | "SRAT: No NUMA node hash function found. Contact maintainer\n"); | 384 | "SRAT: No NUMA node hash function found. Contact maintainer\n"); |