From: Zhao Liu <zhao1.liu@xxxxxxxxx> When the core abstraction is applied for the architecture support CPU hotplug, the plugged CPUs and unplugged CPUs are distributed among the cores created in the topology tree. Add plugged_threads field to help cpu-core decide to how many CPUs to create. Signed-off-by: Zhao Liu <zhao1.liu@xxxxxxxxx> --- hw/cpu/core.c | 33 +++++++++++++++++++++++++++++++++ hw/ppc/pnv_core.c | 6 +++++- hw/ppc/spapr_cpu_core.c | 6 +++++- include/hw/cpu/core.h | 9 +++++++++ include/hw/ppc/pnv_core.h | 2 ++ include/hw/ppc/spapr_cpu_core.h | 2 ++ 6 files changed, 56 insertions(+), 2 deletions(-) diff --git a/hw/cpu/core.c b/hw/cpu/core.c index 7e274d6aebb7..15546b5b2339 100644 --- a/hw/cpu/core.c +++ b/hw/cpu/core.c @@ -36,6 +36,20 @@ static void core_prop_set_nr_threads(Object *obj, Visitor *v, const char *name, core->nr_threads = value; } +static void core_prop_set_plugged_threads(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + CPUCore *core = CPU_CORE(obj); + int64_t value; + + if (!visit_type_int(v, name, &value, errp)) { + return; + } + + core->plugged_threads = value; +} + static void cpu_core_instance_init(Object *obj) { CPUCore *core = CPU_CORE(obj); @@ -48,6 +62,22 @@ static void cpu_core_instance_init(Object *obj) if (current_machine) { core->nr_threads = current_machine->smp.threads; } + + core->plugged_threads = -1; +} + +static void cpu_core_realize(DeviceState *dev, Error **errp) +{ + CPUCore *core = CPU_CORE(dev); + + if (core->plugged_threads > core->nr_threads) { + error_setg(errp, "Plugged threads (plugged-threads: %d) must " + "not be more than max threads (nr-threads: %d)", + core->plugged_threads, core->nr_threads); + return; + } else if (core->plugged_threads == -1) { + core->plugged_threads = core->nr_threads; + } } static void cpu_core_class_init(ObjectClass *oc, void *data) @@ -57,6 +87,9 @@ static void cpu_core_class_init(ObjectClass *oc, void *data) set_bit(DEVICE_CATEGORY_CPU, dc->categories); object_class_property_add(oc, "nr-threads", "int", core_prop_get_nr_threads, core_prop_set_nr_threads, NULL, NULL); + object_class_property_add(oc, "plugged-threads", "int", NULL, + core_prop_set_plugged_threads, NULL, NULL); + dc->realize = cpu_core_realize; } static const TypeInfo cpu_core_type_info = { diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index a90d1ec92bd8..8b75739697d1 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -276,6 +276,8 @@ static void pnv_core_realize(DeviceState *dev, Error **errp) assert(pc->chip); + pcc->parent_realize(dev, errp); + pc->threads = g_new(PowerPCCPU *, cc->nr_threads); for (i = 0; i < cc->nr_threads; i++) { PowerPCCPU *cpu; @@ -376,11 +378,13 @@ static void pnv_core_power10_class_init(ObjectClass *oc, void *data) static void pnv_core_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); + PnvCoreClass *pcc = PNV_CORE_CLASS(oc); - dc->realize = pnv_core_realize; dc->unrealize = pnv_core_unrealize; device_class_set_props(dc, pnv_core_properties); dc->user_creatable = false; + device_class_set_parent_realize(dc, pnv_core_realize, + &pcc->parent_realize); } #define DEFINE_PNV_CORE_TYPE(family, cpu_model) \ diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index 7c2ea1424747..5533a386f350 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -331,6 +331,7 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp) (SpaprMachineState *) object_dynamic_cast(qdev_get_machine(), TYPE_SPAPR_MACHINE); SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev)); + SpaprCpuCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(sc); CPUCore *cc = CPU_CORE(OBJECT(dev)); int i; @@ -339,6 +340,8 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp) return; } + scc->parent_realize(dev, errp); + qemu_register_reset(spapr_cpu_core_reset_handler, sc); sc->threads = g_new0(PowerPCCPU *, cc->nr_threads); for (i = 0; i < cc->nr_threads; i++) { @@ -363,11 +366,12 @@ static void spapr_cpu_core_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); SpaprCpuCoreClass *scc = SPAPR_CPU_CORE_CLASS(oc); - dc->realize = spapr_cpu_core_realize; dc->unrealize = spapr_cpu_core_unrealize; dc->reset = spapr_cpu_core_reset; device_class_set_props(dc, spapr_cpu_core_properties); scc->cpu_type = data; + device_class_set_parent_realize(dc, spapr_cpu_core_realize, + &scc->parent_realize); } #define DEFINE_SPAPR_CPU_CORE_TYPE(cpu_model) \ diff --git a/include/hw/cpu/core.h b/include/hw/cpu/core.h index 17f117bd5225..87d50151ab01 100644 --- a/include/hw/cpu/core.h +++ b/include/hw/cpu/core.h @@ -21,7 +21,16 @@ struct CPUCore { DeviceState parent_obj; /*< public >*/ + int core_id; + + /* Maximum number of threads contained in this core. */ int nr_threads; + + /* + * How many threads should be plugged in this core via + * "-device"/"device_add"? + */ + int plugged_threads; }; #endif diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index 56c3f6b51f2f..3b9edf69f9fb 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -49,6 +49,8 @@ struct PnvCoreClass { /*< public >*/ const MemoryRegionOps *xscom_ops; uint64_t xscom_size; + + DeviceRealize parent_realize; }; #define PNV_CORE_TYPE_SUFFIX "-" TYPE_PNV_CORE diff --git a/include/hw/ppc/spapr_cpu_core.h b/include/hw/ppc/spapr_cpu_core.h index db3e515051ca..dabdbd4bcbc9 100644 --- a/include/hw/ppc/spapr_cpu_core.h +++ b/include/hw/ppc/spapr_cpu_core.h @@ -37,6 +37,8 @@ struct SpaprCpuCoreClass { /*< public >*/ const char *cpu_type; + + DeviceRealize parent_realize; }; const char *spapr_get_cpu_core_type(const char *cpu_type); -- 2.34.1