aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/mm')
-rw-r--r--arch/x86/mm/numa_64.c56
1 files changed, 33 insertions, 23 deletions
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index 6e4ee96d1b11..980d51458c4b 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -789,17 +789,20 @@ static int __init split_nodes_size_interleave(struct numa_meminfo *ei,
789 * Sets up the system RAM area from start_pfn to last_pfn according to the 789 * Sets up the system RAM area from start_pfn to last_pfn according to the
790 * numa=fake command-line option. 790 * numa=fake command-line option.
791 */ 791 */
792static bool __init numa_emulation(void) 792static void __init numa_emulation(struct numa_meminfo *numa_meminfo,
793 int numa_dist_cnt)
793{ 794{
794 static struct numa_meminfo ei __initdata; 795 static struct numa_meminfo ei __initdata;
795 static struct numa_meminfo pi __initdata; 796 static struct numa_meminfo pi __initdata;
796 const u64 max_addr = max_pfn << PAGE_SHIFT; 797 const u64 max_addr = max_pfn << PAGE_SHIFT;
797 int phys_dist_cnt = numa_distance_cnt;
798 u8 *phys_dist = NULL; 798 u8 *phys_dist = NULL;
799 int i, j, ret; 799 int i, j, ret;
800 800
801 if (!emu_cmdline)
802 goto no_emu;
803
801 memset(&ei, 0, sizeof(ei)); 804 memset(&ei, 0, sizeof(ei));
802 pi = numa_meminfo; 805 pi = *numa_meminfo;
803 806
804 for (i = 0; i < MAX_NUMNODES; i++) 807 for (i = 0; i < MAX_NUMNODES; i++)
805 emu_nid_to_phys[i] = NUMA_NO_NODE; 808 emu_nid_to_phys[i] = NUMA_NO_NODE;
@@ -822,19 +825,19 @@ static bool __init numa_emulation(void)
822 } 825 }
823 826
824 if (ret < 0) 827 if (ret < 0)
825 return false; 828 goto no_emu;
826 829
827 if (numa_cleanup_meminfo(&ei) < 0) { 830 if (numa_cleanup_meminfo(&ei) < 0) {
828 pr_warning("NUMA: Warning: constructed meminfo invalid, disabling emulation\n"); 831 pr_warning("NUMA: Warning: constructed meminfo invalid, disabling emulation\n");
829 return false; 832 goto no_emu;
830 } 833 }
831 834
832 /* 835 /*
833 * Copy the original distance table. It's temporary so no need to 836 * Copy the original distance table. It's temporary so no need to
834 * reserve it. 837 * reserve it.
835 */ 838 */
836 if (phys_dist_cnt) { 839 if (numa_dist_cnt) {
837 size_t size = phys_dist_cnt * sizeof(numa_distance[0]); 840 size_t size = numa_dist_cnt * sizeof(phys_dist[0]);
838 u64 phys; 841 u64 phys;
839 842
840 phys = memblock_find_in_range(0, 843 phys = memblock_find_in_range(0,
@@ -842,14 +845,18 @@ static bool __init numa_emulation(void)
842 size, PAGE_SIZE); 845 size, PAGE_SIZE);
843 if (phys == MEMBLOCK_ERROR) { 846 if (phys == MEMBLOCK_ERROR) {
844 pr_warning("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n"); 847 pr_warning("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n");
845 return false; 848 goto no_emu;
846 } 849 }
847 phys_dist = __va(phys); 850 phys_dist = __va(phys);
848 memcpy(phys_dist, numa_distance, size); 851
852 for (i = 0; i < numa_dist_cnt; i++)
853 for (j = 0; j < numa_dist_cnt; j++)
854 phys_dist[i * numa_dist_cnt + j] =
855 node_distance(i, j);
849 } 856 }
850 857
851 /* commit */ 858 /* commit */
852 numa_meminfo = ei; 859 *numa_meminfo = ei;
853 860
854 /* 861 /*
855 * Transform __apicid_to_node table to use emulated nids by 862 * Transform __apicid_to_node table to use emulated nids by
@@ -878,18 +885,27 @@ static bool __init numa_emulation(void)
878 int physj = emu_nid_to_phys[j]; 885 int physj = emu_nid_to_phys[j];
879 int dist; 886 int dist;
880 887
881 if (physi >= phys_dist_cnt || physj >= phys_dist_cnt) 888 if (physi >= numa_dist_cnt || physj >= numa_dist_cnt)
882 dist = physi == physj ? 889 dist = physi == physj ?
883 LOCAL_DISTANCE : REMOTE_DISTANCE; 890 LOCAL_DISTANCE : REMOTE_DISTANCE;
884 else 891 else
885 dist = phys_dist[physi * phys_dist_cnt + physj]; 892 dist = phys_dist[physi * numa_dist_cnt + physj];
886 893
887 numa_set_distance(i, j, dist); 894 numa_set_distance(i, j, dist);
888 } 895 }
889 } 896 }
890 return true; 897 return;
898
899no_emu:
900 /* No emulation. Build identity emu_nid_to_phys[] for numa_add_cpu() */
901 for (i = 0; i < ARRAY_SIZE(emu_nid_to_phys); i++)
902 emu_nid_to_phys[i] = i;
891} 903}
892#endif /* CONFIG_NUMA_EMU */ 904#else /* CONFIG_NUMA_EMU */
905static inline void numa_emulation(struct numa_meminfo *numa_meminfo,
906 int numa_dist_cnt)
907{ }
908#endif /* CONFIG_NUMA_EMU */
893 909
894static int __init dummy_numa_init(void) 910static int __init dummy_numa_init(void)
895{ 911{
@@ -937,15 +953,9 @@ void __init initmem_init(void)
937 953
938 if (numa_cleanup_meminfo(&numa_meminfo) < 0) 954 if (numa_cleanup_meminfo(&numa_meminfo) < 0)
939 continue; 955 continue;
940#ifdef CONFIG_NUMA_EMU 956
941 /* 957 numa_emulation(&numa_meminfo, numa_distance_cnt);
942 * If requested, try emulation. If emulation is not used, 958
943 * build identity emu_nid_to_phys[] for numa_add_cpu()
944 */
945 if (!emu_cmdline || !numa_emulation())
946 for (j = 0; j < ARRAY_SIZE(emu_nid_to_phys); j++)
947 emu_nid_to_phys[j] = j;
948#endif
949 if (numa_register_memblks(&numa_meminfo) < 0) 959 if (numa_register_memblks(&numa_meminfo) < 0)
950 continue; 960 continue;
951 961