From: Zhao Liu <zhao1.liu@intel.com>
Convert CPU to topology device then its parent topology devices could
count the number of CPUs when new CPUs are added into topology tree.
Note since CPUs are created from *_init_cpus() in MachineClass.init() or
added from hotplug way, it depends on board initialization. Thus CPU
topology device isn't marked as DEVICE_CATEGORY_CPU_DEF and it will only
be created after board initialization.
Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
---
accel/kvm/kvm-all.c | 4 ++--
hw/core/cpu-common.c | 25 +++++++++++++++++++++----
include/hw/core/cpu.h | 8 ++++++--
3 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index e39a810a4e92..2eee3eb95907 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -3953,7 +3953,7 @@ static void query_stats(StatsResultList **result, StatsTarget target,
break;
case STATS_TARGET_VCPU:
add_stats_entry(result, STATS_PROVIDER_KVM,
- cpu->parent_obj.canonical_path,
+ DEVICE(cpu)->canonical_path,
stats_list);
break;
default:
@@ -4045,7 +4045,7 @@ static void query_stats_cb(StatsResultList **result, StatsTarget target,
stats_args.names = names;
stats_args.errp = errp;
CPU_FOREACH(cpu) {
- if (!apply_str_list_filter(cpu->parent_obj.canonical_path, targets)) {
+ if (!apply_str_list_filter(DEVICE(cpu)->canonical_path, targets)) {
continue;
}
query_stats_vcpu(cpu, &stats_args);
diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
index 82dae51a550b..e9ed84ff5386 100644
--- a/hw/core/cpu-common.c
+++ b/hw/core/cpu-common.c
@@ -195,6 +195,16 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp)
{
CPUState *cpu = CPU(dev);
Object *machine = qdev_get_machine();
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ /*
+ * The parent topology realize() must be completed before cpu_resume()
+ * where the CPU starts to run.
+ */
+ cc->parent_realize(dev, errp);
+ if (*errp) {
+ return;
+ }
/* qdev_get_machine() can return something that's not TYPE_MACHINE
* if this is one of the user-only emulators; in that case there's
@@ -225,6 +235,7 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp)
static void cpu_common_unrealizefn(DeviceState *dev)
{
CPUState *cpu = CPU(dev);
+ CPUClass *cc = CPU_GET_CLASS(cpu);
/* Call the plugin hook before clearing the cpu is fully unrealized */
if (tcg_enabled()) {
@@ -233,6 +244,7 @@ static void cpu_common_unrealizefn(DeviceState *dev)
/* NOTE: latest generic point before the cpu is fully unrealized */
cpu_exec_unrealizefn(cpu);
+ cc->parent_unrealize(dev);
}
static void cpu_common_initfn(Object *obj)
@@ -275,6 +287,7 @@ static void cpu_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
ResettableClass *rc = RESETTABLE_CLASS(klass);
+ CPUTopoClass *tc = CPU_TOPO_CLASS(klass);
CPUClass *k = CPU_CLASS(klass);
k->parse_features = cpu_common_parse_features;
@@ -282,9 +295,6 @@ static void cpu_class_init(ObjectClass *klass, void *data)
k->has_work = cpu_common_has_work;
k->gdb_read_register = cpu_common_gdb_read_register;
k->gdb_write_register = cpu_common_gdb_write_register;
- set_bit(DEVICE_CATEGORY_CPU, dc->categories);
- dc->realize = cpu_common_realizefn;
- dc->unrealize = cpu_common_unrealizefn;
rc->phases.hold = cpu_common_reset_hold;
cpu_class_init_props(dc);
/*
@@ -292,11 +302,18 @@ static void cpu_class_init(ObjectClass *klass, void *data)
* IRQs, adding reset handlers, halting non-first CPUs, ...
*/
dc->user_creatable = false;
+ /* CPU is the minimum granularity for hotplug. */
+ dc->hotpluggable = true;
+ device_class_set_parent_realize(dc, cpu_common_realizefn,
+ &k->parent_realize);
+ device_class_set_parent_unrealize(dc, cpu_common_unrealizefn,
+ &k->parent_unrealize);
+ tc->level = CPU_TOPO_THREAD;
}
static const TypeInfo cpu_type_info = {
.name = TYPE_CPU,
- .parent = TYPE_DEVICE,
+ .parent = TYPE_CPU_TOPO,
.instance_size = sizeof(CPUState),
.instance_init = cpu_common_initfn,
.instance_finalize = cpu_common_finalize,
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index c0c8320413e5..a700f7c39140 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -20,6 +20,7 @@
#ifndef QEMU_CPU_H
#define QEMU_CPU_H
+#include "hw/core/cpu-topo.h"
#include "hw/qdev-core.h"
#include "disas/dis-asm.h"
#include "exec/cpu-common.h"
@@ -146,7 +147,7 @@ struct SysemuCPUOps;
*/
struct CPUClass {
/*< private >*/
- DeviceClass parent_class;
+ CPUTopoClass parent_class;
/*< public >*/
ObjectClass *(*class_by_name)(const char *cpu_model);
@@ -191,6 +192,9 @@ struct CPUClass {
int reset_dump_flags;
int gdb_num_core_regs;
bool gdb_stop_before_watchpoint;
+
+ DeviceRealize parent_realize;
+ DeviceUnrealize parent_unrealize;
};
/*
@@ -456,7 +460,7 @@ struct qemu_work_item;
*/
struct CPUState {
/*< private >*/
- DeviceState parent_obj;
+ CPUTopoState parent_obj;
/* cache to avoid expensive CPU_GET_CLASS */
CPUClass *cc;
/*< public >*/
--
2.34.1