|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 06/21] xen/device-tree: Read NUMA node distance from Device Tree 'distance-map'
Read the distance between NUMA nodes from the Device Tree's
'distance-map' node.
---
xen/arch/arm/numa.c | 2 +
xen/common/device-tree/numa.c | 93 ++++++++++++++++++++++++++++++++++-
xen/include/xen/dt-numa.h | 1 +
3 files changed, 94 insertions(+), 2 deletions(-)
diff --git a/xen/arch/arm/numa.c b/xen/arch/arm/numa.c
index 15cad3d267..a7769b0c7d 100644
--- a/xen/arch/arm/numa.c
+++ b/xen/arch/arm/numa.c
@@ -41,6 +41,8 @@ void __init numa_memory_affinity_init(void)
dt_numa_memory_affinity_init();
numa_initmem_init(0x0UL, 0x1UL << (PADDR_BITS - 12));
+
+ dt_numa_distance_table_init();
}
int __init arch_get_ram_range(unsigned int idx, paddr_t *start, paddr_t *end)
diff --git a/xen/common/device-tree/numa.c b/xen/common/device-tree/numa.c
index 539ddfccc5..6414806937 100644
--- a/xen/common/device-tree/numa.c
+++ b/xen/common/device-tree/numa.c
@@ -1,4 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Derived from Linux kernel 7.0's $drivers/of/of_numa.c
+ * Parse 'distance-map'
+ *
+ * Copyright (c) 2026 VA Linux Systems Japan K.K.
+ * Author: Hirokazu Takahashi <taka@xxxxxxxxxxxxx>
+ */
#include <xen/bootinfo.h>
#include <xen/device_tree.h>
@@ -12,14 +19,96 @@
#define LOCAL_DISTANCE 10
#define REMOTE_DISTANCE 20
+static u8 __ro_after_init numa_distance[MAX_NUMNODES][MAX_NUMNODES] = {
+ [0 ... MAX_NUMNODES-1][0 ... MAX_NUMNODES-1] = NUMA_NO_DISTANCE
+};
+
/*
* Get the distance between node 'a' and node 'b'.
*/
u8 dt_node_distance(u8 a, u8 b)
{
- if ( a != b )
+ nodeid_t lastnode = last_node(node_online_map);
+
+ if (a > lastnode || b > lastnode)
return REMOTE_DISTANCE;
- return LOCAL_DISTANCE;
+
+ return numa_distance[a][b];
+}
+
+static void __init numa_set_distance(u8 from, u8 to, u8 distance)
+{
+ nodeid_t lastnode = last_node(node_online_map);
+
+ if (from <= lastnode && to <= lastnode)
+ numa_distance[from][to] = distance;
+}
+
+/*
+ * Parse the '/distance-map' node from the flattened device tree
+ * and extract the 3-tuple triplets <from, to, distance>.
+ */
+static void __init dt_numa_parse_distance_map(void)
+{
+ const void *fdt = device_tree_flattened;
+ const struct fdt_property *prop;
+ const __be32 *matrix;
+ int entry_count;
+ int node;
+ int len;
+ int i;
+
+ node = fdt_path_offset(fdt, "/distance-map");
+ if ( node < 0 )
+ return;
+
+ if (fdt_node_check_compatible(fdt, node, "numa-distance-map-v1"))
+ return;
+
+ prop = fdt_get_property(fdt, node, "distance-matrix", &len);
+ if (!prop)
+ return;
+
+ matrix = (const __be32*)prop->data;
+ entry_count = len / sizeof(__be32);
+
+ if ( (entry_count <= 0) || (entry_count % 3) )
+ return;
+
+ for (i = 0; i + 2 < entry_count; i += 3)
+ {
+ u32 nodea, nodeb, distance;
+ nodea = dt_next_cell(1, &matrix);
+ nodeb = dt_next_cell(1, &matrix);
+ distance = dt_next_cell(1, &matrix);
+
+ if ((nodea == nodeb && distance != LOCAL_DISTANCE) ||
+ (nodea != nodeb && distance <= LOCAL_DISTANCE))
+ {
+ printk(XENLOG_WARNING "Invalid distance[node%d -> node%d] = %d\n",
+ nodea, nodeb, distance);
+ continue;
+ }
+
+ numa_set_distance(nodea, nodeb, distance);
+
+ /* Set default distance of node B->A same as A->B */
+ if (nodeb > nodea)
+ numa_set_distance(nodeb, nodea, distance);
+ }
+}
+
+void __init dt_numa_distance_table_init(void)
+{
+ u32 lastnode = last_node(node_online_map);
+ u32 i, j;
+
+ /* fill with the default distances */
+ for (i = 0U; i <= lastnode; i++)
+ for (j = 0U; j <= lastnode; j++)
+ numa_distance[i][j] = i == j ? LOCAL_DISTANCE : REMOTE_DISTANCE;
+
+ dt_numa_parse_distance_map();
}
/*
diff --git a/xen/include/xen/dt-numa.h b/xen/include/xen/dt-numa.h
index c6939d0928..075d31cb89 100644
--- a/xen/include/xen/dt-numa.h
+++ b/xen/include/xen/dt-numa.h
@@ -15,6 +15,7 @@ static inline unsigned int numa_node_to_dt_nid(u32 n)
u8 dt_node_distance(u8 a, u8 b);
void dt_numa_memory_affinity_init(void);
+void dt_numa_distance_table_init(void);
#endif /* CONFIG_DEVICE_TREE_NUMA */
--
2.43.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |