aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/numa_64.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-02-16 11:11:10 -0500
committerTejun Heo <tj@kernel.org>2011-02-16 11:11:10 -0500
commite23bba604433a202cd301a976454a90ea6b783ef (patch)
tree012bc42b25abd68d77e9c6946a6b0d38b9b71bdc /arch/x86/mm/numa_64.c
parent6b78cb549b4105cbf7c6f7461f27a21f00c44997 (diff)
x86-64, NUMA: Unify emulated distance mapping
NUMA emulation needs to update node distance information. It did it by remapping apicid to PXM mapping, even when amdtopology is being used. There is no reason to go through such convolution. The generic code has all the information necessary to transform the distance table to the emulated nid space. Implement generic distance table transformation in numa_emulation() and drop private implementations in srat_64 and amdtopology_64. This makes find_node_by_addr() and fake_physnodes() and related functions unnecessary, drop them. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Brian Gerst <brgerst@gmail.com> Cc: Cyrill Gorcunov <gorcunov@gmail.com> Cc: Shaohui Zheng <shaohui.zheng@intel.com> Cc: David Rientjes <rientjes@google.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86/mm/numa_64.c')
-rw-r--r--arch/x86/mm/numa_64.c102
1 files changed, 40 insertions, 62 deletions
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index 722039e0948f..8ce617735900 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -48,10 +48,6 @@ static struct numa_meminfo numa_meminfo __initdata;
48static int numa_distance_cnt; 48static int numa_distance_cnt;
49static u8 *numa_distance; 49static u8 *numa_distance;
50 50
51#ifdef CONFIG_NUMA_EMU
52static bool numa_emu_dist;
53#endif
54
55/* 51/*
56 * Given a shift value, try to populate memnodemap[] 52 * Given a shift value, try to populate memnodemap[]
57 * Returns : 53 * Returns :
@@ -443,10 +439,6 @@ void __init numa_set_distance(int from, int to, int distance)
443 439
444int __node_distance(int from, int to) 440int __node_distance(int from, int to)
445{ 441{
446#if defined(CONFIG_ACPI_NUMA) && defined(CONFIG_NUMA_EMU)
447 if (numa_emu_dist)
448 return acpi_emu_node_distance(from, to);
449#endif
450 if (from >= numa_distance_cnt || to >= numa_distance_cnt) 442 if (from >= numa_distance_cnt || to >= numa_distance_cnt)
451 return from == to ? LOCAL_DISTANCE : REMOTE_DISTANCE; 443 return from == to ? LOCAL_DISTANCE : REMOTE_DISTANCE;
452 return numa_distance[from * numa_distance_cnt + to]; 444 return numa_distance[from * numa_distance_cnt + to];
@@ -559,56 +551,6 @@ static int __init emu_find_memblk_by_nid(int nid, const struct numa_meminfo *mi)
559 return -ENOENT; 551 return -ENOENT;
560} 552}
561 553
562int __init find_node_by_addr(unsigned long addr)
563{
564 const struct numa_meminfo *mi = &numa_meminfo;
565 int i;
566
567 for (i = 0; i < mi->nr_blks; i++) {
568 /*
569 * Find the real node that this emulated node appears on. For
570 * the sake of simplicity, we only use a real node's starting
571 * address to determine which emulated node it appears on.
572 */
573 if (addr >= mi->blk[i].start && addr < mi->blk[i].end)
574 return mi->blk[i].nid;
575 }
576 return NUMA_NO_NODE;
577}
578
579static void __init fake_physnodes(int acpi, int amd,
580 const struct numa_meminfo *ei)
581{
582 static struct bootnode nodes[MAX_NUMNODES] __initdata;
583 int i, nr_nodes = 0;
584
585 for (i = 0; i < ei->nr_blks; i++) {
586 int nid = ei->blk[i].nid;
587
588 if (nodes[nid].start == nodes[nid].end) {
589 nodes[nid].start = ei->blk[i].start;
590 nodes[nid].end = ei->blk[i].end;
591 nr_nodes++;
592 } else {
593 nodes[nid].start = min(ei->blk[i].start, nodes[nid].start);
594 nodes[nid].end = max(ei->blk[i].end, nodes[nid].end);
595 }
596 }
597
598 BUG_ON(acpi && amd);
599#ifdef CONFIG_ACPI_NUMA
600 if (acpi)
601 acpi_fake_nodes(nodes, nr_nodes);
602#endif
603#ifdef CONFIG_AMD_NUMA
604 if (amd)
605 amd_fake_nodes(nodes, nr_nodes);
606#endif
607 if (!acpi && !amd)
608 for (i = 0; i < nr_cpu_ids; i++)
609 numa_set_node(i, 0);
610}
611
612/* 554/*
613 * Sets up nid to range from @start to @end. The return value is -errno if 555 * Sets up nid to range from @start to @end. The return value is -errno if
614 * something went wrong, 0 otherwise. 556 * something went wrong, 0 otherwise.
@@ -853,11 +795,13 @@ static int __init split_nodes_size_interleave(struct numa_meminfo *ei,
853 * Sets up the system RAM area from start_pfn to last_pfn according to the 795 * Sets up the system RAM area from start_pfn to last_pfn according to the
854 * numa=fake command-line option. 796 * numa=fake command-line option.
855 */ 797 */
856static bool __init numa_emulation(int acpi, int amd) 798static bool __init numa_emulation(void)
857{ 799{
858 static struct numa_meminfo ei __initdata; 800 static struct numa_meminfo ei __initdata;
859 static struct numa_meminfo pi __initdata; 801 static struct numa_meminfo pi __initdata;
860 const u64 max_addr = max_pfn << PAGE_SHIFT; 802 const u64 max_addr = max_pfn << PAGE_SHIFT;
803 int phys_dist_cnt = numa_distance_cnt;
804 u8 *phys_dist = NULL;
861 int i, j, ret; 805 int i, j, ret;
862 806
863 memset(&ei, 0, sizeof(ei)); 807 memset(&ei, 0, sizeof(ei));
@@ -891,6 +835,25 @@ static bool __init numa_emulation(int acpi, int amd)
891 return false; 835 return false;
892 } 836 }
893 837
838 /*
839 * Copy the original distance table. It's temporary so no need to
840 * reserve it.
841 */
842 if (phys_dist_cnt) {
843 size_t size = phys_dist_cnt * sizeof(numa_distance[0]);
844 u64 phys;
845
846 phys = memblock_find_in_range(0,
847 (u64)max_pfn_mapped << PAGE_SHIFT,
848 size, PAGE_SIZE);
849 if (phys == MEMBLOCK_ERROR) {
850 pr_warning("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n");
851 return false;
852 }
853 phys_dist = __va(phys);
854 memcpy(phys_dist, numa_distance, size);
855 }
856
894 /* commit */ 857 /* commit */
895 numa_meminfo = ei; 858 numa_meminfo = ei;
896 859
@@ -913,8 +876,23 @@ static bool __init numa_emulation(int acpi, int amd)
913 if (emu_nid_to_phys[i] == NUMA_NO_NODE) 876 if (emu_nid_to_phys[i] == NUMA_NO_NODE)
914 emu_nid_to_phys[i] = 0; 877 emu_nid_to_phys[i] = 0;
915 878
916 fake_physnodes(acpi, amd, &ei); 879 /* transform distance table */
917 numa_emu_dist = true; 880 numa_reset_distance();
881 for (i = 0; i < MAX_NUMNODES; i++) {
882 for (j = 0; j < MAX_NUMNODES; j++) {
883 int physi = emu_nid_to_phys[i];
884 int physj = emu_nid_to_phys[j];
885 int dist;
886
887 if (physi >= phys_dist_cnt || physj >= phys_dist_cnt)
888 dist = physi == physj ?
889 LOCAL_DISTANCE : REMOTE_DISTANCE;
890 else
891 dist = phys_dist[physi * phys_dist_cnt + physj];
892
893 numa_set_distance(i, j, dist);
894 }
895 }
918 return true; 896 return true;
919} 897}
920#endif /* CONFIG_NUMA_EMU */ 898#endif /* CONFIG_NUMA_EMU */
@@ -970,7 +948,7 @@ void __init initmem_init(void)
970 * If requested, try emulation. If emulation is not used, 948 * If requested, try emulation. If emulation is not used,
971 * build identity emu_nid_to_phys[] for numa_add_cpu() 949 * build identity emu_nid_to_phys[] for numa_add_cpu()
972 */ 950 */
973 if (!emu_cmdline || !numa_emulation(i == 0, i == 1)) 951 if (!emu_cmdline || !numa_emulation())
974 for (j = 0; j < ARRAY_SIZE(emu_nid_to_phys); j++) 952 for (j = 0; j < ARRAY_SIZE(emu_nid_to_phys); j++)
975 emu_nid_to_phys[j] = j; 953 emu_nid_to_phys[j] = j;
976#endif 954#endif