Hi Igor, On 09/09/2014 08:17 PM, Igor Mammedov wrote: > On Thu, 28 Aug 2014 11:36:34 +0800 > Gu Zheng <guz.f...@cn.fujitsu.com> wrote: > >> Move 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. >> Besides, also use cc->get_arch_id as the cpu index of HMP/QMP command output >> to >> fix the index duplicated issue when hotadd a hot-removed cpu. >> >> v2: >> -fix the cpu index duplicated issue in the QMP/HMP command output. >> >> Signed-off-by: Gu Zheng <guz.f...@cn.fujitsu.com> > Please split CPU vmstate/APIC vmstate/QMP-monitor changes into separate > patches.
Got it, it does need to be restructured. > >> --- >> cpus.c | 4 +++- >> exec.c | 32 +++++++++++++++++++------------- >> hw/intc/apic_common.c | 3 +-- >> include/hw/i386/apic_internal.h | 2 ++ >> include/qom/cpu.h | 2 ++ >> monitor.c | 4 +++- >> qom/cpu.c | 2 ++ >> target-i386/cpu.c | 10 ++++++++-- >> 8 files changed, 40 insertions(+), 19 deletions(-) >> >> diff --git a/cpus.c b/cpus.c >> index 2b5c0bd..cce2744 100644 >> --- a/cpus.c >> +++ b/cpus.c >> @@ -1394,6 +1394,7 @@ CpuInfoList *qmp_query_cpus(Error **errp) >> { >> CpuInfoList *head = NULL, *cur_item = NULL; >> CPUState *cpu; >> + CPUClass *cc; >> >> CPU_FOREACH(cpu) { >> CpuInfoList *info; >> @@ -1411,11 +1412,12 @@ CpuInfoList *qmp_query_cpus(Error **errp) >> CPUMIPSState *env = &mips_cpu->env; >> #endif >> >> + cc = CPU_GET_CLASS(cpu); >> cpu_synchronize_state(cpu); >> >> info = g_malloc0(sizeof(*info)); >> info->value = g_malloc0(sizeof(*info->value)); >> - info->value->CPU = cpu->cpu_index; >> + info->value->CPU = cc->get_arch_id(cpu); >> info->value->current = (cpu == first_cpu); >> info->value->halted = cpu->halted; >> info->value->thread_id = cpu->thread_id; >> diff --git a/exec.c b/exec.c >> index 5f9857c..c514492 100644 >> --- a/exec.c >> +++ b/exec.c >> @@ -473,10 +473,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; >> >> @@ -499,18 +517,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) >> diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c >> index ce3d903..029f67d 100644 >> --- a/hw/intc/apic_common.c >> +++ b/hw/intc/apic_common.c >> @@ -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; >> diff --git a/include/hw/i386/apic_internal.h >> b/include/hw/i386/apic_internal.h >> index 83e2a42..2c91609 100644 >> --- a/include/hw/i386/apic_internal.h >> +++ b/include/hw/i386/apic_internal.h >> @@ -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,6 +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); >> diff --git a/include/qom/cpu.h b/include/qom/cpu.h >> index 1aafbf5..bc32c9a 100644 >> --- a/include/qom/cpu.h >> +++ b/include/qom/cpu.h >> @@ -549,6 +549,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, >> diff --git a/monitor.c b/monitor.c >> index 34cee74..55fd06c 100644 >> --- a/monitor.c >> +++ b/monitor.c >> @@ -1032,7 +1032,9 @@ static CPUArchState *mon_get_cpu(void) >> int monitor_get_cpu_index(void) >> { >> CPUState *cpu = ENV_GET_CPU(mon_get_cpu()); >> - return cpu->cpu_index; >> + CPUClass *cc = CPU_GET_CLASS(cpu); >> + >> + return cc->get_arch_id(cpu); >> } >> >> static void do_info_registers(Monitor *mon, const QDict *qdict) >> diff --git a/qom/cpu.c b/qom/cpu.c >> index b32dd0a..bf16590 100644 >> --- a/qom/cpu.c >> +++ b/qom/cpu.c >> @@ -301,6 +301,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); >> diff --git a/target-i386/cpu.c b/target-i386/cpu.c >> index 217500c..2aa2b31 100644 >> --- a/target-i386/cpu.c >> +++ b/target-i386/cpu.c >> @@ -2662,11 +2662,17 @@ 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); > Why have you dropped generic dc->vmsd = &vmstate_apic_common from above > and opencoded it here? Because if dc->vmsd was set, it will be registered with a sequence instance id in device_set_realized, which will break the instance rule (cc->get_arch_id), so we hacked it here. Any better solution is welcome. Thanks, Gu > > >> + >> + if (qdev_init(apic_state)) { >> error_setg(errp, "APIC device '%s' could not be initialized", >> object_get_typename(OBJECT(cpu->apic_state))); >> return; > > . >