Looks like this patch broke migration from 2.10 to 2.9 (and older) when ais is active.
2.9 says error while loading state for instance 0x0 of device 's390-flic' So we need to fence this for older machines types than 2.10. This should also go in 2.10.1. Will have a look. On 07/14/2017 12:41 PM, Christian Borntraeger wrote: > From: Yi Min Zhao <zyi...@linux.vnet.ibm.com> > > During migration we should transfer ais states to the target guest. > This patch introduces a subsection to kvm_s390_flic_vmstate and new > vmsd for qemu_flic. The ais states need to be migrated only when > ais is supported. > > Signed-off-by: Yi Min Zhao <zyi...@linux.vnet.ibm.com> > Signed-off-by: Christian Borntraeger <borntrae...@de.ibm.com> > Reviewed-by: Cornelia Huck <coh...@redhat.com> > --- > hw/intc/s390_flic.c | 20 +++++++++++ > hw/intc/s390_flic_kvm.c | 81 > ++++++++++++++++++++++++++++++++++++++++++++ > include/hw/s390x/s390_flic.h | 1 + > 3 files changed, 102 insertions(+) > > diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c > index 6e7c610..6eaf178 100644 > --- a/hw/intc/s390_flic.c > +++ b/hw/intc/s390_flic.c > @@ -134,12 +134,32 @@ static void qemu_s390_flic_reset(DeviceState *dev) > flic->nimm = 0; > } > > +bool ais_needed(void *opaque) > +{ > + S390FLICState *s = opaque; > + > + return s->ais_supported; > +} > + > +static const VMStateDescription qemu_s390_flic_vmstate = { > + .name = "qemu-s390-flic", > + .version_id = 1, > + .minimum_version_id = 1, > + .needed = ais_needed, > + .fields = (VMStateField[]) { > + VMSTATE_UINT8(simm, QEMUS390FLICState), > + VMSTATE_UINT8(nimm, QEMUS390FLICState), > + VMSTATE_END_OF_LIST() > + } > +}; > + > static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) > { > DeviceClass *dc = DEVICE_CLASS(oc); > S390FLICStateClass *fsc = S390_FLIC_COMMON_CLASS(oc); > > dc->reset = qemu_s390_flic_reset; > + dc->vmsd = &qemu_s390_flic_vmstate; > fsc->register_io_adapter = qemu_s390_register_io_adapter; > fsc->io_adapter_map = qemu_s390_io_adapter_map; > fsc->add_adapter_routes = qemu_s390_add_adapter_routes; > diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c > index d93503f..be3fd00 100644 > --- a/hw/intc/s390_flic_kvm.c > +++ b/hw/intc/s390_flic_kvm.c > @@ -413,7 +413,84 @@ out: > return r; > } > > +typedef struct KVMS390FLICStateMigTmp { > + KVMS390FLICState *parent; > + uint8_t simm; > + uint8_t nimm; > +} KVMS390FLICStateMigTmp; > + > +static void kvm_flic_ais_pre_save(void *opaque) > +{ > + KVMS390FLICStateMigTmp *tmp = opaque; > + KVMS390FLICState *flic = tmp->parent; > + struct kvm_s390_ais_all ais; > + struct kvm_device_attr attr = { > + .group = KVM_DEV_FLIC_AISM_ALL, > + .addr = (uint64_t)&ais, > + .attr = sizeof(ais), > + }; > + > + if (ioctl(flic->fd, KVM_GET_DEVICE_ATTR, &attr)) { > + error_report("Failed to retrieve kvm flic ais states"); > + return; > + } > + > + tmp->simm = ais.simm; > + tmp->nimm = ais.nimm; > +} > + > +static int kvm_flic_ais_post_load(void *opaque, int version_id) > +{ > + KVMS390FLICStateMigTmp *tmp = opaque; > + KVMS390FLICState *flic = tmp->parent; > + struct kvm_s390_ais_all ais = { > + .simm = tmp->simm, > + .nimm = tmp->nimm, > + }; > + struct kvm_device_attr attr = { > + .group = KVM_DEV_FLIC_AISM_ALL, > + .addr = (uint64_t)&ais, > + }; > + > + /* This can happen when the user mis-configures its guests in an > + * incompatible fashion or without a CPU model. For example using > + * qemu with -cpu host (which is not migration safe) and do a > + * migration from a host that has AIS to a host that has no AIS. > + * In that case the target system will reject the migration here. > + */ > + if (!ais_needed(flic)) { > + return -ENOSYS; > + } > + > + return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0; > +} > + > +static const VMStateDescription kvm_s390_flic_ais_tmp = { > + .name = "s390-flic-ais-tmp", > + .pre_save = kvm_flic_ais_pre_save, > + .post_load = kvm_flic_ais_post_load, > + .fields = (VMStateField[]) { > + VMSTATE_UINT8(simm, KVMS390FLICStateMigTmp), > + VMSTATE_UINT8(nimm, KVMS390FLICStateMigTmp), > + VMSTATE_END_OF_LIST() > + } > +}; > + > +static const VMStateDescription kvm_s390_flic_vmstate_ais = { > + .name = "s390-flic/ais", > + .version_id = 1, > + .minimum_version_id = 1, > + .needed = ais_needed, > + .fields = (VMStateField[]) { > + VMSTATE_WITH_TMP(KVMS390FLICState, KVMS390FLICStateMigTmp, > + kvm_s390_flic_ais_tmp), > + VMSTATE_END_OF_LIST() > + } > +}; > + > static const VMStateDescription kvm_s390_flic_vmstate = { > + /* should have been like kvm-s390-flic, > + * can't change without breaking compat */ > .name = "s390-flic", > .version_id = FLIC_SAVEVM_VERSION, > .minimum_version_id = FLIC_SAVEVM_VERSION, > @@ -428,6 +505,10 @@ static const VMStateDescription kvm_s390_flic_vmstate = { > .flags = VMS_SINGLE, > }, > VMSTATE_END_OF_LIST() > + }, > + .subsections = (const VMStateDescription * []) { > + &kvm_s390_flic_vmstate_ais, > + NULL > } > }; > > diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h > index 2f173d9..7aab6ef 100644 > --- a/include/hw/s390x/s390_flic.h > +++ b/include/hw/s390x/s390_flic.h > @@ -89,6 +89,7 @@ typedef struct QEMUS390FLICState { > void s390_flic_init(void); > > S390FLICState *s390_get_flic(void); > +bool ais_needed(void *opaque); > > #ifdef CONFIG_KVM > DeviceState *s390_flic_kvm_create(void); >