On Wed, 11 Aug 2021, Wei Chen wrote: > A NUMA aware device tree will provide a "distance-map" node to > describe distance between any two nodes. This patch introduce a > new helper to parse this distance map. > > Signed-off-by: Wei Chen <wei.c...@arm.com> > --- > xen/arch/arm/numa_device_tree.c | 67 +++++++++++++++++++++++++++++++++ > 1 file changed, 67 insertions(+) > > diff --git a/xen/arch/arm/numa_device_tree.c b/xen/arch/arm/numa_device_tree.c > index bbe081dcd1..6e0d1d3d9f 100644 > --- a/xen/arch/arm/numa_device_tree.c > +++ b/xen/arch/arm/numa_device_tree.c > @@ -200,3 +200,70 @@ device_tree_parse_numa_memory_node(const void *fdt, int > node, > > return 0; > } > + > +/* Parse NUMA distance map v1 */ > +int __init > +device_tree_parse_numa_distance_map_v1(const void *fdt, int node) > +{ > + const struct fdt_property *prop; > + const __be32 *matrix; > + int entry_count, len, i; > + > + printk(XENLOG_INFO "NUMA: parsing numa-distance-map\n"); > + > + prop = fdt_get_property(fdt, node, "distance-matrix", &len); > + if ( !prop ) > + { > + printk(XENLOG_WARNING > + "NUMA: No distance-matrix property in distance-map\n"); > + > + return -EINVAL; > + } > + > + if ( len % sizeof(uint32_t) != 0 ) > + { > + printk(XENLOG_WARNING > + "distance-matrix in node is not a multiple of u32\n"); > + return -EINVAL; > + } > + > + entry_count = len / sizeof(uint32_t); > + if ( entry_count <= 0 ) > + { > + printk(XENLOG_WARNING "NUMA: Invalid distance-matrix\n"); > + > + return -EINVAL; > + } > + > + matrix = (const __be32 *)prop->data; > + for ( i = 0; i + 2 < entry_count; i += 3 ) > + { > + uint32_t from, to, distance; > + > + from = dt_read_number(matrix, 1); > + matrix++; > + to = dt_read_number(matrix, 1); > + matrix++; > + distance = dt_read_number(matrix, 1); > + matrix++; > + > + if ( (from == to && distance != NUMA_LOCAL_DISTANCE) || > + (from != to && distance <= NUMA_LOCAL_DISTANCE) ) > + { > + printk(XENLOG_WARNING > + "Invalid nodes' distance from node#%d to node#%d = %d\n", > + from, to, distance); > + return -EINVAL; > + } > + > + printk(XENLOG_INFO "NUMA: distance from node#%d to node#%d = %d\n", > + from, to, distance); > + numa_set_distance(from, to, distance); > + > + /* Set default distance of node B->A same as A->B */ > + if (to > from) > + numa_set_distance(to, from, distance);
I am a bit unsure about this last 2 lines: why calling numa_set_distance in the opposite direction only when to > from? Wouldn't it be OK to always do both: numa_set_distance(from, to, distance); numa_set_distance(to, from, distance); ? But in any case, I have a different suggestion. The binding states that "distances are equal in either direction". Also it has an example where only one direction is expressed unfortunately (at the end of the document). So my suggestion is to parse it as follows: - call numa_set_distance just once from device_tree_parse_numa_distance_map_v1 - in numa_set_distance: - set node_distance_map[from][to] = distance; - check node_distance_map[to][from] - if unset, node_distance_map[to][from] = distance; - if already set to the same value, return success; - if already set to a different value, return error;