diff options
-rw-r--r-- | arch/x86_64/mm/numa.c | 1 | ||||
-rw-r--r-- | arch/x86_64/mm/srat.c | 76 | ||||
-rw-r--r-- | drivers/acpi/numa.c | 11 | ||||
-rw-r--r-- | include/acpi/acpi_numa.h | 1 | ||||
-rw-r--r-- | include/asm-x86_64/acpi.h | 11 | ||||
-rw-r--r-- | include/linux/acpi.h | 3 |
6 files changed, 96 insertions, 7 deletions
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index 51548947ad3..30bf8043984 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c | |||
@@ -484,6 +484,7 @@ out: | |||
484 | nodes[i].end >> PAGE_SHIFT); | 484 | nodes[i].end >> PAGE_SHIFT); |
485 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); | 485 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); |
486 | } | 486 | } |
487 | acpi_fake_nodes(nodes, num_nodes); | ||
487 | numa_init_array(); | 488 | numa_init_array(); |
488 | return 0; | 489 | return 0; |
489 | } | 490 | } |
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c index 0e0725db20b..7ac8ff333e8 100644 --- a/arch/x86_64/mm/srat.c +++ b/arch/x86_64/mm/srat.c | |||
@@ -350,7 +350,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) | |||
350 | 350 | ||
351 | /* Sanity check to catch more bad SRATs (they are amazingly common). | 351 | /* Sanity check to catch more bad SRATs (they are amazingly common). |
352 | Make sure the PXMs cover all memory. */ | 352 | Make sure the PXMs cover all memory. */ |
353 | static int nodes_cover_memory(void) | 353 | static int __init nodes_cover_memory(const struct bootnode *nodes) |
354 | { | 354 | { |
355 | int i; | 355 | int i; |
356 | unsigned long pxmram, e820ram; | 356 | unsigned long pxmram, e820ram; |
@@ -406,7 +406,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) | |||
406 | } | 406 | } |
407 | } | 407 | } |
408 | 408 | ||
409 | if (!nodes_cover_memory()) { | 409 | if (!nodes_cover_memory(nodes)) { |
410 | bad_srat(); | 410 | bad_srat(); |
411 | return -1; | 411 | return -1; |
412 | } | 412 | } |
@@ -440,6 +440,75 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) | |||
440 | return 0; | 440 | return 0; |
441 | } | 441 | } |
442 | 442 | ||
443 | #ifdef CONFIG_NUMA_EMU | ||
444 | static int __init find_node_by_addr(unsigned long addr) | ||
445 | { | ||
446 | int ret = NUMA_NO_NODE; | ||
447 | int i; | ||
448 | |||
449 | for_each_node_mask(i, nodes_parsed) { | ||
450 | /* | ||
451 | * Find the real node that this emulated node appears on. For | ||
452 | * the sake of simplicity, we only use a real node's starting | ||
453 | * address to determine which emulated node it appears on. | ||
454 | */ | ||
455 | if (addr >= nodes[i].start && addr < nodes[i].end) { | ||
456 | ret = i; | ||
457 | break; | ||
458 | } | ||
459 | } | ||
460 | return i; | ||
461 | } | ||
462 | |||
463 | /* | ||
464 | * In NUMA emulation, we need to setup proximity domain (_PXM) to node ID | ||
465 | * mappings that respect the real ACPI topology but reflect our emulated | ||
466 | * environment. For each emulated node, we find which real node it appears on | ||
467 | * and create PXM to NID mappings for those fake nodes which mirror that | ||
468 | * locality. SLIT will now represent the correct distances between emulated | ||
469 | * nodes as a result of the real topology. | ||
470 | */ | ||
471 | void __init acpi_fake_nodes(const struct bootnode *fake_nodes, int num_nodes) | ||
472 | { | ||
473 | int i; | ||
474 | int fake_node_to_pxm_map[MAX_NUMNODES] = { | ||
475 | [0 ... MAX_NUMNODES-1] = PXM_INVAL | ||
476 | }; | ||
477 | |||
478 | printk(KERN_INFO "Faking PXM affinity for fake nodes on real " | ||
479 | "topology.\n"); | ||
480 | for (i = 0; i < num_nodes; i++) { | ||
481 | int nid, pxm; | ||
482 | |||
483 | nid = find_node_by_addr(fake_nodes[i].start); | ||
484 | if (nid == NUMA_NO_NODE) | ||
485 | continue; | ||
486 | pxm = node_to_pxm(nid); | ||
487 | if (pxm == PXM_INVAL) | ||
488 | continue; | ||
489 | fake_node_to_pxm_map[i] = pxm; | ||
490 | } | ||
491 | for (i = 0; i < num_nodes; i++) | ||
492 | __acpi_map_pxm_to_node(fake_node_to_pxm_map[i], i); | ||
493 | |||
494 | nodes_clear(nodes_parsed); | ||
495 | for (i = 0; i < num_nodes; i++) | ||
496 | if (fake_nodes[i].start != fake_nodes[i].end) | ||
497 | node_set(i, nodes_parsed); | ||
498 | WARN_ON(!nodes_cover_memory(fake_nodes)); | ||
499 | } | ||
500 | |||
501 | static int null_slit_node_compare(int a, int b) | ||
502 | { | ||
503 | return node_to_pxm(a) == node_to_pxm(b); | ||
504 | } | ||
505 | #else | ||
506 | static int null_slit_node_compare(int a, int b) | ||
507 | { | ||
508 | return a == b; | ||
509 | } | ||
510 | #endif /* CONFIG_NUMA_EMU */ | ||
511 | |||
443 | void __init srat_reserve_add_area(int nodeid) | 512 | void __init srat_reserve_add_area(int nodeid) |
444 | { | 513 | { |
445 | if (found_add_area && nodes_add[nodeid].end) { | 514 | if (found_add_area && nodes_add[nodeid].end) { |
@@ -464,7 +533,8 @@ int __node_distance(int a, int b) | |||
464 | int index; | 533 | int index; |
465 | 534 | ||
466 | if (!acpi_slit) | 535 | if (!acpi_slit) |
467 | return a == b ? LOCAL_DISTANCE : REMOTE_DISTANCE; | 536 | return null_slit_node_compare(a, b) ? LOCAL_DISTANCE : |
537 | REMOTE_DISTANCE; | ||
468 | index = acpi_slit->locality_count * node_to_pxm(a); | 538 | index = acpi_slit->locality_count * node_to_pxm(a); |
469 | return acpi_slit->entry[index + node_to_pxm(b)]; | 539 | return acpi_slit->entry[index + node_to_pxm(b)]; |
470 | } | 540 | } |
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 6c44b522f4d..ab04d848b19 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c | |||
@@ -36,8 +36,6 @@ | |||
36 | ACPI_MODULE_NAME("numa"); | 36 | ACPI_MODULE_NAME("numa"); |
37 | 37 | ||
38 | static nodemask_t nodes_found_map = NODE_MASK_NONE; | 38 | static nodemask_t nodes_found_map = NODE_MASK_NONE; |
39 | #define PXM_INVAL -1 | ||
40 | #define NID_INVAL -1 | ||
41 | 39 | ||
42 | /* maps to convert between proximity domain and logical node ID */ | 40 | /* maps to convert between proximity domain and logical node ID */ |
43 | static int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS] | 41 | static int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS] |
@@ -59,6 +57,12 @@ int node_to_pxm(int node) | |||
59 | return node_to_pxm_map[node]; | 57 | return node_to_pxm_map[node]; |
60 | } | 58 | } |
61 | 59 | ||
60 | void __acpi_map_pxm_to_node(int pxm, int node) | ||
61 | { | ||
62 | pxm_to_node_map[pxm] = node; | ||
63 | node_to_pxm_map[node] = pxm; | ||
64 | } | ||
65 | |||
62 | int acpi_map_pxm_to_node(int pxm) | 66 | int acpi_map_pxm_to_node(int pxm) |
63 | { | 67 | { |
64 | int node = pxm_to_node_map[pxm]; | 68 | int node = pxm_to_node_map[pxm]; |
@@ -67,8 +71,7 @@ int acpi_map_pxm_to_node(int pxm) | |||
67 | if (nodes_weight(nodes_found_map) >= MAX_NUMNODES) | 71 | if (nodes_weight(nodes_found_map) >= MAX_NUMNODES) |
68 | return NID_INVAL; | 72 | return NID_INVAL; |
69 | node = first_unset_node(nodes_found_map); | 73 | node = first_unset_node(nodes_found_map); |
70 | pxm_to_node_map[pxm] = node; | 74 | __acpi_map_pxm_to_node(pxm, node); |
71 | node_to_pxm_map[node] = pxm; | ||
72 | node_set(node, nodes_found_map); | 75 | node_set(node, nodes_found_map); |
73 | } | 76 | } |
74 | 77 | ||
diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h index e2fcee2b340..62c5ee4311d 100644 --- a/include/acpi/acpi_numa.h +++ b/include/acpi/acpi_numa.h | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | extern int pxm_to_node(int); | 14 | extern int pxm_to_node(int); |
15 | extern int node_to_pxm(int); | 15 | extern int node_to_pxm(int); |
16 | extern void __acpi_map_pxm_to_node(int, int); | ||
16 | extern int acpi_map_pxm_to_node(int); | 17 | extern int acpi_map_pxm_to_node(int); |
17 | extern void __cpuinit acpi_unmap_pxm_to_node(int); | 18 | extern void __cpuinit acpi_unmap_pxm_to_node(int); |
18 | 19 | ||
diff --git a/include/asm-x86_64/acpi.h b/include/asm-x86_64/acpi.h index a29f05087a3..1da8f49c0fe 100644 --- a/include/asm-x86_64/acpi.h +++ b/include/asm-x86_64/acpi.h | |||
@@ -29,6 +29,7 @@ | |||
29 | #ifdef __KERNEL__ | 29 | #ifdef __KERNEL__ |
30 | 30 | ||
31 | #include <acpi/pdc_intel.h> | 31 | #include <acpi/pdc_intel.h> |
32 | #include <asm/numa.h> | ||
32 | 33 | ||
33 | #define COMPILER_DEPENDENT_INT64 long long | 34 | #define COMPILER_DEPENDENT_INT64 long long |
34 | #define COMPILER_DEPENDENT_UINT64 unsigned long long | 35 | #define COMPILER_DEPENDENT_UINT64 unsigned long long |
@@ -141,6 +142,16 @@ extern int acpi_pci_disabled; | |||
141 | extern int acpi_skip_timer_override; | 142 | extern int acpi_skip_timer_override; |
142 | extern int acpi_use_timer_override; | 143 | extern int acpi_use_timer_override; |
143 | 144 | ||
145 | #ifdef CONFIG_ACPI_NUMA | ||
146 | extern void __init acpi_fake_nodes(const struct bootnode *fake_nodes, | ||
147 | int num_nodes); | ||
148 | #else | ||
149 | static inline void acpi_fake_nodes(const struct bootnode *fake_nodes, | ||
150 | int num_nodes) | ||
151 | { | ||
152 | } | ||
153 | #endif | ||
154 | |||
144 | #endif /*__KERNEL__*/ | 155 | #endif /*__KERNEL__*/ |
145 | 156 | ||
146 | #endif /*_ASM_ACPI_H*/ | 157 | #endif /*_ASM_ACPI_H*/ |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index e88b62e6b3a..d5680cd7746 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -231,6 +231,9 @@ extern int acpi_paddr_to_node(u64 start_addr, u64 size); | |||
231 | 231 | ||
232 | extern int pnpacpi_disabled; | 232 | extern int pnpacpi_disabled; |
233 | 233 | ||
234 | #define PXM_INVAL (-1) | ||
235 | #define NID_INVAL (-1) | ||
236 | |||
234 | #else /* CONFIG_ACPI */ | 237 | #else /* CONFIG_ACPI */ |
235 | 238 | ||
236 | static inline int acpi_boot_init(void) | 239 | static inline int acpi_boot_init(void) |