From: Zhao Liu <zhao1.liu@xxxxxxxxx> Topology index is used to identify the topology child under the same parent topology device. This field corresponds to the topology sub index (e.g., socket-id/ core-id/thread-id) used for addressing. Signed-off-by: Zhao Liu <zhao1.liu@xxxxxxxxx> --- hw/core/cpu-topo.c | 77 ++++++++++++++++++++++++++++++++++++++ include/hw/core/cpu-topo.h | 6 +++ 2 files changed, 83 insertions(+) diff --git a/hw/core/cpu-topo.c b/hw/core/cpu-topo.c index 4428b979a5dc..3e0c183388d8 100644 --- a/hw/core/cpu-topo.c +++ b/hw/core/cpu-topo.c @@ -50,6 +50,66 @@ static const char *cpu_topo_level_to_string(CPUTopoLevel level) return NULL; } +static void cpu_topo_refresh_free_child_index(CPUTopoState *topo) +{ + CPUTopoState *child; + + /* + * Fast way: Assume that the index grows sequentially and that there + * are no "index hole" in the previous children. + * + * The previous check on num_children ensures that free_child_index + 1 + * does not hit the max_children limit. + */ + if (topo->free_child_index + 1 == topo->num_children) { + topo->free_child_index++; + return; + } + + /* Slow way: Search the "index hole". The index hole must be found. */ + for (int index = 0; index < topo->num_children; index++) { + bool existed = false; + + QTAILQ_FOREACH(child, &topo->children, sibling) { + if (child->index == index) { + existed = true; + break; + } + } + + if (!existed) { + topo->free_child_index = index; + return; + } + } +} + +static void cpu_topo_validate_index(CPUTopoState *topo, Error **errp) +{ + CPUTopoState *parent = topo->parent, *child; + + if (topo->index < 0) { + error_setg(errp, "Invalid topology index (%d).", + topo->index); + return; + } + + if (parent->max_children && topo->index >= parent->max_children) { + error_setg(errp, "Invalid topology index (%d): " + "The maximum index is %d.", + topo->index, parent->max_children); + return; + } + + QTAILQ_FOREACH(child, &topo->children, sibling) { + if (child->index == topo->index) { + error_setg(errp, "Duplicate topology index (%d)", + topo->index); + return; + } + } +} + static void cpu_topo_build_hierarchy(CPUTopoState *topo, Error **errp) { CPUTopoState *parent = topo->parent; @@ -80,7 +140,18 @@ static void cpu_topo_build_hierarchy(CPUTopoState *topo, Error **errp) } parent->num_children++; + if (topo->index == UNASSIGNED_TOPO_INDEX) { + topo->index = parent->free_child_index; + } else if (topo->index != parent->free_child_index) { + /* The index has been set, then we need to validate it. */ + cpu_topo_validate_index(topo, errp); + if (*errp) { + return; + } + } + QTAILQ_INSERT_TAIL(&parent->children, topo, sibling); + cpu_topo_refresh_free_child_index(parent); } static void cpu_topo_set_parent(CPUTopoState *topo, Error **errp) @@ -135,6 +206,10 @@ static void cpu_topo_destroy_hierarchy(CPUTopoState *topo) QTAILQ_REMOVE(&parent->children, topo, sibling); parent->num_children--; + if (topo->index < parent->free_child_index) { + parent->free_child_index = topo->index; + } + if (!parent->num_children) { parent->child_level = CPU_TOPO_UNKNOWN; } @@ -180,6 +255,8 @@ static void cpu_topo_instance_init(Object *obj) CPUTopoState *topo = CPU_TOPO(obj); QTAILQ_INIT(&topo->children); + topo->index = UNASSIGNED_TOPO_INDEX; + topo->free_child_index = 0; topo->child_level = CPU_TOPO_UNKNOWN; } diff --git a/include/hw/core/cpu-topo.h b/include/hw/core/cpu-topo.h index ebcbdd854da5..c0dfff9dc63b 100644 --- a/include/hw/core/cpu-topo.h +++ b/include/hw/core/cpu-topo.h @@ -24,6 +24,8 @@ #include "hw/qdev-core.h" #include "qemu/queue.h" +#define UNASSIGNED_TOPO_INDEX -1 + typedef enum CPUTopoLevel { CPU_TOPO_UNKNOWN, CPU_TOPO_THREAD, @@ -53,6 +55,8 @@ struct CPUTopoClass { /** * CPUTopoState: + * @index: Topology index within parent's topology queue. + * @free_child_index: Cached free index to be specified for next child. * @num_children: Number of topology children under this topology device. * @max_children: Maximum number of children allowed to be inserted under * this topology device. @@ -66,6 +70,8 @@ struct CPUTopoState { DeviceState parent_obj; /*< public >*/ + int index; + int free_child_index; int num_children; int max_children; CPUTopoLevel child_level; -- 2.34.1