cpu: add device_add foo-x86_64-cpu support
cover cpu: add device_add foo-x86_64-cpu support
This series is based on the previous patchset from Chen Fan:
https://lists.nongnu.org/archive/html/qemu-devel/2014-05/msg02360.html
This patches try to make cpu hotplug with device_add, and make "-device foo-x86_64-cpu" available,also we can set apic-id property with command line, if without setting apic-id property, we offer the first unoccupied apic id as the default new apic id. When hotplug cpu with device_add, additional check of APIC ID will be done after cpu object initialization which was different from 'cpu_add' command that check 'ids' at the beginning.
Chen Fan (2):
cpu: introduce CpuTopoInfo structure for argument simplification
cpu: add device_add foo-x86_64-cpu support
Gu Zheng (1):
qom/cpu: move register_vmstate to common CPUClass.realizefn
exec.c | 32 ++++++++++------- hw/intc/apic_common.c | 3 +- include/hw/i386/apic_internal.h | 3 +- include/qom/cpu.h | 3 ++ qdev-monitor.c | 1 + qom/cpu.c | 2 + target-i386/cpu.c | 76 ++++++++++++++++++++++++++++++++++++-- target-i386/topology.h | 51 ++++++++++++++++++-------- 8 files changed, 135 insertions(+), 36 deletions(-)
Signature · 1 line
1.7.7
RFC PATCH 1/3 cpu: introduce CpuTopoInfo structure for argument simplification
--- target-i386/topology.h | 33 +++++++++++++++++---------------- 1 files changed, 17 insertions(+), 16 deletions(-)
target-i386/topology.h +17 -16
@@ -47,6 +47,12 @@*/ typedef uint32_t apic_id_t ; +typedef struct X86CPUTopoInfo { +unsigned pkg_id; +unsigned core_id; +unsigned smt_id; +}X86CPUTopoInfo ; +/* Return the bit width needed for 'count' IDs */ static unsigned apicid_bitwidth_for_count (unsigned count)
@@ -92,13 +98,11 @@ static inline unsigned apicid_pkg_offset(unsigned nr_cores, unsigned nr_threads)*/ static inline apic_id_t apicid_from_topo_ids (unsigned nr_cores,unsigned nr_threads, -unsigned pkg_id, -unsigned core_id, -unsigned smt_id) +const X86CPUTopoInfo *topo) { -return (pkg_id <<apicid_pkg_offset (nr_cores, nr_threads)) | - (core_id <<apicid_core_offset (nr_cores, nr_threads)) | - smt_id; +return (topo->pkg_id <<apicid_pkg_offset (nr_cores, nr_threads)) | + (topo->core_id <<apicid_core_offset (nr_cores, nr_threads)) | + topo->smt_id; }/* Calculate thread/core/package IDs for a specific topology,
@@ -107,14 +111,12 @@ static inline apic_id_t apicid_from_topo_ids(unsigned nr_cores,static inline void x86_topo_ids_from_idx (unsigned nr_cores,unsigned nr_threads,unsigned cpu_index, -unsigned *pkg_id, -unsigned *core_id, -unsigned *smt_id) +X86CPUTopoInfo *topo) {unsigned core_index = cpu_index / nr_threads; - *smt_id = cpu_index % nr_threads; - *core_id = core_index % nr_cores; - *pkg_id = core_index / nr_cores; + topo->smt_id = cpu_index % nr_threads; + topo->core_id = core_index % nr_cores; + topo->pkg_id = core_index / nr_cores; }/* Make APIC ID for the CPU 'cpu_index'
@@ -125,10 +127,9 @@ static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores, unsigned nr_threads, unsigned cpu_index) { - unsigned pkg_id, core_id, smt_id; -x86_topo_ids_from_idx (nr_cores, nr_threads, cpu_index, - &pkg_id, &core_id, &smt_id); -return apicid_from_topo_ids (nr_cores, nr_threads, pkg_id, core_id, smt_id); +X86CPUTopoInfo topo; +x86_topo_ids_from_idx (nr_cores, nr_threads, cpu_index, &topo); +return apicid_from_topo_ids (nr_cores, nr_threads, &topo); }#endif /* TARGET_I386_TOPOLOGY_H */
Signature · 1 line
1.7.7
RFC PATCH 2/3 qom/cpu: move register_vmstate to common CPUClass.realizefn
In reply to Gu ZhengMove cpu vmstate register from cpu_exec_init into cpu_common_realizefn, apic vmstate register into x86_cpu_apic_realize. And use the cc->get_arch_id as the instance id that suggested by Igor to fix the migration issue.
--- exec.c | 32 +++++++++++++++++++------------- hw/intc/apic_common.c | 3 +-- include/hw/i386/apic_internal.h | 3 ++- include/qom/cpu.h | 2 ++ qom/cpu.c | 2 ++ target-i386/cpu.c | 12 +++++++++--- 6 files changed, 35 insertions(+), 19 deletions(-)
exec.c +19 -13
@@ -468,10 +468,28 @@ void tcg_cpu_address_space_init(CPUState *cpu, AddressSpace *as) }#endif +void cpu_vmstate_register (CPUState *cpu) +{ +CPUClass *cc =CPU_GET_CLASS (cpu); +int cpu_index = cc->get_arch_id (cpu); + +if (qdev_get_vmsd (DEVICE (cpu)) ==NULL ) { +vmstate_register (NULL , cpu_index, &vmstate_cpu_common, cpu); + } +#if defined(CPU_SAVE_VERSION ) && !defined(CONFIG_USER_ONLY ) +register_savevm (NULL ,"cpu" , cpu_index,CPU_SAVE_VERSION , + cpu_save, cpu_load, cpu->env_ptr); +assert (cc->vmsd ==NULL ); +assert (qdev_get_vmsd (DEVICE (cpu)) ==NULL ); +#endif +if (cc->vmsd !=NULL ) { +vmstate_register (NULL , cpu_index, cc->vmsd, cpu); + } +} +void cpu_exec_init (CPUArchState *env) {CPUState *cpu =ENV_GET_CPU (env); -CPUClass *cc =CPU_GET_CLASS (cpu);CPUState *some_cpu;int cpu_index;
@@ -494,18 +512,6 @@ void cpu_exec_init(CPUArchState *env)#if defined(CONFIG_USER_ONLY )cpu_list_unlock ();#endif -if (qdev_get_vmsd (DEVICE (cpu)) ==NULL ) { -vmstate_register (NULL , cpu_index, &vmstate_cpu_common, cpu); - } -#if defined(CPU_SAVE_VERSION ) && !defined(CONFIG_USER_ONLY ) -register_savevm (NULL ,"cpu" , cpu_index,CPU_SAVE_VERSION , - cpu_save, cpu_load, env); -assert (cc->vmsd ==NULL ); -assert (qdev_get_vmsd (DEVICE (cpu)) ==NULL ); -#endif -if (cc->vmsd !=NULL ) { -vmstate_register (NULL , cpu_index, cc->vmsd, cpu); - } }#if defined(TARGET_HAS_ICE )
hw/intc/apic_common.c +1 -2
@@ -345,7 +345,7 @@ static int apic_dispatch_post_load(void *opaque, int version_id)return 0 ; } -static const VMStateDescription vmstate_apic_common = { +const VMStateDescription vmstate_apic_common = { .name ="apic" , .version_id =3 , .minimum_version_id =3 ,
@@ -391,7 +391,6 @@ static void apic_common_class_init(ObjectClass *klass, void *data)ICCDeviceClass *idc =ICC_DEVICE_CLASS (klass);DeviceClass *dc =DEVICE_CLASS (klass); - dc->vmsd = &vmstate_apic_common; dc->reset = apic_reset_common; dc->props = apic_properties_common; idc->realize = apic_common_realize;
include/hw/i386/apic_internal.h +2 -1
@@ -23,6 +23,7 @@#include "exec/memory.h" #include "hw/cpu/icc_bus.h" #include "qemu/timer.h" +#include "migration/vmstate.h" /* APIC Local Vector Table */ #define APIC_LVT_TIMER 0
@@ -136,7 +137,7 @@ typedef struct VAPICState { }QEMU_PACKED VAPICState;extern bool apic_report_tpr_access; - +extern const VMStateDescription vmstate_apic_common;void apic_report_irq_delivered (int delivered);bool apic_next_timer (APICCommonState *s,int64_t current_time);void apic_enable_tpr_access_reporting (DeviceState *d,bool enable);
include/qom/cpu.h +2 -0
@@ -548,6 +548,8 @@ void cpu_interrupt(CPUState *cpu, int mask);#endif /* USER_ONLY */ +void cpu_vmstate_register (CPUState *cpu); +#ifdef CONFIG_SOFTMMU static inline void cpu_unassigned_access(CPUState *cpu, hwaddr addr, bool is_write, bool is_exec,
qom/cpu.c +2 -0
@@ -296,6 +296,8 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp) {CPUState *cpu =CPU (dev); +cpu_vmstate_register (cpu); +if (dev->hotplugged) {cpu_synchronize_post_init (cpu);notifier_list_notify (&cpu_added_notifiers, dev);
target-i386/cpu.c +9 -3
@@ -2554,13 +2554,19 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)static void x86_cpu_apic_realize (X86CPU *cpu,Error **errp) { -if (cpu->apic_state ==NULL ) { +DeviceState *apic_state = cpu->apic_state; +CPUClass *cc =CPU_GET_CLASS (CPU (cpu)); + +if (apic_state ==NULL ) {return ; } -if (qdev_init (cpu->apic_state)) { +vmstate_register (0 , cc->get_arch_id (CPU (cpu)), + &vmstate_apic_common, apic_state); + +if (qdev_init (apic_state)) {error_setg (errp,"APIC device '%s' could not be initialized" , -object_get_typename (OBJECT (cpu->apic_state))); +object_get_typename (OBJECT (cpu->apic_state)));return ; } }
Signature · 1 line
1.7.7
RFC PATCH 3/3 cpu: add device_add foo-x86_64-cpu support
In reply to Gu ZhengFrom: Chen Fan <[email protected]>
Add support to device_add foo-x86_64-cpu, and additional checks of apic id are added into x86_cpuid_set_apic_id() and x86_cpu_apic_create() for duplicate. Besides, in order to support "device/device_add foo-x86_64-cpu" which without specified apic id, we add a new function get_free_apic_id() to provide the first free apid id each time to avoid apic id duplicate.
--- include/qom/cpu.h | 1 + qdev-monitor.c | 1 + target-i386/cpu.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++- target-i386/topology.h | 18 +++++++++++++ 4 files changed, 83 insertions(+), 1 deletions(-)
include/qom/cpu.h +1 -0
@@ -291,6 +291,7 @@ struct CPUState {QTAILQ_HEAD (CPUTailQ, CPUState);extern struct CPUTailQ cpus;#define CPU_NEXT (cpu) QTAILQ_NEXT(cpu, node) +#define CPU_REMOVE (cpu) QTAILQ_REMOVE(&cpus, cpu, node)#define CPU_FOREACH (cpu) QTAILQ_FOREACH(cpu, &cpus, node)#define CPU_FOREACH_SAFE (cpu, next_cpu) \ QTAILQ_FOREACH_SAFE(cpu, &cpus, node, next_cpu)
qdev-monitor.c +1 -0
@@ -24,6 +24,7 @@#include "qmp-commands.h" #include "sysemu/arch_init.h" #include "qemu/config-file.h" +#include "qom/object_interfaces.h" /* * Aliases were a bad idea from the start. Let's keep them
target-i386/cpu.c +63 -1
143 lines not on this page · raw message
target-i386/topology.h +18 -0
@@ -132,4 +132,22 @@ static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores, return apicid_from_topo_ids(nr_cores, nr_threads, &topo); } +/* Calculate CPU topology based on CPU APIC ID. +*/ +static inline void x86_topo_ids_from_apic_id (unsigned nr_cores, +unsigned nr_threads, +apic_id_t apic_id, +X86CPUTopoInfo *topo) +{ +unsigned offset_mask; + topo->pkg_id = apic_id >>apicid_pkg_offset (nr_cores, nr_threads); + + offset_mask = (1L <<apicid_pkg_offset (nr_cores, nr_threads)) -1 ; + topo->core_id = (apic_id & offset_mask) + >>apicid_core_offset (nr_cores, nr_threads); + + offset_mask = (1L <<apicid_core_offset (nr_cores, nr_threads)) -1 ; + topo->smt_id = apic_id & offset_mask; +} +#endif /* TARGET_I386_TOPOLOGY_H */
Signature · 1 line
1.7.7
Re: [Qemu-devel] [RFC PATCH 1/3] cpu: introduce CpuTopoInfo structure for argument simplification
In reply to Gu ZhengCorrect the author.
From: Chen Fan <[email protected]>
Quoted 75 lines · Gu Zheng
Signed-off-by Chen Fan <[email protected]>Reviewed-by Eduardo Habkost <[email protected]>Signed-off-by Gu Zheng <[email protected]>--- target-i386/topology.h | 33 +++++++++++++++++---------------- 1 files changed, 17 insertions(+), 16 deletions(-)target-i386/topology.h +17
-16@@ -47,6 +47,12 @@*/ typedef uint32_t apic_id_t ; +typedef struct X86CPUTopoInfo { +unsigned pkg_id; +unsigned core_id; +unsigned smt_id; +}X86CPUTopoInfo ; +/* Return the bit width needed for 'count' IDs */ static unsigned apicid_bitwidth_for_count (unsigned count)@@ -92,13 +98,11 @@ static inline unsigned apicid_pkg_offset(unsigned nr_cores, unsigned nr_threads)*/ static inline apic_id_t apicid_from_topo_ids (unsigned nr_cores,unsigned nr_threads, -unsigned pkg_id, -unsigned core_id, -unsigned smt_id) +const X86CPUTopoInfo *topo) { -return (pkg_id <<apicid_pkg_offset (nr_cores, nr_threads)) | - (core_id <<apicid_core_offset (nr_cores, nr_threads)) | - smt_id; +return (topo->pkg_id <<apicid_pkg_offset (nr_cores, nr_threads)) | + (topo->core_id <<apicid_core_offset (nr_cores, nr_threads)) | + topo->smt_id; }/* Calculate thread/core/package IDs for a specific topology, @@ -107,14 +111,12 @@ static inline apic_id_t apicid_from_topo_ids(unsigned nr_cores,static inline void x86_topo_ids_from_idx (unsigned nr_cores,unsigned nr_threads,unsigned cpu_index, -unsigned *pkg_id, -unsigned *core_id, -unsigned *smt_id) +X86CPUTopoInfo *topo) {unsigned core_index = cpu_index / nr_threads; - *smt_id = cpu_index % nr_threads; - *core_id = core_index % nr_cores; - *pkg_id = core_index / nr_cores; + topo->smt_id = cpu_index % nr_threads; + topo->core_id = core_index % nr_cores; + topo->pkg_id = core_index / nr_cores; }/* Make APIC ID for the CPU 'cpu_index' @@ -125,10 +127,9 @@ static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores, unsigned nr_threads, unsigned cpu_index) { - unsigned pkg_id, core_id, smt_id; -x86_topo_ids_from_idx (nr_cores, nr_threads, cpu_index, - &pkg_id, &core_id, &smt_id); -return apicid_from_topo_ids (nr_cores, nr_threads, pkg_id, core_id, smt_id); +X86CPUTopoInfo topo; +x86_topo_ids_from_idx (nr_cores, nr_threads, cpu_index, &topo); +return apicid_from_topo_ids (nr_cores, nr_threads, &topo); }#endif /* TARGET_I386_TOPOLOGY_H */