aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sparc/mm/init_64.c208
1 files changed, 113 insertions, 95 deletions
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 16c1e46e8603..77446eaf1395 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -829,13 +829,23 @@ static void __init find_ramdisk(unsigned long phys_base)
829 829
830struct node_mem_mask { 830struct node_mem_mask {
831 unsigned long mask; 831 unsigned long mask;
832 unsigned long val; 832 unsigned long match;
833}; 833};
834static struct node_mem_mask node_masks[MAX_NUMNODES]; 834static struct node_mem_mask node_masks[MAX_NUMNODES];
835static int num_node_masks; 835static int num_node_masks;
836 836
837#ifdef CONFIG_NEED_MULTIPLE_NODES 837#ifdef CONFIG_NEED_MULTIPLE_NODES
838 838
839struct mdesc_mlgroup {
840 u64 node;
841 u64 latency;
842 u64 match;
843 u64 mask;
844};
845
846static struct mdesc_mlgroup *mlgroups;
847static int num_mlgroups;
848
839int numa_cpu_lookup_table[NR_CPUS]; 849int numa_cpu_lookup_table[NR_CPUS];
840cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES]; 850cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES];
841 851
@@ -846,78 +856,129 @@ struct mdesc_mblock {
846}; 856};
847static struct mdesc_mblock *mblocks; 857static struct mdesc_mblock *mblocks;
848static int num_mblocks; 858static int num_mblocks;
849static int find_numa_node_for_addr(unsigned long pa,
850 struct node_mem_mask *pnode_mask);
851 859
852static unsigned long __init ra_to_pa(unsigned long addr) 860static struct mdesc_mblock * __init addr_to_mblock(unsigned long addr)
853{ 861{
862 struct mdesc_mblock *m = NULL;
854 int i; 863 int i;
855 864
856 for (i = 0; i < num_mblocks; i++) { 865 for (i = 0; i < num_mblocks; i++) {
857 struct mdesc_mblock *m = &mblocks[i]; 866 m = &mblocks[i];
858 867
859 if (addr >= m->base && 868 if (addr >= m->base &&
860 addr < (m->base + m->size)) { 869 addr < (m->base + m->size)) {
861 addr += m->offset;
862 break; 870 break;
863 } 871 }
864 } 872 }
865 return addr; 873
874 return m;
866} 875}
867 876
868static int __init find_node(unsigned long addr) 877static u64 __init memblock_nid_range_sun4u(u64 start, u64 end, int *nid)
869{ 878{
870 static bool search_mdesc = true; 879 int prev_nid, new_nid;
871 static struct node_mem_mask last_mem_mask = { ~0UL, ~0UL };
872 static int last_index;
873 int i;
874 880
875 addr = ra_to_pa(addr); 881 prev_nid = -1;
876 for (i = 0; i < num_node_masks; i++) { 882 for ( ; start < end; start += PAGE_SIZE) {
877 struct node_mem_mask *p = &node_masks[i]; 883 for (new_nid = 0; new_nid < num_node_masks; new_nid++) {
884 struct node_mem_mask *p = &node_masks[new_nid];
878 885
879 if ((addr & p->mask) == p->val) 886 if ((start & p->mask) == p->match) {
880 return i; 887 if (prev_nid == -1)
881 } 888 prev_nid = new_nid;
882 /* The following condition has been observed on LDOM guests because 889 break;
883 * node_masks only contains the best latency mask and value. 890 }
884 * LDOM guest's mdesc can contain a single latency group to
885 * cover multiple address range. Print warning message only if the
886 * address cannot be found in node_masks nor mdesc.
887 */
888 if ((search_mdesc) &&
889 ((addr & last_mem_mask.mask) != last_mem_mask.val)) {
890 /* find the available node in the mdesc */
891 last_index = find_numa_node_for_addr(addr, &last_mem_mask);
892 numadbg("find_node: latency group for address 0x%lx is %d\n",
893 addr, last_index);
894 if ((last_index < 0) || (last_index >= num_node_masks)) {
895 /* WARN_ONCE() and use default group 0 */
896 WARN_ONCE(1, "find_node: A physical address doesn't match a NUMA node rule. Some physical memory will be owned by node 0.");
897 search_mdesc = false;
898 last_index = 0;
899 } 891 }
892
893 if (new_nid == num_node_masks) {
894 prev_nid = 0;
895 WARN_ONCE(1, "addr[%Lx] doesn't match a NUMA node rule. Some memory will be owned by node 0.",
896 start);
897 break;
898 }
899
900 if (prev_nid != new_nid)
901 break;
900 } 902 }
903 *nid = prev_nid;
901 904
902 return last_index; 905 return start > end ? end : start;
903} 906}
904 907
905static u64 __init memblock_nid_range(u64 start, u64 end, int *nid) 908static u64 __init memblock_nid_range(u64 start, u64 end, int *nid)
906{ 909{
907 *nid = find_node(start); 910 u64 ret_end, pa_start, m_mask, m_match, m_end;
908 start += PAGE_SIZE; 911 struct mdesc_mblock *mblock;
909 while (start < end) { 912 int _nid, i;
910 int n = find_node(start); 913
914 if (tlb_type != hypervisor)
915 return memblock_nid_range_sun4u(start, end, nid);
916
917 mblock = addr_to_mblock(start);
918 if (!mblock) {
919 WARN_ONCE(1, "memblock_nid_range: Can't find mblock addr[%Lx]",
920 start);
921
922 _nid = 0;
923 ret_end = end;
924 goto done;
925 }
926
927 pa_start = start + mblock->offset;
928 m_match = 0;
929 m_mask = 0;
930
931 for (_nid = 0; _nid < num_node_masks; _nid++) {
932 struct node_mem_mask *const m = &node_masks[_nid];
911 933
912 if (n != *nid) 934 if ((pa_start & m->mask) == m->match) {
935 m_match = m->match;
936 m_mask = m->mask;
913 break; 937 break;
914 start += PAGE_SIZE; 938 }
915 } 939 }
916 940
917 if (start > end) 941 if (num_node_masks == _nid) {
918 start = end; 942 /* We could not find NUMA group, so default to 0, but lets
943 * search for latency group, so we could calculate the correct
944 * end address that we return
945 */
946 _nid = 0;
919 947
920 return start; 948 for (i = 0; i < num_mlgroups; i++) {
949 struct mdesc_mlgroup *const m = &mlgroups[i];
950
951 if ((pa_start & m->mask) == m->match) {
952 m_match = m->match;
953 m_mask = m->mask;
954 break;
955 }
956 }
957
958 if (i == num_mlgroups) {
959 WARN_ONCE(1, "memblock_nid_range: Can't find latency group addr[%Lx]",
960 start);
961
962 ret_end = end;
963 goto done;
964 }
965 }
966
967 /*
968 * Each latency group has match and mask, and each memory block has an
969 * offset. An address belongs to a latency group if its address matches
970 * the following formula: ((addr + offset) & mask) == match
971 * It is, however, slow to check every single page if it matches a
972 * particular latency group. As optimization we calculate end value by
973 * using bit arithmetics.
974 */
975 m_end = m_match + (1ul << __ffs(m_mask)) - mblock->offset;
976 m_end += pa_start & ~((1ul << fls64(m_mask)) - 1);
977 ret_end = m_end > end ? end : m_end;
978
979done:
980 *nid = _nid;
981 return ret_end;
921} 982}
922#endif 983#endif
923 984
@@ -958,7 +1019,8 @@ static void init_node_masks_nonnuma(void)
958 1019
959 numadbg("Initializing tables for non-numa.\n"); 1020 numadbg("Initializing tables for non-numa.\n");
960 1021
961 node_masks[0].mask = node_masks[0].val = 0; 1022 node_masks[0].mask = 0;
1023 node_masks[0].match = 0;
962 num_node_masks = 1; 1024 num_node_masks = 1;
963 1025
964#ifdef CONFIG_NEED_MULTIPLE_NODES 1026#ifdef CONFIG_NEED_MULTIPLE_NODES
@@ -976,15 +1038,6 @@ EXPORT_SYMBOL(numa_cpu_lookup_table);
976EXPORT_SYMBOL(numa_cpumask_lookup_table); 1038EXPORT_SYMBOL(numa_cpumask_lookup_table);
977EXPORT_SYMBOL(node_data); 1039EXPORT_SYMBOL(node_data);
978 1040
979struct mdesc_mlgroup {
980 u64 node;
981 u64 latency;
982 u64 match;
983 u64 mask;
984};
985static struct mdesc_mlgroup *mlgroups;
986static int num_mlgroups;
987
988static int scan_pio_for_cfg_handle(struct mdesc_handle *md, u64 pio, 1041static int scan_pio_for_cfg_handle(struct mdesc_handle *md, u64 pio,
989 u32 cfg_handle) 1042 u32 cfg_handle)
990{ 1043{
@@ -1226,41 +1279,6 @@ int __node_distance(int from, int to)
1226 return numa_latency[from][to]; 1279 return numa_latency[from][to];
1227} 1280}
1228 1281
1229static int find_numa_node_for_addr(unsigned long pa,
1230 struct node_mem_mask *pnode_mask)
1231{
1232 struct mdesc_handle *md = mdesc_grab();
1233 u64 node, arc;
1234 int i = 0;
1235
1236 node = mdesc_node_by_name(md, MDESC_NODE_NULL, "latency-groups");
1237 if (node == MDESC_NODE_NULL)
1238 goto out;
1239
1240 mdesc_for_each_node_by_name(md, node, "group") {
1241 mdesc_for_each_arc(arc, md, node, MDESC_ARC_TYPE_FWD) {
1242 u64 target = mdesc_arc_target(md, arc);
1243 struct mdesc_mlgroup *m = find_mlgroup(target);
1244
1245 if (!m)
1246 continue;
1247 if ((pa & m->mask) == m->match) {
1248 if (pnode_mask) {
1249 pnode_mask->mask = m->mask;
1250 pnode_mask->val = m->match;
1251 }
1252 mdesc_release(md);
1253 return i;
1254 }
1255 }
1256 i++;
1257 }
1258
1259out:
1260 mdesc_release(md);
1261 return -1;
1262}
1263
1264static int __init find_best_numa_node_for_mlgroup(struct mdesc_mlgroup *grp) 1282static int __init find_best_numa_node_for_mlgroup(struct mdesc_mlgroup *grp)
1265{ 1283{
1266 int i; 1284 int i;
@@ -1268,7 +1286,7 @@ static int __init find_best_numa_node_for_mlgroup(struct mdesc_mlgroup *grp)
1268 for (i = 0; i < MAX_NUMNODES; i++) { 1286 for (i = 0; i < MAX_NUMNODES; i++) {
1269 struct node_mem_mask *n = &node_masks[i]; 1287 struct node_mem_mask *n = &node_masks[i];
1270 1288
1271 if ((grp->mask == n->mask) && (grp->match == n->val)) 1289 if ((grp->mask == n->mask) && (grp->match == n->match))
1272 break; 1290 break;
1273 } 1291 }
1274 return i; 1292 return i;
@@ -1323,10 +1341,10 @@ static int __init numa_attach_mlgroup(struct mdesc_handle *md, u64 grp,
1323 n = &node_masks[num_node_masks++]; 1341 n = &node_masks[num_node_masks++];
1324 1342
1325 n->mask = candidate->mask; 1343 n->mask = candidate->mask;
1326 n->val = candidate->match; 1344 n->match = candidate->match;
1327 1345
1328 numadbg("NUMA NODE[%d]: mask[%lx] val[%lx] (latency[%llx])\n", 1346 numadbg("NUMA NODE[%d]: mask[%lx] match[%lx] (latency[%llx])\n",
1329 index, n->mask, n->val, candidate->latency); 1347 index, n->mask, n->match, candidate->latency);
1330 1348
1331 return 0; 1349 return 0;
1332} 1350}
@@ -1423,7 +1441,7 @@ static int __init numa_parse_jbus(void)
1423 numa_cpu_lookup_table[cpu] = index; 1441 numa_cpu_lookup_table[cpu] = index;
1424 cpumask_copy(&numa_cpumask_lookup_table[index], cpumask_of(cpu)); 1442 cpumask_copy(&numa_cpumask_lookup_table[index], cpumask_of(cpu));
1425 node_masks[index].mask = ~((1UL << 36UL) - 1UL); 1443 node_masks[index].mask = ~((1UL << 36UL) - 1UL);
1426 node_masks[index].val = cpu << 36UL; 1444 node_masks[index].match = cpu << 36UL;
1427 1445
1428 index++; 1446 index++;
1429 } 1447 }