diff options
Diffstat (limited to 'arch/x86/mm')
-rw-r--r-- | arch/x86/mm/numa_64.c | 95 | ||||
-rw-r--r-- | arch/x86/mm/srat_64.c | 27 |
2 files changed, 106 insertions, 16 deletions
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index 8b1f178a866e..a3621f2953d6 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c | |||
@@ -45,6 +45,13 @@ static unsigned long __initdata nodemap_size; | |||
45 | 45 | ||
46 | static struct numa_meminfo numa_meminfo __initdata; | 46 | static struct numa_meminfo numa_meminfo __initdata; |
47 | 47 | ||
48 | static int numa_distance_cnt; | ||
49 | static u8 *numa_distance; | ||
50 | |||
51 | #ifdef CONFIG_NUMA_EMU | ||
52 | static bool numa_emu_dist; | ||
53 | #endif | ||
54 | |||
48 | /* | 55 | /* |
49 | * Given a shift value, try to populate memnodemap[] | 56 | * Given a shift value, try to populate memnodemap[] |
50 | * Returns : | 57 | * Returns : |
@@ -357,6 +364,92 @@ static void __init numa_nodemask_from_meminfo(nodemask_t *nodemask, | |||
357 | } | 364 | } |
358 | 365 | ||
359 | /* | 366 | /* |
367 | * Reset distance table. The current table is freed. The next | ||
368 | * numa_set_distance() call will create a new one. | ||
369 | */ | ||
370 | static void __init numa_reset_distance(void) | ||
371 | { | ||
372 | size_t size; | ||
373 | |||
374 | size = numa_distance_cnt * sizeof(numa_distance[0]); | ||
375 | memblock_x86_free_range(__pa(numa_distance), | ||
376 | __pa(numa_distance) + size); | ||
377 | numa_distance = NULL; | ||
378 | numa_distance_cnt = 0; | ||
379 | } | ||
380 | |||
381 | /* | ||
382 | * Set the distance between node @from to @to to @distance. If distance | ||
383 | * table doesn't exist, one which is large enough to accomodate all the | ||
384 | * currently known nodes will be created. | ||
385 | */ | ||
386 | void __init numa_set_distance(int from, int to, int distance) | ||
387 | { | ||
388 | if (!numa_distance) { | ||
389 | nodemask_t nodes_parsed; | ||
390 | size_t size; | ||
391 | int i, j, cnt = 0; | ||
392 | u64 phys; | ||
393 | |||
394 | /* size the new table and allocate it */ | ||
395 | nodes_parsed = numa_nodes_parsed; | ||
396 | numa_nodemask_from_meminfo(&nodes_parsed, &numa_meminfo); | ||
397 | |||
398 | for_each_node_mask(i, nodes_parsed) | ||
399 | cnt = i; | ||
400 | size = ++cnt * sizeof(numa_distance[0]); | ||
401 | |||
402 | phys = memblock_find_in_range(0, | ||
403 | (u64)max_pfn_mapped << PAGE_SHIFT, | ||
404 | size, PAGE_SIZE); | ||
405 | if (phys == MEMBLOCK_ERROR) { | ||
406 | pr_warning("NUMA: Warning: can't allocate distance table!\n"); | ||
407 | /* don't retry until explicitly reset */ | ||
408 | numa_distance = (void *)1LU; | ||
409 | return; | ||
410 | } | ||
411 | memblock_x86_reserve_range(phys, phys + size, "NUMA DIST"); | ||
412 | |||
413 | numa_distance = __va(phys); | ||
414 | numa_distance_cnt = cnt; | ||
415 | |||
416 | /* fill with the default distances */ | ||
417 | for (i = 0; i < cnt; i++) | ||
418 | for (j = 0; j < cnt; j++) | ||
419 | numa_distance[i * cnt + j] = i == j ? | ||
420 | LOCAL_DISTANCE : REMOTE_DISTANCE; | ||
421 | printk(KERN_DEBUG "NUMA: Initialized distance table, cnt=%d\n", cnt); | ||
422 | } | ||
423 | |||
424 | if (from >= numa_distance_cnt || to >= numa_distance_cnt) { | ||
425 | printk_once(KERN_DEBUG "NUMA: Debug: distance out of bound, from=%d to=%d distance=%d\n", | ||
426 | from, to, distance); | ||
427 | return; | ||
428 | } | ||
429 | |||
430 | if ((u8)distance != distance || | ||
431 | (from == to && distance != LOCAL_DISTANCE)) { | ||
432 | pr_warn_once("NUMA: Warning: invalid distance parameter, from=%d to=%d distance=%d\n", | ||
433 | from, to, distance); | ||
434 | return; | ||
435 | } | ||
436 | |||
437 | numa_distance[from * numa_distance_cnt + to] = distance; | ||
438 | } | ||
439 | |||
440 | int __node_distance(int from, int to) | ||
441 | { | ||
442 | #if defined(CONFIG_ACPI_NUMA) && defined(CONFIG_NUMA_EMU) | ||
443 | if (numa_emu_dist) | ||
444 | return acpi_emu_node_distance(from, to); | ||
445 | #endif | ||
446 | if (from >= numa_distance_cnt || to >= numa_distance_cnt) | ||
447 | return from == to ? LOCAL_DISTANCE : REMOTE_DISTANCE; | ||
448 | return numa_distance[from * numa_distance_cnt + to]; | ||
449 | } | ||
450 | EXPORT_SYMBOL(__node_distance); | ||
451 | |||
452 | /* | ||
360 | * Sanity check to catch more bad NUMA configurations (they are amazingly | 453 | * Sanity check to catch more bad NUMA configurations (they are amazingly |
361 | * common). Make sure the nodes cover all memory. | 454 | * common). Make sure the nodes cover all memory. |
362 | */ | 455 | */ |
@@ -826,6 +919,7 @@ static int __init numa_emulation(unsigned long start_pfn, | |||
826 | setup_physnodes(addr, max_addr); | 919 | setup_physnodes(addr, max_addr); |
827 | fake_physnodes(acpi, amd, num_nodes); | 920 | fake_physnodes(acpi, amd, num_nodes); |
828 | numa_init_array(); | 921 | numa_init_array(); |
922 | numa_emu_dist = true; | ||
829 | return 0; | 923 | return 0; |
830 | } | 924 | } |
831 | #endif /* CONFIG_NUMA_EMU */ | 925 | #endif /* CONFIG_NUMA_EMU */ |
@@ -869,6 +963,7 @@ void __init initmem_init(void) | |||
869 | nodes_clear(node_online_map); | 963 | nodes_clear(node_online_map); |
870 | memset(&numa_meminfo, 0, sizeof(numa_meminfo)); | 964 | memset(&numa_meminfo, 0, sizeof(numa_meminfo)); |
871 | remove_all_active_ranges(); | 965 | remove_all_active_ranges(); |
966 | numa_reset_distance(); | ||
872 | 967 | ||
873 | if (numa_init[i]() < 0) | 968 | if (numa_init[i]() < 0) |
874 | continue; | 969 | continue; |
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index 4f8e6cde9bf6..d2f53f35d86a 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c | |||
@@ -50,9 +50,16 @@ static __init inline int srat_disabled(void) | |||
50 | /* Callback for SLIT parsing */ | 50 | /* Callback for SLIT parsing */ |
51 | void __init acpi_numa_slit_init(struct acpi_table_slit *slit) | 51 | void __init acpi_numa_slit_init(struct acpi_table_slit *slit) |
52 | { | 52 | { |
53 | int i, j; | ||
53 | unsigned length; | 54 | unsigned length; |
54 | unsigned long phys; | 55 | unsigned long phys; |
55 | 56 | ||
57 | for (i = 0; i < slit->locality_count; i++) | ||
58 | for (j = 0; j < slit->locality_count; j++) | ||
59 | numa_set_distance(pxm_to_node(i), pxm_to_node(j), | ||
60 | slit->entry[slit->locality_count * i + j]); | ||
61 | |||
62 | /* acpi_slit is used only by emulation */ | ||
56 | length = slit->header.length; | 63 | length = slit->header.length; |
57 | phys = memblock_find_in_range(0, max_pfn_mapped<<PAGE_SHIFT, length, | 64 | phys = memblock_find_in_range(0, max_pfn_mapped<<PAGE_SHIFT, length, |
58 | PAGE_SIZE); | 65 | PAGE_SIZE); |
@@ -313,29 +320,17 @@ void __init acpi_fake_nodes(const struct bootnode *fake_nodes, int num_nodes) | |||
313 | node_set(i, numa_nodes_parsed); | 320 | node_set(i, numa_nodes_parsed); |
314 | } | 321 | } |
315 | 322 | ||
316 | static int null_slit_node_compare(int a, int b) | 323 | int acpi_emu_node_distance(int a, int b) |
317 | { | ||
318 | return node_to_pxm(a) == node_to_pxm(b); | ||
319 | } | ||
320 | #else | ||
321 | static int null_slit_node_compare(int a, int b) | ||
322 | { | ||
323 | return a == b; | ||
324 | } | ||
325 | #endif /* CONFIG_NUMA_EMU */ | ||
326 | |||
327 | int __node_distance(int a, int b) | ||
328 | { | 324 | { |
329 | int index; | 325 | int index; |
330 | 326 | ||
331 | if (!acpi_slit) | 327 | if (!acpi_slit) |
332 | return null_slit_node_compare(a, b) ? LOCAL_DISTANCE : | 328 | return node_to_pxm(a) == node_to_pxm(b) ? |
333 | REMOTE_DISTANCE; | 329 | LOCAL_DISTANCE : REMOTE_DISTANCE; |
334 | index = acpi_slit->locality_count * node_to_pxm(a); | 330 | index = acpi_slit->locality_count * node_to_pxm(a); |
335 | return acpi_slit->entry[index + node_to_pxm(b)]; | 331 | return acpi_slit->entry[index + node_to_pxm(b)]; |
336 | } | 332 | } |
337 | 333 | #endif /* CONFIG_NUMA_EMU */ | |
338 | EXPORT_SYMBOL(__node_distance); | ||
339 | 334 | ||
340 | #if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) | 335 | #if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) |
341 | int memory_add_physaddr_to_nid(u64 start) | 336 | int memory_add_physaddr_to_nid(u64 start) |