@@ -829,13 +829,23 @@ static void __init find_ramdisk(unsigned long phys_base)
829
829
830
830
struct node_mem_mask {
831
831
unsigned long mask ;
832
- unsigned long val ;
832
+ unsigned long match ;
833
833
};
834
834
static struct node_mem_mask node_masks [MAX_NUMNODES ];
835
835
static int num_node_masks ;
836
836
837
837
#ifdef CONFIG_NEED_MULTIPLE_NODES
838
838
839
+ struct mdesc_mlgroup {
840
+ u64 node ;
841
+ u64 latency ;
842
+ u64 match ;
843
+ u64 mask ;
844
+ };
845
+
846
+ static struct mdesc_mlgroup * mlgroups ;
847
+ static int num_mlgroups ;
848
+
839
849
int numa_cpu_lookup_table [NR_CPUS ];
840
850
cpumask_t numa_cpumask_lookup_table [MAX_NUMNODES ];
841
851
@@ -846,78 +856,129 @@ struct mdesc_mblock {
846
856
};
847
857
static struct mdesc_mblock * mblocks ;
848
858
static int num_mblocks ;
849
- static int find_numa_node_for_addr (unsigned long pa ,
850
- struct node_mem_mask * pnode_mask );
851
859
852
- static unsigned long __init ra_to_pa (unsigned long addr )
860
+ static struct mdesc_mblock * __init addr_to_mblock (unsigned long addr )
853
861
{
862
+ struct mdesc_mblock * m = NULL ;
854
863
int i ;
855
864
856
865
for (i = 0 ; i < num_mblocks ; i ++ ) {
857
- struct mdesc_mblock * m = & mblocks [i ];
866
+ m = & mblocks [i ];
858
867
859
868
if (addr >= m -> base &&
860
869
addr < (m -> base + m -> size )) {
861
- addr += m -> offset ;
862
870
break ;
863
871
}
864
872
}
865
- return addr ;
873
+
874
+ return m ;
866
875
}
867
876
868
- static int __init find_node ( unsigned long addr )
877
+ static u64 __init memblock_nid_range_sun4u ( u64 start , u64 end , int * nid )
869
878
{
870
- static bool search_mdesc = true;
871
- static struct node_mem_mask last_mem_mask = { ~0UL , ~0UL };
872
- static int last_index ;
873
- int i ;
879
+ int prev_nid , new_nid ;
874
880
875
- addr = ra_to_pa (addr );
876
- for (i = 0 ; i < num_node_masks ; i ++ ) {
877
- struct node_mem_mask * p = & node_masks [i ];
881
+ prev_nid = -1 ;
882
+ for ( ; start < end ; start += PAGE_SIZE ) {
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 )
880
- return i ;
881
- }
882
- /* The following condition has been observed on LDOM guests because
883
- * node_masks only contains the best latency mask and value.
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 ;
886
+ if ((start & p -> mask ) == p -> match ) {
887
+ if (prev_nid == -1 )
888
+ prev_nid = new_nid ;
889
+ break ;
890
+ }
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
905
908
static u64 __init memblock_nid_range (u64 start , u64 end , int * nid )
906
909
{
907
- * nid = find_node (start );
908
- start += PAGE_SIZE ;
909
- while (start < end ) {
910
- int n = find_node (start );
910
+ u64 ret_end , pa_start , m_mask , m_match , m_end ;
911
+ struct mdesc_mblock * mblock ;
912
+ int _nid , i ;
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
937
break ;
914
- start += PAGE_SIZE ;
938
+ }
915
939
}
916
940
917
- if (start > end )
918
- start = end ;
941
+ if (num_node_masks == _nid ) {
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
+
979
+ done :
980
+ * nid = _nid ;
981
+ return ret_end ;
921
982
}
922
983
#endif
923
984
@@ -958,7 +1019,8 @@ static void init_node_masks_nonnuma(void)
958
1019
959
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
1024
num_node_masks = 1 ;
963
1025
964
1026
#ifdef CONFIG_NEED_MULTIPLE_NODES
@@ -976,15 +1038,6 @@ EXPORT_SYMBOL(numa_cpu_lookup_table);
976
1038
EXPORT_SYMBOL (numa_cpumask_lookup_table );
977
1039
EXPORT_SYMBOL (node_data );
978
1040
979
- struct mdesc_mlgroup {
980
- u64 node ;
981
- u64 latency ;
982
- u64 match ;
983
- u64 mask ;
984
- };
985
- static struct mdesc_mlgroup * mlgroups ;
986
- static int num_mlgroups ;
987
-
988
1041
static int scan_pio_for_cfg_handle (struct mdesc_handle * md , u64 pio ,
989
1042
u32 cfg_handle )
990
1043
{
@@ -1226,49 +1279,14 @@ int __node_distance(int from, int to)
1226
1279
return numa_latency [from ][to ];
1227
1280
}
1228
1281
1229
- static 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
-
1259
- out :
1260
- mdesc_release (md );
1261
- return -1 ;
1262
- }
1263
-
1264
1282
static int __init find_best_numa_node_for_mlgroup (struct mdesc_mlgroup * grp )
1265
1283
{
1266
1284
int i ;
1267
1285
1268
1286
for (i = 0 ; i < MAX_NUMNODES ; i ++ ) {
1269
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
1290
break ;
1273
1291
}
1274
1292
return i ;
@@ -1323,10 +1341,10 @@ static int __init numa_attach_mlgroup(struct mdesc_handle *md, u64 grp,
1323
1341
n = & node_masks [num_node_masks ++ ];
1324
1342
1325
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" ,
1329
- index , n -> mask , n -> val , candidate -> latency );
1346
+ numadbg ("NUMA NODE[%d]: mask[%lx] match [%lx] (latency[%llx])\n" ,
1347
+ index , n -> mask , n -> match , candidate -> latency );
1330
1348
1331
1349
return 0 ;
1332
1350
}
@@ -1423,7 +1441,7 @@ static int __init numa_parse_jbus(void)
1423
1441
numa_cpu_lookup_table [cpu ] = index ;
1424
1442
cpumask_copy (& numa_cpumask_lookup_table [index ], cpumask_of (cpu ));
1425
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
1446
index ++ ;
1429
1447
}
0 commit comments