Re: [Xen-devel] [RFC PATCH v3 14/24] ARM: NUMA: DT: Parse NUMA distance information
Hi Vijay, On 18/07/17 12:41, vijay.kil...@gmail.com wrote: From: Vijaya Kumar KParse distance-matrix and fetch node distance information. Store distance information in node_distance[]. Register dt_node_distance() function pointer with the ARM numa code. This approach can be later used for ACPI. After my comment on v1, I was expecting to see a link to the binding in the commit message... Signed-off-by: Vijaya Kumar K --- v3: - Moved __node_distance() declaration to common header file - Use device_tree_node_compatible() instead of device_tree_node_matches() - Dropped xen/errno.h inclusion --- xen/arch/arm/numa/dt_numa.c | 131 xen/arch/arm/numa/numa.c| 22 xen/include/asm-arm/numa.h | 2 + xen/include/asm-x86/numa.h | 1 - xen/include/xen/numa.h | 3 + 5 files changed, 158 insertions(+), 1 deletion(-) diff --git a/xen/arch/arm/numa/dt_numa.c b/xen/arch/arm/numa/dt_numa.c index 84030e7..46c0346 100644 --- a/xen/arch/arm/numa/dt_numa.c +++ b/xen/arch/arm/numa/dt_numa.c @@ -23,6 +23,48 @@ #include #include +static uint8_t node_distance[MAX_NUMNODES][MAX_NUMNODES]; On v1, you said that you will look at allocating node_distance on the fly. So why it is not done? You can give a look at alloc_boot_pages(...). + +static uint8_t dt_node_distance(nodeid_t nodea, nodeid_t nodeb) +{ +if ( nodea >= MAX_NUMNODES || nodeb >= MAX_NUMNODES ) +return nodea == nodeb ? LOCAL_DISTANCE : REMOTE_DISTANCE; Do we really expect dt_node_distance to be called with wrong node? Looking at the ACPI code, they don't check that... So likely this should be an ASSERT(...). + +return node_distance[nodea][nodeb]; +} + +static int dt_numa_set_distance(uint32_t nodea, uint32_t nodeb, I think this should be __init. +uint32_t distance) +{ + /* node_distance is uint8_t. Ensure distance is less than 255 */ + if ( nodea >= MAX_NUMNODES || nodeb >= MAX_NUMNODES || distance > 255 ) + return -EINVAL; + + node_distance[nodea][nodeb] = distance; + + return 0; +} + +void init_dt_numa_distance(void) Ditto. +{ +int i, j; + +for ( i = 0; i < MAX_NUMNODES; i++ ) +{ +for ( j = 0; j < MAX_NUMNODES; j++ ) +{ +/* + * Initialize distance 10 for local distance and + * 20 for remote distance. + */ +if ( i == j ) +node_distance[i][j] = LOCAL_DISTANCE; +else +node_distance[i][j] = REMOTE_DISTANCE; +} +} +} + /* * Even though we connect cpus to numa domains later in SMP * init, we need to know the node ids now for all cpus. @@ -58,6 +100,76 @@ static int __init dt_numa_process_cpu_node(const void *fdt) return 0; } +static int __init dt_numa_parse_distance_map(const void *fdt, int node, + const char *name, + uint32_t address_cells, + uint32_t size_cells) +{ +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", ); +if ( !prop ) +{ +printk(XENLOG_WARNING s/XENLOG_WARNING/XENLOG_INFO/ because numa-distance-map is not mandatory. + "NUMA: No distance-matrix property in distance-map\n"); + +return -EINVAL; If I am reading correctly the binding, the distance-matrix is not mandatory. If it is not present, you should use a default matrix. But here you will disable NUMA completely. +} + +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 ) It would be easier to read if entry_count is the number of triplet. E.g entry_count = (len / sizeof(uint32_t)) / 3; for ( i = 0; i < entry_count; i++ ) +{ +uint32_t nodea, nodeb, distance; + +nodea = dt_read_number(matrix, 1); +matrix++; nodea = dt_next_cell(1, ) will do the increment for you. +nodeb = dt_read_number(matrix, 1); +matrix++; Ditto. +distance = dt_read_number(matrix, 1); +matrix++; Ditto. + +if ( dt_numa_set_distance(nodea, nodeb, distance) ) +{ +printk(XENLOG_WARNING + "NUMA: node-id out of range in distance matrix for [node%d -> node%d]\n", s/%d/%u/ +
[Xen-devel] [RFC PATCH v3 14/24] ARM: NUMA: DT: Parse NUMA distance information
From: Vijaya Kumar KParse distance-matrix and fetch node distance information. Store distance information in node_distance[]. Register dt_node_distance() function pointer with the ARM numa code. This approach can be later used for ACPI. Signed-off-by: Vijaya Kumar K --- v3: - Moved __node_distance() declaration to common header file - Use device_tree_node_compatible() instead of device_tree_node_matches() - Dropped xen/errno.h inclusion --- xen/arch/arm/numa/dt_numa.c | 131 xen/arch/arm/numa/numa.c| 22 xen/include/asm-arm/numa.h | 2 + xen/include/asm-x86/numa.h | 1 - xen/include/xen/numa.h | 3 + 5 files changed, 158 insertions(+), 1 deletion(-) diff --git a/xen/arch/arm/numa/dt_numa.c b/xen/arch/arm/numa/dt_numa.c index 84030e7..46c0346 100644 --- a/xen/arch/arm/numa/dt_numa.c +++ b/xen/arch/arm/numa/dt_numa.c @@ -23,6 +23,48 @@ #include #include +static uint8_t node_distance[MAX_NUMNODES][MAX_NUMNODES]; + +static uint8_t dt_node_distance(nodeid_t nodea, nodeid_t nodeb) +{ +if ( nodea >= MAX_NUMNODES || nodeb >= MAX_NUMNODES ) +return nodea == nodeb ? LOCAL_DISTANCE : REMOTE_DISTANCE; + +return node_distance[nodea][nodeb]; +} + +static int dt_numa_set_distance(uint32_t nodea, uint32_t nodeb, +uint32_t distance) +{ + /* node_distance is uint8_t. Ensure distance is less than 255 */ + if ( nodea >= MAX_NUMNODES || nodeb >= MAX_NUMNODES || distance > 255 ) + return -EINVAL; + + node_distance[nodea][nodeb] = distance; + + return 0; +} + +void init_dt_numa_distance(void) +{ +int i, j; + +for ( i = 0; i < MAX_NUMNODES; i++ ) +{ +for ( j = 0; j < MAX_NUMNODES; j++ ) +{ +/* + * Initialize distance 10 for local distance and + * 20 for remote distance. + */ +if ( i == j ) +node_distance[i][j] = LOCAL_DISTANCE; +else +node_distance[i][j] = REMOTE_DISTANCE; +} +} +} + /* * Even though we connect cpus to numa domains later in SMP * init, we need to know the node ids now for all cpus. @@ -58,6 +100,76 @@ static int __init dt_numa_process_cpu_node(const void *fdt) return 0; } +static int __init dt_numa_parse_distance_map(const void *fdt, int node, + const char *name, + uint32_t address_cells, + uint32_t size_cells) +{ +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", ); +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 nodea, nodeb, distance; + +nodea = dt_read_number(matrix, 1); +matrix++; +nodeb = dt_read_number(matrix, 1); +matrix++; +distance = dt_read_number(matrix, 1); +matrix++; + +if ( dt_numa_set_distance(nodea, nodeb, distance) ) +{ +printk(XENLOG_WARNING + "NUMA: node-id out of range in distance matrix for [node%d -> node%d]\n", + nodea, nodeb); +return -EINVAL; + +} +printk(XENLOG_INFO "NUMA: distance[node%d -> node%d] = %d\n", + nodea, nodeb, distance); + +/* + * Set default distance of node B->A same as A->B. + * No need to check for return value of numa_set_distance. + */ +if ( nodeb > nodea ) +dt_numa_set_distance(nodeb, nodea, distance); +} + +return 0; +} + void __init dt_numa_process_memory_node(uint32_t nid, paddr_t start, paddr_t size) { @@ -90,11 +202,30 @@ void __init dt_numa_process_memory_node(uint32_t nid, paddr_t start, return; } +static int __init dt_numa_scan_distance_node(const void *fdt, int node, + const char *name, int depth, + uint32_t address_cells, + uint32_t size_cells, void *data) +{ +if ( device_tree_node_compatible(fdt, node,