@@ -800,8 +800,10 @@ struct mdesc_mblock {
800800};
801801static struct mdesc_mblock * mblocks ;
802802static int num_mblocks ;
803+ static int find_numa_node_for_addr (unsigned long pa ,
804+ struct node_mem_mask * pnode_mask );
803805
804- static unsigned long ra_to_pa (unsigned long addr )
806+ static unsigned long __init ra_to_pa (unsigned long addr )
805807{
806808 int i ;
807809
@@ -817,8 +819,11 @@ static unsigned long ra_to_pa(unsigned long addr)
817819 return addr ;
818820}
819821
820- static int find_node (unsigned long addr )
822+ static int __init find_node (unsigned long addr )
821823{
824+ static bool search_mdesc = true;
825+ static struct node_mem_mask last_mem_mask = { ~0UL , ~0UL };
826+ static int last_index ;
822827 int i ;
823828
824829 addr = ra_to_pa (addr );
@@ -828,13 +833,30 @@ static int find_node(unsigned long addr)
828833 if ((addr & p -> mask ) == p -> val )
829834 return i ;
830835 }
831- /* The following condition has been observed on LDOM guests.*/
832- WARN_ONCE (1 , "find_node: A physical address doesn't match a NUMA node"
833- " rule. Some physical memory will be owned by node 0." );
834- return 0 ;
836+ /* The following condition has been observed on LDOM guests because
837+ * node_masks only contains the best latency mask and value.
838+ * LDOM guest's mdesc can contain a single latency group to
839+ * cover multiple address range. Print warning message only if the
840+ * address cannot be found in node_masks nor mdesc.
841+ */
842+ if ((search_mdesc ) &&
843+ ((addr & last_mem_mask .mask ) != last_mem_mask .val )) {
844+ /* find the available node in the mdesc */
845+ last_index = find_numa_node_for_addr (addr , & last_mem_mask );
846+ numadbg ("find_node: latency group for address 0x%lx is %d\n" ,
847+ addr , last_index );
848+ if ((last_index < 0 ) || (last_index >= num_node_masks )) {
849+ /* WARN_ONCE() and use default group 0 */
850+ WARN_ONCE (1 , "find_node: A physical address doesn't match a NUMA node rule. Some physical memory will be owned by node 0." );
851+ search_mdesc = false;
852+ last_index = 0 ;
853+ }
854+ }
855+
856+ return last_index ;
835857}
836858
837- static u64 memblock_nid_range (u64 start , u64 end , int * nid )
859+ static u64 __init memblock_nid_range (u64 start , u64 end , int * nid )
838860{
839861 * nid = find_node (start );
840862 start += PAGE_SIZE ;
@@ -1158,6 +1180,41 @@ int __node_distance(int from, int to)
11581180 return numa_latency [from ][to ];
11591181}
11601182
1183+ static int find_numa_node_for_addr (unsigned long pa ,
1184+ struct node_mem_mask * pnode_mask )
1185+ {
1186+ struct mdesc_handle * md = mdesc_grab ();
1187+ u64 node , arc ;
1188+ int i = 0 ;
1189+
1190+ node = mdesc_node_by_name (md , MDESC_NODE_NULL , "latency-groups" );
1191+ if (node == MDESC_NODE_NULL )
1192+ goto out ;
1193+
1194+ mdesc_for_each_node_by_name (md , node , "group" ) {
1195+ mdesc_for_each_arc (arc , md , node , MDESC_ARC_TYPE_FWD ) {
1196+ u64 target = mdesc_arc_target (md , arc );
1197+ struct mdesc_mlgroup * m = find_mlgroup (target );
1198+
1199+ if (!m )
1200+ continue ;
1201+ if ((pa & m -> mask ) == m -> match ) {
1202+ if (pnode_mask ) {
1203+ pnode_mask -> mask = m -> mask ;
1204+ pnode_mask -> val = m -> match ;
1205+ }
1206+ mdesc_release (md );
1207+ return i ;
1208+ }
1209+ }
1210+ i ++ ;
1211+ }
1212+
1213+ out :
1214+ mdesc_release (md );
1215+ return -1 ;
1216+ }
1217+
11611218static int find_best_numa_node_for_mlgroup (struct mdesc_mlgroup * grp )
11621219{
11631220 int i ;
0 commit comments