From: Zhao Liu <zhao1.liu@xxxxxxxxx> Currenltly cpu-cluster is used in TCG case to organize CPUs with the same type. Wrap 2 things into TCG specific areas: 1. cluster-id: The cluster-id in TCG case is global, since no higher topology container above cluster. To simplify the logic of cluster topology in virtualization, move the cluster-id into CONFIG_TCG, then it won't be exposed in cli. 2. CPU collection in realize(): In TCG case, the CPUs are added into cluster directly via child<> property. But in virtualization case, the CPU topology will be built via topology tree. Thus, wrap CPU collection as the TCG operation. Signed-off-by: Zhao Liu <zhao1.liu@xxxxxxxxx> --- hw/cpu/cluster.c | 30 +++++++++++++++++++++++++----- include/hw/cpu/cluster.h | 22 ++++++++++++++++++++-- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/hw/cpu/cluster.c b/hw/cpu/cluster.c index fd978a543e40..340cfad9f8f1 100644 --- a/hw/cpu/cluster.c +++ b/hw/cpu/cluster.c @@ -26,7 +26,9 @@ #include "qapi/error.h" static Property cpu_cluster_properties[] = { +#ifdef CONFIG_TCG DEFINE_PROP_UINT32("cluster-id", CPUCluster, cluster_id, 0), +#endif DEFINE_PROP_END_OF_LIST() }; @@ -47,18 +49,17 @@ static int add_cpu_to_cluster(Object *obj, void *opaque) return 0; } -static void cpu_cluster_realize(DeviceState *dev, Error **errp) +static void cpu_cluster_common_collect_cpus(CPUCluster *cluster, Error **errp) { /* Iterate through all our CPU children and set their cluster_index */ - CPUCluster *cluster = CPU_CLUSTER(dev); - Object *cluster_obj = OBJECT(dev); + Object *cluster_obj = OBJECT(cluster); CallbackData cbdata = { .cluster = cluster, .cpu_count = 0, }; - if (cluster->cluster_id >= MAX_CLUSTERS) { - error_setg(errp, "cluster-id must be less than %d", MAX_CLUSTERS); + if (cluster->cluster_id >= MAX_TCG_CLUSTERS) { + error_setg(errp, "cluster-id must be less than %d", MAX_TCG_CLUSTERS); return; } @@ -73,15 +74,34 @@ static void cpu_cluster_realize(DeviceState *dev, Error **errp) assert(cbdata.cpu_count > 0); } +static const struct TCGClusterOps common_cluster_tcg_ops = { + .collect_cpus = cpu_cluster_common_collect_cpus, +}; + +static void cpu_cluster_realize(DeviceState *dev, Error **errp) +{ + CPUCluster *cluster = CPU_CLUSTER(dev); + CPUClusterClass *cc = CPU_CLUSTER_GET_CLASS(dev); + + if (cc->tcg_clu_ops->collect_cpus) { + cc->tcg_clu_ops->collect_cpus(cluster, errp); + } +} + static void cpu_cluster_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + CPUClusterClass *cc = CPU_CLUSTER_CLASS(klass); device_class_set_props(dc, cpu_cluster_properties); dc->realize = cpu_cluster_realize; /* This is not directly for users, CPU children must be attached by code */ dc->user_creatable = false; + +#ifdef CONFIG_TCG + cc->tcg_clu_ops = &common_cluster_tcg_ops; +#endif } static const TypeInfo cpu_cluster_type_info = { diff --git a/include/hw/cpu/cluster.h b/include/hw/cpu/cluster.h index 644b87350268..c038f05ddc9f 100644 --- a/include/hw/cpu/cluster.h +++ b/include/hw/cpu/cluster.h @@ -55,13 +55,31 @@ */ #define TYPE_CPU_CLUSTER "cpu-cluster" -OBJECT_DECLARE_SIMPLE_TYPE(CPUCluster, CPU_CLUSTER) +OBJECT_DECLARE_TYPE(CPUCluster, CPUClusterClass, CPU_CLUSTER) /* * This limit is imposed by TCG, which puts the cluster ID into an * 8 bit field (and uses all-1s for the default "not in any cluster"). */ -#define MAX_CLUSTERS 255 +#define MAX_TCG_CLUSTERS 255 + +struct TCGClusterOps { + /** + * @collect_cpus: Iterate children CPUs and set cluser_index. + * + * Called when the cluster is realized. + */ + void (*collect_cpus)(CPUCluster *cluster, Error **errp); +}; + +struct CPUClusterClass { + /*< private >*/ + DeviceClass parent_class; + + /*< public >*/ + /* when TCG is not available, this pointer is NULL */ + const struct TCGClusterOps *tcg_clu_ops; +}; /** * CPUCluster: -- 2.34.1