On 03/24/2014 04:28 PM, Alexey Kardashevskiy wrote: > Currently only migration fails if CPU version is different even a bit. > For example, migration from POWER7 v2.0 to POWER7 v2.1 fails because of > that. Since there is no difference between CPU versions which could > affect migration stream, we can safely enable it. > > This adds a helper to find the closest POWERPC family class (i.e. first > abstract class in hierarchy). > > This replaces VMSTATE_UINTTL_EQUAL statement with a custom handler which > checks if the source and destination CPUs belong to the same family and > fails if they are not. > > This adds a PVR reset to the default value as it will be overwritten > by VMSTATE_UINTTL_ARRAY(env.spr, PowerPCCPU, 1024). > > Since the actual migration format is not changed by this patch, > @version_id of vmstate_ppc_cpu does not have to be changed either. > > Signed-off-by: Bharata B Rao <bhar...@linux.vnet.ibm.com> > Signed-off-by: Alexey Kardashevskiy <a...@ozlabs.ru>
Ping? > --- > target-ppc/cpu-qom.h | 1 + > target-ppc/machine.c | 40 ++++++++++++++++++++++++++++++++++++++-- > target-ppc/translate_init.c | 12 ++++++++++++ > 3 files changed, 51 insertions(+), 2 deletions(-) > > diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h > index 47dc8e6..5eb56ea 100644 > --- a/target-ppc/cpu-qom.h > +++ b/target-ppc/cpu-qom.h > @@ -105,6 +105,7 @@ static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState > *env) > > PowerPCCPUClass *ppc_cpu_class_by_pvr(uint32_t pvr); > PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t pvr); > +PowerPCCPUClass *ppc_cpu_family_class_by_pvr_mask(uint32_t pvr); > > void ppc_cpu_do_interrupt(CPUState *cpu); > void ppc_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf, > diff --git a/target-ppc/machine.c b/target-ppc/machine.c > index 063b379..834297e 100644 > --- a/target-ppc/machine.c > +++ b/target-ppc/machine.c > @@ -160,6 +160,11 @@ static int cpu_post_load(void *opaque, int version_id) > CPUPPCState *env = &cpu->env; > int i; > > + /* > + * Allow migration between hosts of same processor family > + * by restoring the default PVR for this VM on this host. > + */ > + env->spr[SPR_PVR] = env->spr_cb[SPR_PVR].default_value; > env->lr = env->spr[SPR_LR]; > env->ctr = env->spr[SPR_CTR]; > env->xer = env->spr[SPR_XER]; > @@ -462,6 +467,37 @@ static const VMStateDescription vmstate_tlbmas = { > } > }; > > +static int get_pvr(QEMUFile *f, void *pv, size_t size) > +{ > + target_ulong pvrdest = *(target_ulong *)pv; > +#if TARGET_LONG_BITS == 64 > + target_ulong pvrsrc = qemu_get_be64(f); > +#else > + target_ulong pvrsrc = qemu_get_be32(f); > +#endif > + PowerPCCPUClass *pccdest = ppc_cpu_family_class_by_pvr_mask(pvrdest); > + PowerPCCPUClass *pccsrc = ppc_cpu_family_class_by_pvr_mask(pvrsrc); > + > + return (pccdest == pccsrc) ? 0 : -1; > +} > + > +static void put_pvr(QEMUFile *f, void *pv, size_t size) > +{ > + target_ulong pvr = *(target_ulong *)pv; > + > +#if TARGET_LONG_BITS == 64 > + qemu_put_be64(f, pvr); > +#else > + qemu_put_be32(f, pvr); > +#endif > +} > + > +static const VMStateInfo vmstate_pvr = { > + .name = "PVR", > + .get = get_pvr, > + .put = put_pvr, > +}; > + > const VMStateDescription vmstate_ppc_cpu = { > .name = "cpu", > .version_id = 5, > @@ -471,8 +507,8 @@ const VMStateDescription vmstate_ppc_cpu = { > .pre_save = cpu_pre_save, > .post_load = cpu_post_load, > .fields = (VMStateField []) { > - /* Verify we haven't changed the pvr */ > - VMSTATE_UINTTL_EQUAL(env.spr[SPR_PVR], PowerPCCPU), > + VMSTATE_SINGLE(env.spr[SPR_PVR], PowerPCCPU, 0, vmstate_pvr, > + target_ulong), > > /* User mode architected state */ > VMSTATE_UINTTL_ARRAY(env.gpr, PowerPCCPU, 32), > diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c > index cdb2d2a..0c5c6a8 100644 > --- a/target-ppc/translate_init.c > +++ b/target-ppc/translate_init.c > @@ -8146,6 +8146,18 @@ PowerPCCPUClass *ppc_cpu_class_by_pvr_mask(uint32_t > pvr) > return pcc; > } > > +PowerPCCPUClass *ppc_cpu_family_class_by_pvr_mask(uint32_t pvr) > +{ > + PowerPCCPUClass *pcc = ppc_cpu_class_by_pvr_mask(pvr); > + ObjectClass *oc = OBJECT_CLASS(pcc); > + > + while (oc && !object_class_is_abstract(oc)) { > + oc = object_class_get_parent(oc); > + } > + > + return POWERPC_CPU_CLASS(oc); > +} > + > static gint ppc_cpu_compare_class_name(gconstpointer a, gconstpointer b) > { > ObjectClass *oc = (ObjectClass *)a; > -- Alexey