diff options
author | Ingo Molnar <mingo@elte.hu> | 2011-01-10 03:35:57 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-01-10 03:36:07 -0500 |
commit | 9adcc4a127be6c979eae1ae34083261f2ec5dfec (patch) | |
tree | 93652985f5dc4c0e38fda60dd03fca2583932094 | |
parent | 30285c6f03be05f6f894b50d03bcb638886e3936 (diff) | |
parent | d906f0eb2f0e6d1a24c479f69a9c39e7e45c5ae8 (diff) |
Merge branch 'x86/numa' into x86/urgent
Merge reason: Topic is ready for upstream.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/include/asm/acpi.h | 11 | ||||
-rw-r--r-- | arch/x86/include/asm/amd_nb.h | 6 | ||||
-rw-r--r-- | arch/x86/include/asm/numa_64.h | 2 | ||||
-rw-r--r-- | arch/x86/mm/amdtopology_64.c | 86 | ||||
-rw-r--r-- | arch/x86/mm/numa_64.c | 157 | ||||
-rw-r--r-- | arch/x86/mm/srat_64.c | 26 |
6 files changed, 225 insertions, 63 deletions
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 55d106b5e31b..211ca3f7fd16 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h | |||
@@ -185,17 +185,16 @@ struct bootnode; | |||
185 | 185 | ||
186 | #ifdef CONFIG_ACPI_NUMA | 186 | #ifdef CONFIG_ACPI_NUMA |
187 | extern int acpi_numa; | 187 | extern int acpi_numa; |
188 | extern int acpi_get_nodes(struct bootnode *physnodes); | 188 | extern void acpi_get_nodes(struct bootnode *physnodes, unsigned long start, |
189 | unsigned long end); | ||
189 | extern int acpi_scan_nodes(unsigned long start, unsigned long end); | 190 | extern int acpi_scan_nodes(unsigned long start, unsigned long end); |
190 | #define NR_NODE_MEMBLKS (MAX_NUMNODES*2) | 191 | #define NR_NODE_MEMBLKS (MAX_NUMNODES*2) |
192 | |||
193 | #ifdef CONFIG_NUMA_EMU | ||
191 | extern void acpi_fake_nodes(const struct bootnode *fake_nodes, | 194 | extern void acpi_fake_nodes(const struct bootnode *fake_nodes, |
192 | int num_nodes); | 195 | int num_nodes); |
193 | #else | ||
194 | static inline void acpi_fake_nodes(const struct bootnode *fake_nodes, | ||
195 | int num_nodes) | ||
196 | { | ||
197 | } | ||
198 | #endif | 196 | #endif |
197 | #endif /* CONFIG_ACPI_NUMA */ | ||
199 | 198 | ||
200 | #define acpi_unlazy_tlb(x) leave_mm(x) | 199 | #define acpi_unlazy_tlb(x) leave_mm(x) |
201 | 200 | ||
diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h index 6aee50d655d1..980f22567631 100644 --- a/arch/x86/include/asm/amd_nb.h +++ b/arch/x86/include/asm/amd_nb.h | |||
@@ -9,10 +9,14 @@ struct bootnode; | |||
9 | extern int early_is_amd_nb(u32 value); | 9 | extern int early_is_amd_nb(u32 value); |
10 | extern int amd_cache_northbridges(void); | 10 | extern int amd_cache_northbridges(void); |
11 | extern void amd_flush_garts(void); | 11 | extern void amd_flush_garts(void); |
12 | extern int amd_get_nodes(struct bootnode *nodes); | ||
13 | extern int amd_numa_init(unsigned long start_pfn, unsigned long end_pfn); | 12 | extern int amd_numa_init(unsigned long start_pfn, unsigned long end_pfn); |
14 | extern int amd_scan_nodes(void); | 13 | extern int amd_scan_nodes(void); |
15 | 14 | ||
15 | #ifdef CONFIG_NUMA_EMU | ||
16 | extern void amd_fake_nodes(const struct bootnode *nodes, int nr_nodes); | ||
17 | extern void amd_get_nodes(struct bootnode *nodes); | ||
18 | #endif | ||
19 | |||
16 | struct amd_northbridge { | 20 | struct amd_northbridge { |
17 | struct pci_dev *misc; | 21 | struct pci_dev *misc; |
18 | }; | 22 | }; |
diff --git a/arch/x86/include/asm/numa_64.h b/arch/x86/include/asm/numa_64.h index 823e070e7c26..5ae87285a502 100644 --- a/arch/x86/include/asm/numa_64.h +++ b/arch/x86/include/asm/numa_64.h | |||
@@ -38,7 +38,7 @@ extern void __cpuinit numa_add_cpu(int cpu); | |||
38 | extern void __cpuinit numa_remove_cpu(int cpu); | 38 | extern void __cpuinit numa_remove_cpu(int cpu); |
39 | 39 | ||
40 | #ifdef CONFIG_NUMA_EMU | 40 | #ifdef CONFIG_NUMA_EMU |
41 | #define FAKE_NODE_MIN_SIZE ((u64)64 << 20) | 41 | #define FAKE_NODE_MIN_SIZE ((u64)32 << 20) |
42 | #define FAKE_NODE_MIN_HASH_MASK (~(FAKE_NODE_MIN_SIZE - 1UL)) | 42 | #define FAKE_NODE_MIN_HASH_MASK (~(FAKE_NODE_MIN_SIZE - 1UL)) |
43 | #endif /* CONFIG_NUMA_EMU */ | 43 | #endif /* CONFIG_NUMA_EMU */ |
44 | #else | 44 | #else |
diff --git a/arch/x86/mm/amdtopology_64.c b/arch/x86/mm/amdtopology_64.c index 08a0069b87a5..f21962c435ed 100644 --- a/arch/x86/mm/amdtopology_64.c +++ b/arch/x86/mm/amdtopology_64.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <asm/amd_nb.h> | 27 | #include <asm/amd_nb.h> |
28 | 28 | ||
29 | static struct bootnode __initdata nodes[8]; | 29 | static struct bootnode __initdata nodes[8]; |
30 | static unsigned char __initdata nodeids[8]; | ||
30 | static nodemask_t __initdata nodes_parsed = NODE_MASK_NONE; | 31 | static nodemask_t __initdata nodes_parsed = NODE_MASK_NONE; |
31 | 32 | ||
32 | static __init int find_northbridge(void) | 33 | static __init int find_northbridge(void) |
@@ -68,19 +69,6 @@ static __init void early_get_boot_cpu_id(void) | |||
68 | #endif | 69 | #endif |
69 | } | 70 | } |
70 | 71 | ||
71 | int __init amd_get_nodes(struct bootnode *physnodes) | ||
72 | { | ||
73 | int i; | ||
74 | int ret = 0; | ||
75 | |||
76 | for_each_node_mask(i, nodes_parsed) { | ||
77 | physnodes[ret].start = nodes[i].start; | ||
78 | physnodes[ret].end = nodes[i].end; | ||
79 | ret++; | ||
80 | } | ||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) | 72 | int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) |
85 | { | 73 | { |
86 | unsigned long start = PFN_PHYS(start_pfn); | 74 | unsigned long start = PFN_PHYS(start_pfn); |
@@ -113,7 +101,7 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) | |||
113 | base = read_pci_config(0, nb, 1, 0x40 + i*8); | 101 | base = read_pci_config(0, nb, 1, 0x40 + i*8); |
114 | limit = read_pci_config(0, nb, 1, 0x44 + i*8); | 102 | limit = read_pci_config(0, nb, 1, 0x44 + i*8); |
115 | 103 | ||
116 | nodeid = limit & 7; | 104 | nodeids[i] = nodeid = limit & 7; |
117 | if ((base & 3) == 0) { | 105 | if ((base & 3) == 0) { |
118 | if (i < numnodes) | 106 | if (i < numnodes) |
119 | pr_info("Skipping disabled node %d\n", i); | 107 | pr_info("Skipping disabled node %d\n", i); |
@@ -193,6 +181,76 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) | |||
193 | return 0; | 181 | return 0; |
194 | } | 182 | } |
195 | 183 | ||
184 | #ifdef CONFIG_NUMA_EMU | ||
185 | static s16 fake_apicid_to_node[MAX_LOCAL_APIC] __initdata = { | ||
186 | [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE | ||
187 | }; | ||
188 | |||
189 | void __init amd_get_nodes(struct bootnode *physnodes) | ||
190 | { | ||
191 | int i; | ||
192 | |||
193 | for_each_node_mask(i, nodes_parsed) { | ||
194 | physnodes[i].start = nodes[i].start; | ||
195 | physnodes[i].end = nodes[i].end; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | static int __init find_node_by_addr(unsigned long addr) | ||
200 | { | ||
201 | int ret = NUMA_NO_NODE; | ||
202 | int i; | ||
203 | |||
204 | for (i = 0; i < 8; i++) | ||
205 | if (addr >= nodes[i].start && addr < nodes[i].end) { | ||
206 | ret = i; | ||
207 | break; | ||
208 | } | ||
209 | return ret; | ||
210 | } | ||
211 | |||
212 | /* | ||
213 | * For NUMA emulation, fake proximity domain (_PXM) to node id mappings must be | ||
214 | * setup to represent the physical topology but reflect the emulated | ||
215 | * environment. For each emulated node, the real node which it appears on is | ||
216 | * found and a fake pxm to nid mapping is created which mirrors the actual | ||
217 | * locality. node_distance() then represents the correct distances between | ||
218 | * emulated nodes by using the fake acpi mappings to pxms. | ||
219 | */ | ||
220 | void __init amd_fake_nodes(const struct bootnode *nodes, int nr_nodes) | ||
221 | { | ||
222 | unsigned int bits; | ||
223 | unsigned int cores; | ||
224 | unsigned int apicid_base = 0; | ||
225 | int i; | ||
226 | |||
227 | bits = boot_cpu_data.x86_coreid_bits; | ||
228 | cores = 1 << bits; | ||
229 | early_get_boot_cpu_id(); | ||
230 | if (boot_cpu_physical_apicid > 0) | ||
231 | apicid_base = boot_cpu_physical_apicid; | ||
232 | |||
233 | for (i = 0; i < nr_nodes; i++) { | ||
234 | int index; | ||
235 | int nid; | ||
236 | int j; | ||
237 | |||
238 | nid = find_node_by_addr(nodes[i].start); | ||
239 | if (nid == NUMA_NO_NODE) | ||
240 | continue; | ||
241 | |||
242 | index = nodeids[nid] << bits; | ||
243 | if (fake_apicid_to_node[index + apicid_base] == NUMA_NO_NODE) | ||
244 | for (j = apicid_base; j < cores + apicid_base; j++) | ||
245 | fake_apicid_to_node[index + j] = i; | ||
246 | #ifdef CONFIG_ACPI_NUMA | ||
247 | __acpi_map_pxm_to_node(nid, i); | ||
248 | #endif | ||
249 | } | ||
250 | memcpy(apicid_to_node, fake_apicid_to_node, sizeof(apicid_to_node)); | ||
251 | } | ||
252 | #endif /* CONFIG_NUMA_EMU */ | ||
253 | |||
196 | int __init amd_scan_nodes(void) | 254 | int __init amd_scan_nodes(void) |
197 | { | 255 | { |
198 | unsigned int bits; | 256 | unsigned int bits; |
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index 7762a517d69d..1e72102e80c9 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c | |||
@@ -260,30 +260,30 @@ void __init numa_init_array(void) | |||
260 | #ifdef CONFIG_NUMA_EMU | 260 | #ifdef CONFIG_NUMA_EMU |
261 | /* Numa emulation */ | 261 | /* Numa emulation */ |
262 | static struct bootnode nodes[MAX_NUMNODES] __initdata; | 262 | static struct bootnode nodes[MAX_NUMNODES] __initdata; |
263 | static struct bootnode physnodes[MAX_NUMNODES] __initdata; | 263 | static struct bootnode physnodes[MAX_NUMNODES] __cpuinitdata; |
264 | static char *cmdline __initdata; | 264 | static char *cmdline __initdata; |
265 | 265 | ||
266 | static int __init setup_physnodes(unsigned long start, unsigned long end, | 266 | static int __init setup_physnodes(unsigned long start, unsigned long end, |
267 | int acpi, int amd) | 267 | int acpi, int amd) |
268 | { | 268 | { |
269 | int nr_nodes = 0; | ||
270 | int ret = 0; | 269 | int ret = 0; |
271 | int i; | 270 | int i; |
272 | 271 | ||
272 | memset(physnodes, 0, sizeof(physnodes)); | ||
273 | #ifdef CONFIG_ACPI_NUMA | 273 | #ifdef CONFIG_ACPI_NUMA |
274 | if (acpi) | 274 | if (acpi) |
275 | nr_nodes = acpi_get_nodes(physnodes); | 275 | acpi_get_nodes(physnodes, start, end); |
276 | #endif | 276 | #endif |
277 | #ifdef CONFIG_AMD_NUMA | 277 | #ifdef CONFIG_AMD_NUMA |
278 | if (amd) | 278 | if (amd) |
279 | nr_nodes = amd_get_nodes(physnodes); | 279 | amd_get_nodes(physnodes); |
280 | #endif | 280 | #endif |
281 | /* | 281 | /* |
282 | * Basic sanity checking on the physical node map: there may be errors | 282 | * Basic sanity checking on the physical node map: there may be errors |
283 | * if the SRAT or AMD code incorrectly reported the topology or the mem= | 283 | * if the SRAT or AMD code incorrectly reported the topology or the mem= |
284 | * kernel parameter is used. | 284 | * kernel parameter is used. |
285 | */ | 285 | */ |
286 | for (i = 0; i < nr_nodes; i++) { | 286 | for (i = 0; i < MAX_NUMNODES; i++) { |
287 | if (physnodes[i].start == physnodes[i].end) | 287 | if (physnodes[i].start == physnodes[i].end) |
288 | continue; | 288 | continue; |
289 | if (physnodes[i].start > end) { | 289 | if (physnodes[i].start > end) { |
@@ -298,17 +298,6 @@ static int __init setup_physnodes(unsigned long start, unsigned long end, | |||
298 | physnodes[i].start = start; | 298 | physnodes[i].start = start; |
299 | if (physnodes[i].end > end) | 299 | if (physnodes[i].end > end) |
300 | physnodes[i].end = end; | 300 | physnodes[i].end = end; |
301 | } | ||
302 | |||
303 | /* | ||
304 | * Remove all nodes that have no memory or were truncated because of the | ||
305 | * limited address range. | ||
306 | */ | ||
307 | for (i = 0; i < nr_nodes; i++) { | ||
308 | if (physnodes[i].start == physnodes[i].end) | ||
309 | continue; | ||
310 | physnodes[ret].start = physnodes[i].start; | ||
311 | physnodes[ret].end = physnodes[i].end; | ||
312 | ret++; | 301 | ret++; |
313 | } | 302 | } |
314 | 303 | ||
@@ -324,6 +313,24 @@ static int __init setup_physnodes(unsigned long start, unsigned long end, | |||
324 | return ret; | 313 | return ret; |
325 | } | 314 | } |
326 | 315 | ||
316 | static void __init fake_physnodes(int acpi, int amd, int nr_nodes) | ||
317 | { | ||
318 | int i; | ||
319 | |||
320 | BUG_ON(acpi && amd); | ||
321 | #ifdef CONFIG_ACPI_NUMA | ||
322 | if (acpi) | ||
323 | acpi_fake_nodes(nodes, nr_nodes); | ||
324 | #endif | ||
325 | #ifdef CONFIG_AMD_NUMA | ||
326 | if (amd) | ||
327 | amd_fake_nodes(nodes, nr_nodes); | ||
328 | #endif | ||
329 | if (!acpi && !amd) | ||
330 | for (i = 0; i < nr_cpu_ids; i++) | ||
331 | numa_set_node(i, 0); | ||
332 | } | ||
333 | |||
327 | /* | 334 | /* |
328 | * Setups up nid to range from addr to addr + size. If the end | 335 | * Setups up nid to range from addr to addr + size. If the end |
329 | * boundary is greater than max_addr, then max_addr is used instead. | 336 | * boundary is greater than max_addr, then max_addr is used instead. |
@@ -352,8 +359,7 @@ static int __init setup_node_range(int nid, u64 *addr, u64 size, u64 max_addr) | |||
352 | * Sets up nr_nodes fake nodes interleaved over physical nodes ranging from addr | 359 | * Sets up nr_nodes fake nodes interleaved over physical nodes ranging from addr |
353 | * to max_addr. The return value is the number of nodes allocated. | 360 | * to max_addr. The return value is the number of nodes allocated. |
354 | */ | 361 | */ |
355 | static int __init split_nodes_interleave(u64 addr, u64 max_addr, | 362 | static int __init split_nodes_interleave(u64 addr, u64 max_addr, int nr_nodes) |
356 | int nr_phys_nodes, int nr_nodes) | ||
357 | { | 363 | { |
358 | nodemask_t physnode_mask = NODE_MASK_NONE; | 364 | nodemask_t physnode_mask = NODE_MASK_NONE; |
359 | u64 size; | 365 | u64 size; |
@@ -384,7 +390,7 @@ static int __init split_nodes_interleave(u64 addr, u64 max_addr, | |||
384 | return -1; | 390 | return -1; |
385 | } | 391 | } |
386 | 392 | ||
387 | for (i = 0; i < nr_phys_nodes; i++) | 393 | for (i = 0; i < MAX_NUMNODES; i++) |
388 | if (physnodes[i].start != physnodes[i].end) | 394 | if (physnodes[i].start != physnodes[i].end) |
389 | node_set(i, physnode_mask); | 395 | node_set(i, physnode_mask); |
390 | 396 | ||
@@ -553,11 +559,9 @@ static int __init numa_emulation(unsigned long start_pfn, | |||
553 | { | 559 | { |
554 | u64 addr = start_pfn << PAGE_SHIFT; | 560 | u64 addr = start_pfn << PAGE_SHIFT; |
555 | u64 max_addr = last_pfn << PAGE_SHIFT; | 561 | u64 max_addr = last_pfn << PAGE_SHIFT; |
556 | int num_phys_nodes; | ||
557 | int num_nodes; | 562 | int num_nodes; |
558 | int i; | 563 | int i; |
559 | 564 | ||
560 | num_phys_nodes = setup_physnodes(addr, max_addr, acpi, amd); | ||
561 | /* | 565 | /* |
562 | * If the numa=fake command-line contains a 'M' or 'G', it represents | 566 | * If the numa=fake command-line contains a 'M' or 'G', it represents |
563 | * the fixed node size. Otherwise, if it is just a single number N, | 567 | * the fixed node size. Otherwise, if it is just a single number N, |
@@ -572,7 +576,7 @@ static int __init numa_emulation(unsigned long start_pfn, | |||
572 | unsigned long n; | 576 | unsigned long n; |
573 | 577 | ||
574 | n = simple_strtoul(cmdline, NULL, 0); | 578 | n = simple_strtoul(cmdline, NULL, 0); |
575 | num_nodes = split_nodes_interleave(addr, max_addr, num_phys_nodes, n); | 579 | num_nodes = split_nodes_interleave(addr, max_addr, n); |
576 | } | 580 | } |
577 | 581 | ||
578 | if (num_nodes < 0) | 582 | if (num_nodes < 0) |
@@ -595,7 +599,8 @@ static int __init numa_emulation(unsigned long start_pfn, | |||
595 | nodes[i].end >> PAGE_SHIFT); | 599 | nodes[i].end >> PAGE_SHIFT); |
596 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); | 600 | setup_node_bootmem(i, nodes[i].start, nodes[i].end); |
597 | } | 601 | } |
598 | acpi_fake_nodes(nodes, num_nodes); | 602 | setup_physnodes(addr, max_addr, acpi, amd); |
603 | fake_physnodes(acpi, amd, num_nodes); | ||
599 | numa_init_array(); | 604 | numa_init_array(); |
600 | return 0; | 605 | return 0; |
601 | } | 606 | } |
@@ -610,8 +615,12 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn, | |||
610 | nodes_clear(node_online_map); | 615 | nodes_clear(node_online_map); |
611 | 616 | ||
612 | #ifdef CONFIG_NUMA_EMU | 617 | #ifdef CONFIG_NUMA_EMU |
618 | setup_physnodes(start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT, | ||
619 | acpi, amd); | ||
613 | if (cmdline && !numa_emulation(start_pfn, last_pfn, acpi, amd)) | 620 | if (cmdline && !numa_emulation(start_pfn, last_pfn, acpi, amd)) |
614 | return; | 621 | return; |
622 | setup_physnodes(start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT, | ||
623 | acpi, amd); | ||
615 | nodes_clear(node_possible_map); | 624 | nodes_clear(node_possible_map); |
616 | nodes_clear(node_online_map); | 625 | nodes_clear(node_online_map); |
617 | #endif | 626 | #endif |
@@ -767,6 +776,7 @@ void __cpuinit numa_clear_node(int cpu) | |||
767 | 776 | ||
768 | #ifndef CONFIG_DEBUG_PER_CPU_MAPS | 777 | #ifndef CONFIG_DEBUG_PER_CPU_MAPS |
769 | 778 | ||
779 | #ifndef CONFIG_NUMA_EMU | ||
770 | void __cpuinit numa_add_cpu(int cpu) | 780 | void __cpuinit numa_add_cpu(int cpu) |
771 | { | 781 | { |
772 | cpumask_set_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); | 782 | cpumask_set_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); |
@@ -776,34 +786,115 @@ void __cpuinit numa_remove_cpu(int cpu) | |||
776 | { | 786 | { |
777 | cpumask_clear_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); | 787 | cpumask_clear_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); |
778 | } | 788 | } |
789 | #else | ||
790 | void __cpuinit numa_add_cpu(int cpu) | ||
791 | { | ||
792 | unsigned long addr; | ||
793 | u16 apicid; | ||
794 | int physnid; | ||
795 | int nid = NUMA_NO_NODE; | ||
796 | |||
797 | apicid = early_per_cpu(x86_cpu_to_apicid, cpu); | ||
798 | if (apicid != BAD_APICID) | ||
799 | nid = apicid_to_node[apicid]; | ||
800 | if (nid == NUMA_NO_NODE) | ||
801 | nid = early_cpu_to_node(cpu); | ||
802 | BUG_ON(nid == NUMA_NO_NODE || !node_online(nid)); | ||
803 | |||
804 | /* | ||
805 | * Use the starting address of the emulated node to find which physical | ||
806 | * node it is allocated on. | ||
807 | */ | ||
808 | addr = node_start_pfn(nid) << PAGE_SHIFT; | ||
809 | for (physnid = 0; physnid < MAX_NUMNODES; physnid++) | ||
810 | if (addr >= physnodes[physnid].start && | ||
811 | addr < physnodes[physnid].end) | ||
812 | break; | ||
813 | |||
814 | /* | ||
815 | * Map the cpu to each emulated node that is allocated on the physical | ||
816 | * node of the cpu's apic id. | ||
817 | */ | ||
818 | for_each_online_node(nid) { | ||
819 | addr = node_start_pfn(nid) << PAGE_SHIFT; | ||
820 | if (addr >= physnodes[physnid].start && | ||
821 | addr < physnodes[physnid].end) | ||
822 | cpumask_set_cpu(cpu, node_to_cpumask_map[nid]); | ||
823 | } | ||
824 | } | ||
825 | |||
826 | void __cpuinit numa_remove_cpu(int cpu) | ||
827 | { | ||
828 | int i; | ||
829 | |||
830 | for_each_online_node(i) | ||
831 | cpumask_clear_cpu(cpu, node_to_cpumask_map[i]); | ||
832 | } | ||
833 | #endif /* !CONFIG_NUMA_EMU */ | ||
779 | 834 | ||
780 | #else /* CONFIG_DEBUG_PER_CPU_MAPS */ | 835 | #else /* CONFIG_DEBUG_PER_CPU_MAPS */ |
836 | static struct cpumask __cpuinit *debug_cpumask_set_cpu(int cpu, int enable) | ||
837 | { | ||
838 | int node = early_cpu_to_node(cpu); | ||
839 | struct cpumask *mask; | ||
840 | char buf[64]; | ||
841 | |||
842 | mask = node_to_cpumask_map[node]; | ||
843 | if (!mask) { | ||
844 | pr_err("node_to_cpumask_map[%i] NULL\n", node); | ||
845 | dump_stack(); | ||
846 | return NULL; | ||
847 | } | ||
848 | |||
849 | cpulist_scnprintf(buf, sizeof(buf), mask); | ||
850 | printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n", | ||
851 | enable ? "numa_add_cpu" : "numa_remove_cpu", | ||
852 | cpu, node, buf); | ||
853 | return mask; | ||
854 | } | ||
781 | 855 | ||
782 | /* | 856 | /* |
783 | * --------- debug versions of the numa functions --------- | 857 | * --------- debug versions of the numa functions --------- |
784 | */ | 858 | */ |
859 | #ifndef CONFIG_NUMA_EMU | ||
785 | static void __cpuinit numa_set_cpumask(int cpu, int enable) | 860 | static void __cpuinit numa_set_cpumask(int cpu, int enable) |
786 | { | 861 | { |
787 | int node = early_cpu_to_node(cpu); | ||
788 | struct cpumask *mask; | 862 | struct cpumask *mask; |
789 | char buf[64]; | ||
790 | 863 | ||
791 | mask = node_to_cpumask_map[node]; | 864 | mask = debug_cpumask_set_cpu(cpu, enable); |
792 | if (mask == NULL) { | 865 | if (!mask) |
793 | printk(KERN_ERR "node_to_cpumask_map[%i] NULL\n", node); | ||
794 | dump_stack(); | ||
795 | return; | 866 | return; |
796 | } | ||
797 | 867 | ||
798 | if (enable) | 868 | if (enable) |
799 | cpumask_set_cpu(cpu, mask); | 869 | cpumask_set_cpu(cpu, mask); |
800 | else | 870 | else |
801 | cpumask_clear_cpu(cpu, mask); | 871 | cpumask_clear_cpu(cpu, mask); |
872 | } | ||
873 | #else | ||
874 | static void __cpuinit numa_set_cpumask(int cpu, int enable) | ||
875 | { | ||
876 | int node = early_cpu_to_node(cpu); | ||
877 | struct cpumask *mask; | ||
878 | int i; | ||
802 | 879 | ||
803 | cpulist_scnprintf(buf, sizeof(buf), mask); | 880 | for_each_online_node(i) { |
804 | printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n", | 881 | unsigned long addr; |
805 | enable ? "numa_add_cpu" : "numa_remove_cpu", cpu, node, buf); | 882 | |
883 | addr = node_start_pfn(i) << PAGE_SHIFT; | ||
884 | if (addr < physnodes[node].start || | ||
885 | addr >= physnodes[node].end) | ||
886 | continue; | ||
887 | mask = debug_cpumask_set_cpu(cpu, enable); | ||
888 | if (!mask) | ||
889 | return; | ||
890 | |||
891 | if (enable) | ||
892 | cpumask_set_cpu(cpu, mask); | ||
893 | else | ||
894 | cpumask_clear_cpu(cpu, mask); | ||
895 | } | ||
806 | } | 896 | } |
897 | #endif /* CONFIG_NUMA_EMU */ | ||
807 | 898 | ||
808 | void __cpuinit numa_add_cpu(int cpu) | 899 | void __cpuinit numa_add_cpu(int cpu) |
809 | { | 900 | { |
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index 171a0aacb99a..603d285d1daa 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c | |||
@@ -349,18 +349,19 @@ static int __init nodes_cover_memory(const struct bootnode *nodes) | |||
349 | 349 | ||
350 | void __init acpi_numa_arch_fixup(void) {} | 350 | void __init acpi_numa_arch_fixup(void) {} |
351 | 351 | ||
352 | int __init acpi_get_nodes(struct bootnode *physnodes) | 352 | #ifdef CONFIG_NUMA_EMU |
353 | void __init acpi_get_nodes(struct bootnode *physnodes, unsigned long start, | ||
354 | unsigned long end) | ||
353 | { | 355 | { |
354 | int i; | 356 | int i; |
355 | int ret = 0; | ||
356 | 357 | ||
357 | for_each_node_mask(i, nodes_parsed) { | 358 | for_each_node_mask(i, nodes_parsed) { |
358 | physnodes[ret].start = nodes[i].start; | 359 | cutoff_node(i, start, end); |
359 | physnodes[ret].end = nodes[i].end; | 360 | physnodes[i].start = nodes[i].start; |
360 | ret++; | 361 | physnodes[i].end = nodes[i].end; |
361 | } | 362 | } |
362 | return ret; | ||
363 | } | 363 | } |
364 | #endif /* CONFIG_NUMA_EMU */ | ||
364 | 365 | ||
365 | /* Use the information discovered above to actually set up the nodes. */ | 366 | /* Use the information discovered above to actually set up the nodes. */ |
366 | int __init acpi_scan_nodes(unsigned long start, unsigned long end) | 367 | int __init acpi_scan_nodes(unsigned long start, unsigned long end) |
@@ -505,8 +506,6 @@ void __init acpi_fake_nodes(const struct bootnode *fake_nodes, int num_nodes) | |||
505 | { | 506 | { |
506 | int i, j; | 507 | int i, j; |
507 | 508 | ||
508 | printk(KERN_INFO "Faking PXM affinity for fake nodes on real " | ||
509 | "topology.\n"); | ||
510 | for (i = 0; i < num_nodes; i++) { | 509 | for (i = 0; i < num_nodes; i++) { |
511 | int nid, pxm; | 510 | int nid, pxm; |
512 | 511 | ||
@@ -526,6 +525,17 @@ void __init acpi_fake_nodes(const struct bootnode *fake_nodes, int num_nodes) | |||
526 | fake_apicid_to_node[j] == NUMA_NO_NODE) | 525 | fake_apicid_to_node[j] == NUMA_NO_NODE) |
527 | fake_apicid_to_node[j] = i; | 526 | fake_apicid_to_node[j] = i; |
528 | } | 527 | } |
528 | |||
529 | /* | ||
530 | * If there are apicid-to-node mappings for physical nodes that do not | ||
531 | * have a corresponding emulated node, it should default to a guaranteed | ||
532 | * value. | ||
533 | */ | ||
534 | for (i = 0; i < MAX_LOCAL_APIC; i++) | ||
535 | if (apicid_to_node[i] != NUMA_NO_NODE && | ||
536 | fake_apicid_to_node[i] == NUMA_NO_NODE) | ||
537 | fake_apicid_to_node[i] = 0; | ||
538 | |||
529 | for (i = 0; i < num_nodes; i++) | 539 | for (i = 0; i < num_nodes; i++) |
530 | __acpi_map_pxm_to_node(fake_node_to_pxm_map[i], i); | 540 | __acpi_map_pxm_to_node(fake_node_to_pxm_map[i], i); |
531 | memcpy(apicid_to_node, fake_apicid_to_node, sizeof(apicid_to_node)); | 541 | memcpy(apicid_to_node, fake_apicid_to_node, sizeof(apicid_to_node)); |