Message ID | 1475519097-27611-4-git-send-email-duanj@linux.vnet.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
* Jianjun Duan (duanj@linux.vnet.ibm.com) wrote: > Current migration code cannot handle some data structures such as > QTAILQ in qemu/queue.h. Here we extend the signatures of put/get > in VMStateInfo so that customized handling is supported. > > Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com> > --- > hw/net/vmxnet3.c | 18 ++++++--- > hw/nvram/eeprom93xx.c | 6 ++- > hw/nvram/fw_cfg.c | 6 ++- > hw/pci/msix.c | 6 ++- > hw/pci/pci.c | 12 ++++-- > hw/pci/shpc.c | 5 ++- > hw/scsi/scsi-bus.c | 6 ++- > hw/timer/twl92230.c | 6 ++- > hw/usb/redirect.c | 18 ++++++--- > hw/virtio/virtio-pci.c | 6 ++- > hw/virtio/virtio.c | 6 ++- > include/migration/vmstate.h | 10 +++-- > migration/savevm.c | 5 ++- > migration/vmstate.c | 95 ++++++++++++++++++++++++++++----------------- > target-alpha/machine.c | 5 ++- > target-arm/machine.c | 12 ++++-- > target-i386/machine.c | 21 ++++++---- > target-mips/machine.c | 10 +++-- > target-ppc/machine.c | 10 +++-- > target-sparc/machine.c | 5 ++- > 20 files changed, 171 insertions(+), 97 deletions(-) > <snip> > diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c > index 444672a..2ca4b46 100644 > --- a/hw/usb/redirect.c > +++ b/hw/usb/redirect.c > @@ -2154,7 +2154,8 @@ static int usbredir_post_load(void *priv, int version_id) > } > > /* For usbredirparser migration */ > -static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused) > +static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused, > + void *opaque, QJSON *vmdesc) > { > USBRedirDevice *dev = priv; > uint8_t *data; > @@ -2174,7 +2175,8 @@ static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused) > free(data); > } > > -static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused) > +static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused, > + void *opaque) Neither of these built for me; I had to change those to VMStateField rather than void *; also is this series tested ontop of Halil's patches - because without them I'm finding I also had to fix up most of the other virtio devices. Dave > USBRedirDevice *dev = priv; > uint8_t *data; > @@ -2217,7 +2219,8 @@ static const VMStateInfo usbredir_parser_vmstate_info = { > > > /* For buffered packets (iso/irq) queue migration */ > -static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused) > +static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused, > + VMStateField *field, QJSON *vmdesc) > { > struct endp_data *endp = priv; > USBRedirDevice *dev = endp->dev; > @@ -2237,7 +2240,8 @@ static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused) > assert(i == endp->bufpq_size); > } > > -static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused) > +static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused, > + VMStateField *field) > { > struct endp_data *endp = priv; > USBRedirDevice *dev = endp->dev; > @@ -2340,7 +2344,8 @@ static const VMStateDescription usbredir_ep_vmstate = { > > > /* For PacketIdQueue migration */ > -static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused) > +static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused, > + VMStateField *field, QJSON *vmdesc) > { > struct PacketIdQueue *q = priv; > USBRedirDevice *dev = q->dev; > @@ -2356,7 +2361,8 @@ static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused) > assert(remain == 0); > } > > -static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused) > +static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused, > + VMStateField *field) > { > struct PacketIdQueue *q = priv; > USBRedirDevice *dev = q->dev; > diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c > index 2d60a00..38a7abd 100644 > --- a/hw/virtio/virtio-pci.c > +++ b/hw/virtio/virtio-pci.c > @@ -108,7 +108,8 @@ static bool virtio_pci_has_extra_state(DeviceState *d) > return proxy->flags & VIRTIO_PCI_FLAG_MIGRATE_EXTRA; > } > > -static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size) > +static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size, > + VMStateField *field) > { > VirtIOPCIProxy *proxy = pv; > int i; > @@ -137,7 +138,8 @@ static void virtio_pci_save_modern_queue_state(VirtIOPCIQueue *vq, > qemu_put_be32(f, vq->used[1]); > } > > -static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size) > +static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size, > + VMStateField *field, QJSON *vmdesc) > { > VirtIOPCIProxy *proxy = pv; > int i; > diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c > index 18ce333..ade2683 100644 > --- a/hw/virtio/virtio.c > +++ b/hw/virtio/virtio.c > @@ -1467,7 +1467,8 @@ static const VMStateDescription vmstate_virtio_ringsize = { > } > }; > > -static int get_extra_state(QEMUFile *f, void *pv, size_t size) > +static int get_extra_state(QEMUFile *f, void *pv, size_t size, > + VMStateField *field) > { > VirtIODevice *vdev = pv; > BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); > @@ -1480,7 +1481,8 @@ static int get_extra_state(QEMUFile *f, void *pv, size_t size) > } > } > > -static void put_extra_state(QEMUFile *f, void *pv, size_t size) > +static void put_extra_state(QEMUFile *f, void *pv, size_t size, > + VMStateField *field, QJSON *vmdesc) > { > VirtIODevice *vdev = pv; > BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); > diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h > index 1638ee5..459dd4a 100644 > --- a/include/migration/vmstate.h > +++ b/include/migration/vmstate.h > @@ -81,11 +81,13 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque); > > typedef struct VMStateInfo VMStateInfo; > typedef struct VMStateDescription VMStateDescription; > +typedef struct VMStateField VMStateField; > > struct VMStateInfo { > const char *name; > - int (*get)(QEMUFile *f, void *pv, size_t size); > - void (*put)(QEMUFile *f, void *pv, size_t size); > + int (*get)(QEMUFile *f, void *pv, size_t size, VMStateField *field); > + void (*put)(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc); > }; > > enum VMStateFlags { > @@ -186,7 +188,7 @@ enum VMStateFlags { > VMS_MULTIPLY_ELEMENTS = 0x4000, > }; > > -typedef struct { > +struct VMStateField { > const char *name; > size_t offset; > size_t size; > @@ -199,7 +201,7 @@ typedef struct { > const VMStateDescription *vmsd; > int version_id; > bool (*field_exists)(void *opaque, int version_id); > -} VMStateField; > +}; > > struct VMStateDescription { > const char *name; > diff --git a/migration/savevm.c b/migration/savevm.c > index ef5c3d1..13b53ad 100644 > --- a/migration/savevm.c > +++ b/migration/savevm.c > @@ -220,14 +220,15 @@ void timer_get(QEMUFile *f, QEMUTimer *ts) > * Not in vmstate.c to not add qemu-timer.c as dependency to vmstate.c > */ > > -static int get_timer(QEMUFile *f, void *pv, size_t size) > +static int get_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field) > { > QEMUTimer *v = pv; > timer_get(f, v); > return 0; > } > > -static void put_timer(QEMUFile *f, void *pv, size_t size) > +static void put_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > QEMUTimer *v = pv; > timer_put(f, v); > diff --git a/migration/vmstate.c b/migration/vmstate.c > index fc29acf..66802cb 100644 > --- a/migration/vmstate.c > +++ b/migration/vmstate.c > @@ -122,7 +122,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, > ret = vmstate_load_state(f, field->vmsd, addr, > field->vmsd->version_id); > } else { > - ret = field->info->get(f, addr, size); > + ret = field->info->get(f, addr, size, NULL); > > } > if (ret >= 0) { > @@ -328,7 +328,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, > if (field->flags & VMS_STRUCT) { > vmstate_save_state(f, field->vmsd, addr, vmdesc_loop); > } else { > - field->info->put(f, addr, size); > + field->info->put(f, addr, size, NULL, NULL); > } > > written_bytes = qemu_ftell_fast(f) - old_offset; > @@ -461,14 +461,15 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, > > /* bool */ > > -static int get_bool(QEMUFile *f, void *pv, size_t size) > +static int get_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field) > { > bool *v = pv; > *v = qemu_get_byte(f); > return 0; > } > > -static void put_bool(QEMUFile *f, void *pv, size_t size) > +static void put_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > bool *v = pv; > qemu_put_byte(f, *v); > @@ -482,14 +483,15 @@ const VMStateInfo vmstate_info_bool = { > > /* 8 bit int */ > > -static int get_int8(QEMUFile *f, void *pv, size_t size) > +static int get_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field) > { > int8_t *v = pv; > qemu_get_s8s(f, v); > return 0; > } > > -static void put_int8(QEMUFile *f, void *pv, size_t size) > +static void put_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > int8_t *v = pv; > qemu_put_s8s(f, v); > @@ -503,14 +505,15 @@ const VMStateInfo vmstate_info_int8 = { > > /* 16 bit int */ > > -static int get_int16(QEMUFile *f, void *pv, size_t size) > +static int get_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field) > { > int16_t *v = pv; > qemu_get_sbe16s(f, v); > return 0; > } > > -static void put_int16(QEMUFile *f, void *pv, size_t size) > +static void put_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > int16_t *v = pv; > qemu_put_sbe16s(f, v); > @@ -524,14 +527,15 @@ const VMStateInfo vmstate_info_int16 = { > > /* 32 bit int */ > > -static int get_int32(QEMUFile *f, void *pv, size_t size) > +static int get_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field) > { > int32_t *v = pv; > qemu_get_sbe32s(f, v); > return 0; > } > > -static void put_int32(QEMUFile *f, void *pv, size_t size) > +static void put_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > int32_t *v = pv; > qemu_put_sbe32s(f, v); > @@ -546,7 +550,8 @@ const VMStateInfo vmstate_info_int32 = { > /* 32 bit int. See that the received value is the same than the one > in the field */ > > -static int get_int32_equal(QEMUFile *f, void *pv, size_t size) > +static int get_int32_equal(QEMUFile *f, void *pv, size_t size, > + VMStateField *field) > { > int32_t *v = pv; > int32_t v2; > @@ -568,7 +573,7 @@ const VMStateInfo vmstate_info_int32_equal = { > * and less than or equal to the one in the field. > */ > > -static int get_int32_le(QEMUFile *f, void *pv, size_t size) > +static int get_int32_le(QEMUFile *f, void *pv, size_t size, VMStateField *field) > { > int32_t *cur = pv; > int32_t loaded; > @@ -589,14 +594,15 @@ const VMStateInfo vmstate_info_int32_le = { > > /* 64 bit int */ > > -static int get_int64(QEMUFile *f, void *pv, size_t size) > +static int get_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field) > { > int64_t *v = pv; > qemu_get_sbe64s(f, v); > return 0; > } > > -static void put_int64(QEMUFile *f, void *pv, size_t size) > +static void put_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > int64_t *v = pv; > qemu_put_sbe64s(f, v); > @@ -610,14 +616,15 @@ const VMStateInfo vmstate_info_int64 = { > > /* 8 bit unsigned int */ > > -static int get_uint8(QEMUFile *f, void *pv, size_t size) > +static int get_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field) > { > uint8_t *v = pv; > qemu_get_8s(f, v); > return 0; > } > > -static void put_uint8(QEMUFile *f, void *pv, size_t size) > +static void put_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > uint8_t *v = pv; > qemu_put_8s(f, v); > @@ -631,14 +638,15 @@ const VMStateInfo vmstate_info_uint8 = { > > /* 16 bit unsigned int */ > > -static int get_uint16(QEMUFile *f, void *pv, size_t size) > +static int get_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field) > { > uint16_t *v = pv; > qemu_get_be16s(f, v); > return 0; > } > > -static void put_uint16(QEMUFile *f, void *pv, size_t size) > +static void put_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > uint16_t *v = pv; > qemu_put_be16s(f, v); > @@ -652,14 +660,15 @@ const VMStateInfo vmstate_info_uint16 = { > > /* 32 bit unsigned int */ > > -static int get_uint32(QEMUFile *f, void *pv, size_t size) > +static int get_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field) > { > uint32_t *v = pv; > qemu_get_be32s(f, v); > return 0; > } > > -static void put_uint32(QEMUFile *f, void *pv, size_t size) > +static void put_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > uint32_t *v = pv; > qemu_put_be32s(f, v); > @@ -674,7 +683,8 @@ const VMStateInfo vmstate_info_uint32 = { > /* 32 bit uint. See that the received value is the same than the one > in the field */ > > -static int get_uint32_equal(QEMUFile *f, void *pv, size_t size) > +static int get_uint32_equal(QEMUFile *f, void *pv, size_t size, > + VMStateField *field) > { > uint32_t *v = pv; > uint32_t v2; > @@ -694,14 +704,15 @@ const VMStateInfo vmstate_info_uint32_equal = { > > /* 64 bit unsigned int */ > > -static int get_uint64(QEMUFile *f, void *pv, size_t size) > +static int get_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field) > { > uint64_t *v = pv; > qemu_get_be64s(f, v); > return 0; > } > > -static void put_uint64(QEMUFile *f, void *pv, size_t size) > +static void put_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > uint64_t *v = pv; > qemu_put_be64s(f, v); > @@ -716,7 +727,8 @@ const VMStateInfo vmstate_info_uint64 = { > /* 64 bit unsigned int. See that the received value is the same than the one > in the field */ > > -static int get_uint64_equal(QEMUFile *f, void *pv, size_t size) > +static int get_uint64_equal(QEMUFile *f, void *pv, size_t size, > + VMStateField *field) > { > uint64_t *v = pv; > uint64_t v2; > @@ -737,7 +749,8 @@ const VMStateInfo vmstate_info_uint64_equal = { > /* 8 bit int. See that the received value is the same than the one > in the field */ > > -static int get_uint8_equal(QEMUFile *f, void *pv, size_t size) > +static int get_uint8_equal(QEMUFile *f, void *pv, size_t size, > + VMStateField *field) > { > uint8_t *v = pv; > uint8_t v2; > @@ -758,7 +771,8 @@ const VMStateInfo vmstate_info_uint8_equal = { > /* 16 bit unsigned int int. See that the received value is the same than the one > in the field */ > > -static int get_uint16_equal(QEMUFile *f, void *pv, size_t size) > +static int get_uint16_equal(QEMUFile *f, void *pv, size_t size, > + VMStateField *field) > { > uint16_t *v = pv; > uint16_t v2; > @@ -778,7 +792,8 @@ const VMStateInfo vmstate_info_uint16_equal = { > > /* floating point */ > > -static int get_float64(QEMUFile *f, void *pv, size_t size) > +static int get_float64(QEMUFile *f, void *pv, size_t size, > + VMStateField *field) > { > float64 *v = pv; > > @@ -786,7 +801,8 @@ static int get_float64(QEMUFile *f, void *pv, size_t size) > return 0; > } > > -static void put_float64(QEMUFile *f, void *pv, size_t size) > +static void put_float64(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > uint64_t *v = pv; > > @@ -801,7 +817,8 @@ const VMStateInfo vmstate_info_float64 = { > > /* CPU_DoubleU type */ > > -static int get_cpudouble(QEMUFile *f, void *pv, size_t size) > +static int get_cpudouble(QEMUFile *f, void *pv, size_t size, > + VMStateField *field) > { > CPU_DoubleU *v = pv; > qemu_get_be32s(f, &v->l.upper); > @@ -809,7 +826,8 @@ static int get_cpudouble(QEMUFile *f, void *pv, size_t size) > return 0; > } > > -static void put_cpudouble(QEMUFile *f, void *pv, size_t size) > +static void put_cpudouble(QEMUFile *f, void *pv, size_t size, > + VMStateField *field, QJSON *vmdesc) > { > CPU_DoubleU *v = pv; > qemu_put_be32s(f, &v->l.upper); > @@ -824,14 +842,16 @@ const VMStateInfo vmstate_info_cpudouble = { > > /* uint8_t buffers */ > > -static int get_buffer(QEMUFile *f, void *pv, size_t size) > +static int get_buffer(QEMUFile *f, void *pv, size_t size, > + VMStateField *field) > { > uint8_t *v = pv; > qemu_get_buffer(f, v, size); > return 0; > } > > -static void put_buffer(QEMUFile *f, void *pv, size_t size) > +static void put_buffer(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > uint8_t *v = pv; > qemu_put_buffer(f, v, size); > @@ -846,7 +866,8 @@ const VMStateInfo vmstate_info_buffer = { > /* unused buffers: space that was used for some fields that are > not useful anymore */ > > -static int get_unused_buffer(QEMUFile *f, void *pv, size_t size) > +static int get_unused_buffer(QEMUFile *f, void *pv, size_t size, > + VMStateField *field) > { > uint8_t buf[1024]; > int block_len; > @@ -859,7 +880,8 @@ static int get_unused_buffer(QEMUFile *f, void *pv, size_t size) > return 0; > } > > -static void put_unused_buffer(QEMUFile *f, void *pv, size_t size) > +static void put_unused_buffer(QEMUFile *f, void *pv, size_t size, > + VMStateField *field, QJSON *vmdesc) > { > static const uint8_t buf[1024]; > int block_len; > @@ -884,7 +906,7 @@ const VMStateInfo vmstate_info_unused_buffer = { > */ > /* This is the number of 64 bit words sent over the wire */ > #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64) > -static int get_bitmap(QEMUFile *f, void *pv, size_t size) > +static int get_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field) > { > unsigned long *bmp = pv; > int i, idx = 0; > @@ -898,7 +920,8 @@ static int get_bitmap(QEMUFile *f, void *pv, size_t size) > return 0; > } > > -static void put_bitmap(QEMUFile *f, void *pv, size_t size) > +static void put_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > unsigned long *bmp = pv; > int i, idx = 0; > diff --git a/target-alpha/machine.c b/target-alpha/machine.c > index 710b783..48e3278 100644 > --- a/target-alpha/machine.c > +++ b/target-alpha/machine.c > @@ -5,14 +5,15 @@ > #include "hw/boards.h" > #include "migration/cpu.h" > > -static int get_fpcr(QEMUFile *f, void *opaque, size_t size) > +static int get_fpcr(QEMUFile *f, void *opaque, size_t size, VMStateField *field) > { > CPUAlphaState *env = opaque; > cpu_alpha_store_fpcr(env, qemu_get_be64(f)); > return 0; > } > > -static void put_fpcr(QEMUFile *f, void *opaque, size_t size) > +static void put_fpcr(QEMUFile *f, void *opaque, size_t size, > + VMStateField *field, QJSON *vmdesc) > { > CPUAlphaState *env = opaque; > qemu_put_be64(f, cpu_alpha_load_fpcr(env)); > diff --git a/target-arm/machine.c b/target-arm/machine.c > index 7a6ca31..41a0de9 100644 > --- a/target-arm/machine.c > +++ b/target-arm/machine.c > @@ -17,7 +17,8 @@ static bool vfp_needed(void *opaque) > return arm_feature(env, ARM_FEATURE_VFP); > } > > -static int get_fpscr(QEMUFile *f, void *opaque, size_t size) > +static int get_fpscr(QEMUFile *f, void *opaque, size_t size, > + VMStateField *field) > { > ARMCPU *cpu = opaque; > CPUARMState *env = &cpu->env; > @@ -27,7 +28,8 @@ static int get_fpscr(QEMUFile *f, void *opaque, size_t size) > return 0; > } > > -static void put_fpscr(QEMUFile *f, void *opaque, size_t size) > +static void put_fpscr(QEMUFile *f, void *opaque, size_t size, > + VMStateField *field, QJSON *vmdesc) > { > ARMCPU *cpu = opaque; > CPUARMState *env = &cpu->env; > @@ -163,7 +165,8 @@ static const VMStateDescription vmstate_pmsav7 = { > } > }; > > -static int get_cpsr(QEMUFile *f, void *opaque, size_t size) > +static int get_cpsr(QEMUFile *f, void *opaque, size_t size, > + VMStateField *field) > { > ARMCPU *cpu = opaque; > CPUARMState *env = &cpu->env; > @@ -180,7 +183,8 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size) > return 0; > } > > -static void put_cpsr(QEMUFile *f, void *opaque, size_t size) > +static void put_cpsr(QEMUFile *f, void *opaque, size_t size, > + VMStateField *field, QJSON *vmdesc) > { > ARMCPU *cpu = opaque; > CPUARMState *env = &cpu->env; > diff --git a/target-i386/machine.c b/target-i386/machine.c > index 71c0e4d..1df19e2 100644 > --- a/target-i386/machine.c > +++ b/target-i386/machine.c > @@ -139,7 +139,8 @@ static const VMStateDescription vmstate_mtrr_var = { > #define VMSTATE_MTRR_VARS(_field, _state, _n, _v) \ > VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar) > > -static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size) > +static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size, > + VMStateField *field, QJSON *vmdesc) > { > fprintf(stderr, "call put_fpreg() with invalid arguments\n"); > exit(0); > @@ -167,7 +168,8 @@ static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp) > p->exp = e; > } > > -static int get_fpreg(QEMUFile *f, void *opaque, size_t size) > +static int get_fpreg(QEMUFile *f, void *opaque, size_t size, > + VMStateField *field) > { > FPReg *fp_reg = opaque; > uint64_t mant; > @@ -179,7 +181,8 @@ static int get_fpreg(QEMUFile *f, void *opaque, size_t size) > return 0; > } > > -static void put_fpreg(QEMUFile *f, void *opaque, size_t size) > +static void put_fpreg(QEMUFile *f, void *opaque, size_t size, > + VMStateField *field, QJSON *vmdesc) > { > FPReg *fp_reg = opaque; > uint64_t mant; > @@ -197,7 +200,8 @@ static const VMStateInfo vmstate_fpreg = { > .put = put_fpreg, > }; > > -static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size) > +static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size, > + VMStateField *field) > { > union x86_longdouble *p = opaque; > uint64_t mant; > @@ -214,7 +218,8 @@ static const VMStateInfo vmstate_fpreg_1_mmx = { > .put = put_fpreg_error, > }; > > -static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size) > +static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size, > + VMStateField *field) > { > union x86_longdouble *p = opaque; > uint64_t mant; > @@ -276,14 +281,16 @@ static bool less_than_7(void *opaque, int version_id) > return version_id < 7; > } > > -static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size) > +static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size, > + VMStateField *field) > { > uint64_t *v = pv; > *v = qemu_get_be32(f); > return 0; > } > > -static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size) > +static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size, > + VMStateField *field, QJSON *vmdesc) > { > uint64_t *v = pv; > qemu_put_be32(f, *v); > diff --git a/target-mips/machine.c b/target-mips/machine.c > index a27f2f1..179084c 100644 > --- a/target-mips/machine.c > +++ b/target-mips/machine.c > @@ -20,7 +20,7 @@ static int cpu_post_load(void *opaque, int version_id) > > /* FPU state */ > > -static int get_fpr(QEMUFile *f, void *pv, size_t size) > +static int get_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field) > { > int i; > fpr_t *v = pv; > @@ -31,7 +31,8 @@ static int get_fpr(QEMUFile *f, void *pv, size_t size) > return 0; > } > > -static void put_fpr(QEMUFile *f, void *pv, size_t size) > +static void put_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > int i; > fpr_t *v = pv; > @@ -125,7 +126,7 @@ const VMStateDescription vmstate_mvp = { > > /* TLB state */ > > -static int get_tlb(QEMUFile *f, void *pv, size_t size) > +static int get_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field) > { > r4k_tlb_t *v = pv; > uint16_t flags; > @@ -152,7 +153,8 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size) > return 0; > } > > -static void put_tlb(QEMUFile *f, void *pv, size_t size) > +static void put_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > r4k_tlb_t *v = pv; > > diff --git a/target-ppc/machine.c b/target-ppc/machine.c > index 4820f22..0e1822c 100644 > --- a/target-ppc/machine.c > +++ b/target-ppc/machine.c > @@ -106,7 +106,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id) > return 0; > } > > -static int get_avr(QEMUFile *f, void *pv, size_t size) > +static int get_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field) > { > ppc_avr_t *v = pv; > > @@ -116,7 +116,8 @@ static int get_avr(QEMUFile *f, void *pv, size_t size) > return 0; > } > > -static void put_avr(QEMUFile *f, void *pv, size_t size) > +static void put_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > ppc_avr_t *v = pv; > > @@ -324,7 +325,7 @@ static const VMStateDescription vmstate_sr = { > }; > > #ifdef TARGET_PPC64 > -static int get_slbe(QEMUFile *f, void *pv, size_t size) > +static int get_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field) > { > ppc_slb_t *v = pv; > > @@ -334,7 +335,8 @@ static int get_slbe(QEMUFile *f, void *pv, size_t size) > return 0; > } > > -static void put_slbe(QEMUFile *f, void *pv, size_t size) > +static void put_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > ppc_slb_t *v = pv; > > diff --git a/target-sparc/machine.c b/target-sparc/machine.c > index 59c92f7..3194e03 100644 > --- a/target-sparc/machine.c > +++ b/target-sparc/machine.c > @@ -59,7 +59,7 @@ static const VMStateDescription vmstate_tlb_entry = { > }; > #endif > > -static int get_psr(QEMUFile *f, void *opaque, size_t size) > +static int get_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field) > { > SPARCCPU *cpu = opaque; > CPUSPARCState *env = &cpu->env; > @@ -72,7 +72,8 @@ static int get_psr(QEMUFile *f, void *opaque, size_t size) > return 0; > } > > -static void put_psr(QEMUFile *f, void *opaque, size_t size) > +static void put_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field, > + QJSON *vmdesc) > { > SPARCCPU *cpu = opaque; > CPUSPARCState *env = &cpu->env; > -- > 1.9.1 > > -- Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
On 10/07/2016 05:08 AM, Dr. David Alan Gilbert wrote: > * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote: >> Current migration code cannot handle some data structures such as >> QTAILQ in qemu/queue.h. Here we extend the signatures of put/get >> in VMStateInfo so that customized handling is supported. >> >> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com> >> --- >> hw/net/vmxnet3.c | 18 ++++++--- >> hw/nvram/eeprom93xx.c | 6 ++- >> hw/nvram/fw_cfg.c | 6 ++- >> hw/pci/msix.c | 6 ++- >> hw/pci/pci.c | 12 ++++-- >> hw/pci/shpc.c | 5 ++- >> hw/scsi/scsi-bus.c | 6 ++- >> hw/timer/twl92230.c | 6 ++- >> hw/usb/redirect.c | 18 ++++++--- >> hw/virtio/virtio-pci.c | 6 ++- >> hw/virtio/virtio.c | 6 ++- >> include/migration/vmstate.h | 10 +++-- >> migration/savevm.c | 5 ++- >> migration/vmstate.c | 95 ++++++++++++++++++++++++++++----------------- >> target-alpha/machine.c | 5 ++- >> target-arm/machine.c | 12 ++++-- >> target-i386/machine.c | 21 ++++++---- >> target-mips/machine.c | 10 +++-- >> target-ppc/machine.c | 10 +++-- >> target-sparc/machine.c | 5 ++- >> 20 files changed, 171 insertions(+), 97 deletions(-) >> > > <snip> > >> diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c >> index 444672a..2ca4b46 100644 >> --- a/hw/usb/redirect.c >> +++ b/hw/usb/redirect.c >> @@ -2154,7 +2154,8 @@ static int usbredir_post_load(void *priv, int version_id) >> } >> >> /* For usbredirparser migration */ >> -static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused) >> +static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused, >> + void *opaque, QJSON *vmdesc) >> { >> USBRedirDevice *dev = priv; >> uint8_t *data; >> @@ -2174,7 +2175,8 @@ static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused) >> free(data); >> } >> >> -static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused) >> +static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused, >> + void *opaque) > > Neither of these built for me; I had to change those to VMStateField rather than void *; > > also is this series tested ontop of Halil's patches - because without them > I'm finding I also had to fix up most of the other virtio devices. > > Dave I built it on top of ppc-for-2.8 without problems. Is Hail's patch in ppc-for-2.8 yet? Thanks, Jianjun > > >> USBRedirDevice *dev = priv; >> uint8_t *data; >> @@ -2217,7 +2219,8 @@ static const VMStateInfo usbredir_parser_vmstate_info = { >> >> >> /* For buffered packets (iso/irq) queue migration */ >> -static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused) >> +static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused, >> + VMStateField *field, QJSON *vmdesc) >> { >> struct endp_data *endp = priv; >> USBRedirDevice *dev = endp->dev; >> @@ -2237,7 +2240,8 @@ static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused) >> assert(i == endp->bufpq_size); >> } >> >> -static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused) >> +static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused, >> + VMStateField *field) >> { >> struct endp_data *endp = priv; >> USBRedirDevice *dev = endp->dev; >> @@ -2340,7 +2344,8 @@ static const VMStateDescription usbredir_ep_vmstate = { >> >> >> /* For PacketIdQueue migration */ >> -static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused) >> +static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused, >> + VMStateField *field, QJSON *vmdesc) >> { >> struct PacketIdQueue *q = priv; >> USBRedirDevice *dev = q->dev; >> @@ -2356,7 +2361,8 @@ static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused) >> assert(remain == 0); >> } >> >> -static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused) >> +static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused, >> + VMStateField *field) >> { >> struct PacketIdQueue *q = priv; >> USBRedirDevice *dev = q->dev; >> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c >> index 2d60a00..38a7abd 100644 >> --- a/hw/virtio/virtio-pci.c >> +++ b/hw/virtio/virtio-pci.c >> @@ -108,7 +108,8 @@ static bool virtio_pci_has_extra_state(DeviceState *d) >> return proxy->flags & VIRTIO_PCI_FLAG_MIGRATE_EXTRA; >> } >> >> -static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size) >> +static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field) >> { >> VirtIOPCIProxy *proxy = pv; >> int i; >> @@ -137,7 +138,8 @@ static void virtio_pci_save_modern_queue_state(VirtIOPCIQueue *vq, >> qemu_put_be32(f, vq->used[1]); >> } >> >> -static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size) >> +static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field, QJSON *vmdesc) >> { >> VirtIOPCIProxy *proxy = pv; >> int i; >> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c >> index 18ce333..ade2683 100644 >> --- a/hw/virtio/virtio.c >> +++ b/hw/virtio/virtio.c >> @@ -1467,7 +1467,8 @@ static const VMStateDescription vmstate_virtio_ringsize = { >> } >> }; >> >> -static int get_extra_state(QEMUFile *f, void *pv, size_t size) >> +static int get_extra_state(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field) >> { >> VirtIODevice *vdev = pv; >> BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); >> @@ -1480,7 +1481,8 @@ static int get_extra_state(QEMUFile *f, void *pv, size_t size) >> } >> } >> >> -static void put_extra_state(QEMUFile *f, void *pv, size_t size) >> +static void put_extra_state(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field, QJSON *vmdesc) >> { >> VirtIODevice *vdev = pv; >> BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); >> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h >> index 1638ee5..459dd4a 100644 >> --- a/include/migration/vmstate.h >> +++ b/include/migration/vmstate.h >> @@ -81,11 +81,13 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque); >> >> typedef struct VMStateInfo VMStateInfo; >> typedef struct VMStateDescription VMStateDescription; >> +typedef struct VMStateField VMStateField; >> >> struct VMStateInfo { >> const char *name; >> - int (*get)(QEMUFile *f, void *pv, size_t size); >> - void (*put)(QEMUFile *f, void *pv, size_t size); >> + int (*get)(QEMUFile *f, void *pv, size_t size, VMStateField *field); >> + void (*put)(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc); >> }; >> >> enum VMStateFlags { >> @@ -186,7 +188,7 @@ enum VMStateFlags { >> VMS_MULTIPLY_ELEMENTS = 0x4000, >> }; >> >> -typedef struct { >> +struct VMStateField { >> const char *name; >> size_t offset; >> size_t size; >> @@ -199,7 +201,7 @@ typedef struct { >> const VMStateDescription *vmsd; >> int version_id; >> bool (*field_exists)(void *opaque, int version_id); >> -} VMStateField; >> +}; >> >> struct VMStateDescription { >> const char *name; >> diff --git a/migration/savevm.c b/migration/savevm.c >> index ef5c3d1..13b53ad 100644 >> --- a/migration/savevm.c >> +++ b/migration/savevm.c >> @@ -220,14 +220,15 @@ void timer_get(QEMUFile *f, QEMUTimer *ts) >> * Not in vmstate.c to not add qemu-timer.c as dependency to vmstate.c >> */ >> >> -static int get_timer(QEMUFile *f, void *pv, size_t size) >> +static int get_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field) >> { >> QEMUTimer *v = pv; >> timer_get(f, v); >> return 0; >> } >> >> -static void put_timer(QEMUFile *f, void *pv, size_t size) >> +static void put_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> QEMUTimer *v = pv; >> timer_put(f, v); >> diff --git a/migration/vmstate.c b/migration/vmstate.c >> index fc29acf..66802cb 100644 >> --- a/migration/vmstate.c >> +++ b/migration/vmstate.c >> @@ -122,7 +122,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, >> ret = vmstate_load_state(f, field->vmsd, addr, >> field->vmsd->version_id); >> } else { >> - ret = field->info->get(f, addr, size); >> + ret = field->info->get(f, addr, size, NULL); >> >> } >> if (ret >= 0) { >> @@ -328,7 +328,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, >> if (field->flags & VMS_STRUCT) { >> vmstate_save_state(f, field->vmsd, addr, vmdesc_loop); >> } else { >> - field->info->put(f, addr, size); >> + field->info->put(f, addr, size, NULL, NULL); >> } >> >> written_bytes = qemu_ftell_fast(f) - old_offset; >> @@ -461,14 +461,15 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, >> >> /* bool */ >> >> -static int get_bool(QEMUFile *f, void *pv, size_t size) >> +static int get_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field) >> { >> bool *v = pv; >> *v = qemu_get_byte(f); >> return 0; >> } >> >> -static void put_bool(QEMUFile *f, void *pv, size_t size) >> +static void put_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> bool *v = pv; >> qemu_put_byte(f, *v); >> @@ -482,14 +483,15 @@ const VMStateInfo vmstate_info_bool = { >> >> /* 8 bit int */ >> >> -static int get_int8(QEMUFile *f, void *pv, size_t size) >> +static int get_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field) >> { >> int8_t *v = pv; >> qemu_get_s8s(f, v); >> return 0; >> } >> >> -static void put_int8(QEMUFile *f, void *pv, size_t size) >> +static void put_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> int8_t *v = pv; >> qemu_put_s8s(f, v); >> @@ -503,14 +505,15 @@ const VMStateInfo vmstate_info_int8 = { >> >> /* 16 bit int */ >> >> -static int get_int16(QEMUFile *f, void *pv, size_t size) >> +static int get_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field) >> { >> int16_t *v = pv; >> qemu_get_sbe16s(f, v); >> return 0; >> } >> >> -static void put_int16(QEMUFile *f, void *pv, size_t size) >> +static void put_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> int16_t *v = pv; >> qemu_put_sbe16s(f, v); >> @@ -524,14 +527,15 @@ const VMStateInfo vmstate_info_int16 = { >> >> /* 32 bit int */ >> >> -static int get_int32(QEMUFile *f, void *pv, size_t size) >> +static int get_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field) >> { >> int32_t *v = pv; >> qemu_get_sbe32s(f, v); >> return 0; >> } >> >> -static void put_int32(QEMUFile *f, void *pv, size_t size) >> +static void put_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> int32_t *v = pv; >> qemu_put_sbe32s(f, v); >> @@ -546,7 +550,8 @@ const VMStateInfo vmstate_info_int32 = { >> /* 32 bit int. See that the received value is the same than the one >> in the field */ >> >> -static int get_int32_equal(QEMUFile *f, void *pv, size_t size) >> +static int get_int32_equal(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field) >> { >> int32_t *v = pv; >> int32_t v2; >> @@ -568,7 +573,7 @@ const VMStateInfo vmstate_info_int32_equal = { >> * and less than or equal to the one in the field. >> */ >> >> -static int get_int32_le(QEMUFile *f, void *pv, size_t size) >> +static int get_int32_le(QEMUFile *f, void *pv, size_t size, VMStateField *field) >> { >> int32_t *cur = pv; >> int32_t loaded; >> @@ -589,14 +594,15 @@ const VMStateInfo vmstate_info_int32_le = { >> >> /* 64 bit int */ >> >> -static int get_int64(QEMUFile *f, void *pv, size_t size) >> +static int get_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field) >> { >> int64_t *v = pv; >> qemu_get_sbe64s(f, v); >> return 0; >> } >> >> -static void put_int64(QEMUFile *f, void *pv, size_t size) >> +static void put_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> int64_t *v = pv; >> qemu_put_sbe64s(f, v); >> @@ -610,14 +616,15 @@ const VMStateInfo vmstate_info_int64 = { >> >> /* 8 bit unsigned int */ >> >> -static int get_uint8(QEMUFile *f, void *pv, size_t size) >> +static int get_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field) >> { >> uint8_t *v = pv; >> qemu_get_8s(f, v); >> return 0; >> } >> >> -static void put_uint8(QEMUFile *f, void *pv, size_t size) >> +static void put_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> uint8_t *v = pv; >> qemu_put_8s(f, v); >> @@ -631,14 +638,15 @@ const VMStateInfo vmstate_info_uint8 = { >> >> /* 16 bit unsigned int */ >> >> -static int get_uint16(QEMUFile *f, void *pv, size_t size) >> +static int get_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field) >> { >> uint16_t *v = pv; >> qemu_get_be16s(f, v); >> return 0; >> } >> >> -static void put_uint16(QEMUFile *f, void *pv, size_t size) >> +static void put_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> uint16_t *v = pv; >> qemu_put_be16s(f, v); >> @@ -652,14 +660,15 @@ const VMStateInfo vmstate_info_uint16 = { >> >> /* 32 bit unsigned int */ >> >> -static int get_uint32(QEMUFile *f, void *pv, size_t size) >> +static int get_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field) >> { >> uint32_t *v = pv; >> qemu_get_be32s(f, v); >> return 0; >> } >> >> -static void put_uint32(QEMUFile *f, void *pv, size_t size) >> +static void put_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> uint32_t *v = pv; >> qemu_put_be32s(f, v); >> @@ -674,7 +683,8 @@ const VMStateInfo vmstate_info_uint32 = { >> /* 32 bit uint. See that the received value is the same than the one >> in the field */ >> >> -static int get_uint32_equal(QEMUFile *f, void *pv, size_t size) >> +static int get_uint32_equal(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field) >> { >> uint32_t *v = pv; >> uint32_t v2; >> @@ -694,14 +704,15 @@ const VMStateInfo vmstate_info_uint32_equal = { >> >> /* 64 bit unsigned int */ >> >> -static int get_uint64(QEMUFile *f, void *pv, size_t size) >> +static int get_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field) >> { >> uint64_t *v = pv; >> qemu_get_be64s(f, v); >> return 0; >> } >> >> -static void put_uint64(QEMUFile *f, void *pv, size_t size) >> +static void put_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> uint64_t *v = pv; >> qemu_put_be64s(f, v); >> @@ -716,7 +727,8 @@ const VMStateInfo vmstate_info_uint64 = { >> /* 64 bit unsigned int. See that the received value is the same than the one >> in the field */ >> >> -static int get_uint64_equal(QEMUFile *f, void *pv, size_t size) >> +static int get_uint64_equal(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field) >> { >> uint64_t *v = pv; >> uint64_t v2; >> @@ -737,7 +749,8 @@ const VMStateInfo vmstate_info_uint64_equal = { >> /* 8 bit int. See that the received value is the same than the one >> in the field */ >> >> -static int get_uint8_equal(QEMUFile *f, void *pv, size_t size) >> +static int get_uint8_equal(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field) >> { >> uint8_t *v = pv; >> uint8_t v2; >> @@ -758,7 +771,8 @@ const VMStateInfo vmstate_info_uint8_equal = { >> /* 16 bit unsigned int int. See that the received value is the same than the one >> in the field */ >> >> -static int get_uint16_equal(QEMUFile *f, void *pv, size_t size) >> +static int get_uint16_equal(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field) >> { >> uint16_t *v = pv; >> uint16_t v2; >> @@ -778,7 +792,8 @@ const VMStateInfo vmstate_info_uint16_equal = { >> >> /* floating point */ >> >> -static int get_float64(QEMUFile *f, void *pv, size_t size) >> +static int get_float64(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field) >> { >> float64 *v = pv; >> >> @@ -786,7 +801,8 @@ static int get_float64(QEMUFile *f, void *pv, size_t size) >> return 0; >> } >> >> -static void put_float64(QEMUFile *f, void *pv, size_t size) >> +static void put_float64(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> uint64_t *v = pv; >> >> @@ -801,7 +817,8 @@ const VMStateInfo vmstate_info_float64 = { >> >> /* CPU_DoubleU type */ >> >> -static int get_cpudouble(QEMUFile *f, void *pv, size_t size) >> +static int get_cpudouble(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field) >> { >> CPU_DoubleU *v = pv; >> qemu_get_be32s(f, &v->l.upper); >> @@ -809,7 +826,8 @@ static int get_cpudouble(QEMUFile *f, void *pv, size_t size) >> return 0; >> } >> >> -static void put_cpudouble(QEMUFile *f, void *pv, size_t size) >> +static void put_cpudouble(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field, QJSON *vmdesc) >> { >> CPU_DoubleU *v = pv; >> qemu_put_be32s(f, &v->l.upper); >> @@ -824,14 +842,16 @@ const VMStateInfo vmstate_info_cpudouble = { >> >> /* uint8_t buffers */ >> >> -static int get_buffer(QEMUFile *f, void *pv, size_t size) >> +static int get_buffer(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field) >> { >> uint8_t *v = pv; >> qemu_get_buffer(f, v, size); >> return 0; >> } >> >> -static void put_buffer(QEMUFile *f, void *pv, size_t size) >> +static void put_buffer(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> uint8_t *v = pv; >> qemu_put_buffer(f, v, size); >> @@ -846,7 +866,8 @@ const VMStateInfo vmstate_info_buffer = { >> /* unused buffers: space that was used for some fields that are >> not useful anymore */ >> >> -static int get_unused_buffer(QEMUFile *f, void *pv, size_t size) >> +static int get_unused_buffer(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field) >> { >> uint8_t buf[1024]; >> int block_len; >> @@ -859,7 +880,8 @@ static int get_unused_buffer(QEMUFile *f, void *pv, size_t size) >> return 0; >> } >> >> -static void put_unused_buffer(QEMUFile *f, void *pv, size_t size) >> +static void put_unused_buffer(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field, QJSON *vmdesc) >> { >> static const uint8_t buf[1024]; >> int block_len; >> @@ -884,7 +906,7 @@ const VMStateInfo vmstate_info_unused_buffer = { >> */ >> /* This is the number of 64 bit words sent over the wire */ >> #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64) >> -static int get_bitmap(QEMUFile *f, void *pv, size_t size) >> +static int get_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field) >> { >> unsigned long *bmp = pv; >> int i, idx = 0; >> @@ -898,7 +920,8 @@ static int get_bitmap(QEMUFile *f, void *pv, size_t size) >> return 0; >> } >> >> -static void put_bitmap(QEMUFile *f, void *pv, size_t size) >> +static void put_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> unsigned long *bmp = pv; >> int i, idx = 0; >> diff --git a/target-alpha/machine.c b/target-alpha/machine.c >> index 710b783..48e3278 100644 >> --- a/target-alpha/machine.c >> +++ b/target-alpha/machine.c >> @@ -5,14 +5,15 @@ >> #include "hw/boards.h" >> #include "migration/cpu.h" >> >> -static int get_fpcr(QEMUFile *f, void *opaque, size_t size) >> +static int get_fpcr(QEMUFile *f, void *opaque, size_t size, VMStateField *field) >> { >> CPUAlphaState *env = opaque; >> cpu_alpha_store_fpcr(env, qemu_get_be64(f)); >> return 0; >> } >> >> -static void put_fpcr(QEMUFile *f, void *opaque, size_t size) >> +static void put_fpcr(QEMUFile *f, void *opaque, size_t size, >> + VMStateField *field, QJSON *vmdesc) >> { >> CPUAlphaState *env = opaque; >> qemu_put_be64(f, cpu_alpha_load_fpcr(env)); >> diff --git a/target-arm/machine.c b/target-arm/machine.c >> index 7a6ca31..41a0de9 100644 >> --- a/target-arm/machine.c >> +++ b/target-arm/machine.c >> @@ -17,7 +17,8 @@ static bool vfp_needed(void *opaque) >> return arm_feature(env, ARM_FEATURE_VFP); >> } >> >> -static int get_fpscr(QEMUFile *f, void *opaque, size_t size) >> +static int get_fpscr(QEMUFile *f, void *opaque, size_t size, >> + VMStateField *field) >> { >> ARMCPU *cpu = opaque; >> CPUARMState *env = &cpu->env; >> @@ -27,7 +28,8 @@ static int get_fpscr(QEMUFile *f, void *opaque, size_t size) >> return 0; >> } >> >> -static void put_fpscr(QEMUFile *f, void *opaque, size_t size) >> +static void put_fpscr(QEMUFile *f, void *opaque, size_t size, >> + VMStateField *field, QJSON *vmdesc) >> { >> ARMCPU *cpu = opaque; >> CPUARMState *env = &cpu->env; >> @@ -163,7 +165,8 @@ static const VMStateDescription vmstate_pmsav7 = { >> } >> }; >> >> -static int get_cpsr(QEMUFile *f, void *opaque, size_t size) >> +static int get_cpsr(QEMUFile *f, void *opaque, size_t size, >> + VMStateField *field) >> { >> ARMCPU *cpu = opaque; >> CPUARMState *env = &cpu->env; >> @@ -180,7 +183,8 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size) >> return 0; >> } >> >> -static void put_cpsr(QEMUFile *f, void *opaque, size_t size) >> +static void put_cpsr(QEMUFile *f, void *opaque, size_t size, >> + VMStateField *field, QJSON *vmdesc) >> { >> ARMCPU *cpu = opaque; >> CPUARMState *env = &cpu->env; >> diff --git a/target-i386/machine.c b/target-i386/machine.c >> index 71c0e4d..1df19e2 100644 >> --- a/target-i386/machine.c >> +++ b/target-i386/machine.c >> @@ -139,7 +139,8 @@ static const VMStateDescription vmstate_mtrr_var = { >> #define VMSTATE_MTRR_VARS(_field, _state, _n, _v) \ >> VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar) >> >> -static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size) >> +static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size, >> + VMStateField *field, QJSON *vmdesc) >> { >> fprintf(stderr, "call put_fpreg() with invalid arguments\n"); >> exit(0); >> @@ -167,7 +168,8 @@ static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp) >> p->exp = e; >> } >> >> -static int get_fpreg(QEMUFile *f, void *opaque, size_t size) >> +static int get_fpreg(QEMUFile *f, void *opaque, size_t size, >> + VMStateField *field) >> { >> FPReg *fp_reg = opaque; >> uint64_t mant; >> @@ -179,7 +181,8 @@ static int get_fpreg(QEMUFile *f, void *opaque, size_t size) >> return 0; >> } >> >> -static void put_fpreg(QEMUFile *f, void *opaque, size_t size) >> +static void put_fpreg(QEMUFile *f, void *opaque, size_t size, >> + VMStateField *field, QJSON *vmdesc) >> { >> FPReg *fp_reg = opaque; >> uint64_t mant; >> @@ -197,7 +200,8 @@ static const VMStateInfo vmstate_fpreg = { >> .put = put_fpreg, >> }; >> >> -static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size) >> +static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size, >> + VMStateField *field) >> { >> union x86_longdouble *p = opaque; >> uint64_t mant; >> @@ -214,7 +218,8 @@ static const VMStateInfo vmstate_fpreg_1_mmx = { >> .put = put_fpreg_error, >> }; >> >> -static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size) >> +static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size, >> + VMStateField *field) >> { >> union x86_longdouble *p = opaque; >> uint64_t mant; >> @@ -276,14 +281,16 @@ static bool less_than_7(void *opaque, int version_id) >> return version_id < 7; >> } >> >> -static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size) >> +static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field) >> { >> uint64_t *v = pv; >> *v = qemu_get_be32(f); >> return 0; >> } >> >> -static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size) >> +static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size, >> + VMStateField *field, QJSON *vmdesc) >> { >> uint64_t *v = pv; >> qemu_put_be32(f, *v); >> diff --git a/target-mips/machine.c b/target-mips/machine.c >> index a27f2f1..179084c 100644 >> --- a/target-mips/machine.c >> +++ b/target-mips/machine.c >> @@ -20,7 +20,7 @@ static int cpu_post_load(void *opaque, int version_id) >> >> /* FPU state */ >> >> -static int get_fpr(QEMUFile *f, void *pv, size_t size) >> +static int get_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field) >> { >> int i; >> fpr_t *v = pv; >> @@ -31,7 +31,8 @@ static int get_fpr(QEMUFile *f, void *pv, size_t size) >> return 0; >> } >> >> -static void put_fpr(QEMUFile *f, void *pv, size_t size) >> +static void put_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> int i; >> fpr_t *v = pv; >> @@ -125,7 +126,7 @@ const VMStateDescription vmstate_mvp = { >> >> /* TLB state */ >> >> -static int get_tlb(QEMUFile *f, void *pv, size_t size) >> +static int get_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field) >> { >> r4k_tlb_t *v = pv; >> uint16_t flags; >> @@ -152,7 +153,8 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size) >> return 0; >> } >> >> -static void put_tlb(QEMUFile *f, void *pv, size_t size) >> +static void put_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> r4k_tlb_t *v = pv; >> >> diff --git a/target-ppc/machine.c b/target-ppc/machine.c >> index 4820f22..0e1822c 100644 >> --- a/target-ppc/machine.c >> +++ b/target-ppc/machine.c >> @@ -106,7 +106,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id) >> return 0; >> } >> >> -static int get_avr(QEMUFile *f, void *pv, size_t size) >> +static int get_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field) >> { >> ppc_avr_t *v = pv; >> >> @@ -116,7 +116,8 @@ static int get_avr(QEMUFile *f, void *pv, size_t size) >> return 0; >> } >> >> -static void put_avr(QEMUFile *f, void *pv, size_t size) >> +static void put_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> ppc_avr_t *v = pv; >> >> @@ -324,7 +325,7 @@ static const VMStateDescription vmstate_sr = { >> }; >> >> #ifdef TARGET_PPC64 >> -static int get_slbe(QEMUFile *f, void *pv, size_t size) >> +static int get_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field) >> { >> ppc_slb_t *v = pv; >> >> @@ -334,7 +335,8 @@ static int get_slbe(QEMUFile *f, void *pv, size_t size) >> return 0; >> } >> >> -static void put_slbe(QEMUFile *f, void *pv, size_t size) >> +static void put_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> ppc_slb_t *v = pv; >> >> diff --git a/target-sparc/machine.c b/target-sparc/machine.c >> index 59c92f7..3194e03 100644 >> --- a/target-sparc/machine.c >> +++ b/target-sparc/machine.c >> @@ -59,7 +59,7 @@ static const VMStateDescription vmstate_tlb_entry = { >> }; >> #endif >> >> -static int get_psr(QEMUFile *f, void *opaque, size_t size) >> +static int get_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field) >> { >> SPARCCPU *cpu = opaque; >> CPUSPARCState *env = &cpu->env; >> @@ -72,7 +72,8 @@ static int get_psr(QEMUFile *f, void *opaque, size_t size) >> return 0; >> } >> >> -static void put_psr(QEMUFile *f, void *opaque, size_t size) >> +static void put_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field, >> + QJSON *vmdesc) >> { >> SPARCCPU *cpu = opaque; >> CPUSPARCState *env = &cpu->env; >> -- >> 1.9.1 >> >> > -- > Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK >
* Jianjun Duan (duanj@linux.vnet.ibm.com) wrote: > > > On 10/07/2016 05:08 AM, Dr. David Alan Gilbert wrote: > > * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote: > >> Current migration code cannot handle some data structures such as > >> QTAILQ in qemu/queue.h. Here we extend the signatures of put/get > >> in VMStateInfo so that customized handling is supported. > >> > >> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com> > >> --- > >> hw/net/vmxnet3.c | 18 ++++++--- > >> hw/nvram/eeprom93xx.c | 6 ++- > >> hw/nvram/fw_cfg.c | 6 ++- > >> hw/pci/msix.c | 6 ++- > >> hw/pci/pci.c | 12 ++++-- > >> hw/pci/shpc.c | 5 ++- > >> hw/scsi/scsi-bus.c | 6 ++- > >> hw/timer/twl92230.c | 6 ++- > >> hw/usb/redirect.c | 18 ++++++--- > >> hw/virtio/virtio-pci.c | 6 ++- > >> hw/virtio/virtio.c | 6 ++- > >> include/migration/vmstate.h | 10 +++-- > >> migration/savevm.c | 5 ++- > >> migration/vmstate.c | 95 ++++++++++++++++++++++++++++----------------- > >> target-alpha/machine.c | 5 ++- > >> target-arm/machine.c | 12 ++++-- > >> target-i386/machine.c | 21 ++++++---- > >> target-mips/machine.c | 10 +++-- > >> target-ppc/machine.c | 10 +++-- > >> target-sparc/machine.c | 5 ++- > >> 20 files changed, 171 insertions(+), 97 deletions(-) > >> > > > > <snip> > > > >> diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c > >> index 444672a..2ca4b46 100644 > >> --- a/hw/usb/redirect.c > >> +++ b/hw/usb/redirect.c > >> @@ -2154,7 +2154,8 @@ static int usbredir_post_load(void *priv, int version_id) > >> } > >> > >> /* For usbredirparser migration */ > >> -static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused) > >> +static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused, > >> + void *opaque, QJSON *vmdesc) > >> { > >> USBRedirDevice *dev = priv; > >> uint8_t *data; > >> @@ -2174,7 +2175,8 @@ static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused) > >> free(data); > >> } > >> > >> -static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused) > >> +static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused, > >> + void *opaque) > > > > Neither of these built for me; I had to change those to VMStateField rather than void *; > > > > also is this series tested ontop of Halil's patches - because without them > > I'm finding I also had to fix up most of the other virtio devices. > > > > Dave > > I built it on top of ppc-for-2.8 without problems. Is Hail's patch in > ppc-for-2.8 yet? I don't know about ppc-for-2.8; patches for inclusion should work on the current head unless stated otherwise. Also, make sure you have the usbredir libraries installed and as much else as possible to make sure you cover all the .get/.put functions - they're all over! Dave > Thanks, > Jianjun > > > > > > >> USBRedirDevice *dev = priv; > >> uint8_t *data; > >> @@ -2217,7 +2219,8 @@ static const VMStateInfo usbredir_parser_vmstate_info = { > >> > >> > >> /* For buffered packets (iso/irq) queue migration */ > >> -static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused) > >> +static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused, > >> + VMStateField *field, QJSON *vmdesc) > >> { > >> struct endp_data *endp = priv; > >> USBRedirDevice *dev = endp->dev; > >> @@ -2237,7 +2240,8 @@ static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused) > >> assert(i == endp->bufpq_size); > >> } > >> > >> -static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused) > >> +static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused, > >> + VMStateField *field) > >> { > >> struct endp_data *endp = priv; > >> USBRedirDevice *dev = endp->dev; > >> @@ -2340,7 +2344,8 @@ static const VMStateDescription usbredir_ep_vmstate = { > >> > >> > >> /* For PacketIdQueue migration */ > >> -static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused) > >> +static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused, > >> + VMStateField *field, QJSON *vmdesc) > >> { > >> struct PacketIdQueue *q = priv; > >> USBRedirDevice *dev = q->dev; > >> @@ -2356,7 +2361,8 @@ static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused) > >> assert(remain == 0); > >> } > >> > >> -static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused) > >> +static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused, > >> + VMStateField *field) > >> { > >> struct PacketIdQueue *q = priv; > >> USBRedirDevice *dev = q->dev; > >> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c > >> index 2d60a00..38a7abd 100644 > >> --- a/hw/virtio/virtio-pci.c > >> +++ b/hw/virtio/virtio-pci.c > >> @@ -108,7 +108,8 @@ static bool virtio_pci_has_extra_state(DeviceState *d) > >> return proxy->flags & VIRTIO_PCI_FLAG_MIGRATE_EXTRA; > >> } > >> > >> -static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size) > >> +static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field) > >> { > >> VirtIOPCIProxy *proxy = pv; > >> int i; > >> @@ -137,7 +138,8 @@ static void virtio_pci_save_modern_queue_state(VirtIOPCIQueue *vq, > >> qemu_put_be32(f, vq->used[1]); > >> } > >> > >> -static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size) > >> +static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field, QJSON *vmdesc) > >> { > >> VirtIOPCIProxy *proxy = pv; > >> int i; > >> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c > >> index 18ce333..ade2683 100644 > >> --- a/hw/virtio/virtio.c > >> +++ b/hw/virtio/virtio.c > >> @@ -1467,7 +1467,8 @@ static const VMStateDescription vmstate_virtio_ringsize = { > >> } > >> }; > >> > >> -static int get_extra_state(QEMUFile *f, void *pv, size_t size) > >> +static int get_extra_state(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field) > >> { > >> VirtIODevice *vdev = pv; > >> BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); > >> @@ -1480,7 +1481,8 @@ static int get_extra_state(QEMUFile *f, void *pv, size_t size) > >> } > >> } > >> > >> -static void put_extra_state(QEMUFile *f, void *pv, size_t size) > >> +static void put_extra_state(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field, QJSON *vmdesc) > >> { > >> VirtIODevice *vdev = pv; > >> BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); > >> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h > >> index 1638ee5..459dd4a 100644 > >> --- a/include/migration/vmstate.h > >> +++ b/include/migration/vmstate.h > >> @@ -81,11 +81,13 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque); > >> > >> typedef struct VMStateInfo VMStateInfo; > >> typedef struct VMStateDescription VMStateDescription; > >> +typedef struct VMStateField VMStateField; > >> > >> struct VMStateInfo { > >> const char *name; > >> - int (*get)(QEMUFile *f, void *pv, size_t size); > >> - void (*put)(QEMUFile *f, void *pv, size_t size); > >> + int (*get)(QEMUFile *f, void *pv, size_t size, VMStateField *field); > >> + void (*put)(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc); > >> }; > >> > >> enum VMStateFlags { > >> @@ -186,7 +188,7 @@ enum VMStateFlags { > >> VMS_MULTIPLY_ELEMENTS = 0x4000, > >> }; > >> > >> -typedef struct { > >> +struct VMStateField { > >> const char *name; > >> size_t offset; > >> size_t size; > >> @@ -199,7 +201,7 @@ typedef struct { > >> const VMStateDescription *vmsd; > >> int version_id; > >> bool (*field_exists)(void *opaque, int version_id); > >> -} VMStateField; > >> +}; > >> > >> struct VMStateDescription { > >> const char *name; > >> diff --git a/migration/savevm.c b/migration/savevm.c > >> index ef5c3d1..13b53ad 100644 > >> --- a/migration/savevm.c > >> +++ b/migration/savevm.c > >> @@ -220,14 +220,15 @@ void timer_get(QEMUFile *f, QEMUTimer *ts) > >> * Not in vmstate.c to not add qemu-timer.c as dependency to vmstate.c > >> */ > >> > >> -static int get_timer(QEMUFile *f, void *pv, size_t size) > >> +static int get_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field) > >> { > >> QEMUTimer *v = pv; > >> timer_get(f, v); > >> return 0; > >> } > >> > >> -static void put_timer(QEMUFile *f, void *pv, size_t size) > >> +static void put_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> QEMUTimer *v = pv; > >> timer_put(f, v); > >> diff --git a/migration/vmstate.c b/migration/vmstate.c > >> index fc29acf..66802cb 100644 > >> --- a/migration/vmstate.c > >> +++ b/migration/vmstate.c > >> @@ -122,7 +122,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, > >> ret = vmstate_load_state(f, field->vmsd, addr, > >> field->vmsd->version_id); > >> } else { > >> - ret = field->info->get(f, addr, size); > >> + ret = field->info->get(f, addr, size, NULL); > >> > >> } > >> if (ret >= 0) { > >> @@ -328,7 +328,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, > >> if (field->flags & VMS_STRUCT) { > >> vmstate_save_state(f, field->vmsd, addr, vmdesc_loop); > >> } else { > >> - field->info->put(f, addr, size); > >> + field->info->put(f, addr, size, NULL, NULL); > >> } > >> > >> written_bytes = qemu_ftell_fast(f) - old_offset; > >> @@ -461,14 +461,15 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, > >> > >> /* bool */ > >> > >> -static int get_bool(QEMUFile *f, void *pv, size_t size) > >> +static int get_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field) > >> { > >> bool *v = pv; > >> *v = qemu_get_byte(f); > >> return 0; > >> } > >> > >> -static void put_bool(QEMUFile *f, void *pv, size_t size) > >> +static void put_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> bool *v = pv; > >> qemu_put_byte(f, *v); > >> @@ -482,14 +483,15 @@ const VMStateInfo vmstate_info_bool = { > >> > >> /* 8 bit int */ > >> > >> -static int get_int8(QEMUFile *f, void *pv, size_t size) > >> +static int get_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field) > >> { > >> int8_t *v = pv; > >> qemu_get_s8s(f, v); > >> return 0; > >> } > >> > >> -static void put_int8(QEMUFile *f, void *pv, size_t size) > >> +static void put_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> int8_t *v = pv; > >> qemu_put_s8s(f, v); > >> @@ -503,14 +505,15 @@ const VMStateInfo vmstate_info_int8 = { > >> > >> /* 16 bit int */ > >> > >> -static int get_int16(QEMUFile *f, void *pv, size_t size) > >> +static int get_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field) > >> { > >> int16_t *v = pv; > >> qemu_get_sbe16s(f, v); > >> return 0; > >> } > >> > >> -static void put_int16(QEMUFile *f, void *pv, size_t size) > >> +static void put_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> int16_t *v = pv; > >> qemu_put_sbe16s(f, v); > >> @@ -524,14 +527,15 @@ const VMStateInfo vmstate_info_int16 = { > >> > >> /* 32 bit int */ > >> > >> -static int get_int32(QEMUFile *f, void *pv, size_t size) > >> +static int get_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field) > >> { > >> int32_t *v = pv; > >> qemu_get_sbe32s(f, v); > >> return 0; > >> } > >> > >> -static void put_int32(QEMUFile *f, void *pv, size_t size) > >> +static void put_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> int32_t *v = pv; > >> qemu_put_sbe32s(f, v); > >> @@ -546,7 +550,8 @@ const VMStateInfo vmstate_info_int32 = { > >> /* 32 bit int. See that the received value is the same than the one > >> in the field */ > >> > >> -static int get_int32_equal(QEMUFile *f, void *pv, size_t size) > >> +static int get_int32_equal(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field) > >> { > >> int32_t *v = pv; > >> int32_t v2; > >> @@ -568,7 +573,7 @@ const VMStateInfo vmstate_info_int32_equal = { > >> * and less than or equal to the one in the field. > >> */ > >> > >> -static int get_int32_le(QEMUFile *f, void *pv, size_t size) > >> +static int get_int32_le(QEMUFile *f, void *pv, size_t size, VMStateField *field) > >> { > >> int32_t *cur = pv; > >> int32_t loaded; > >> @@ -589,14 +594,15 @@ const VMStateInfo vmstate_info_int32_le = { > >> > >> /* 64 bit int */ > >> > >> -static int get_int64(QEMUFile *f, void *pv, size_t size) > >> +static int get_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field) > >> { > >> int64_t *v = pv; > >> qemu_get_sbe64s(f, v); > >> return 0; > >> } > >> > >> -static void put_int64(QEMUFile *f, void *pv, size_t size) > >> +static void put_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> int64_t *v = pv; > >> qemu_put_sbe64s(f, v); > >> @@ -610,14 +616,15 @@ const VMStateInfo vmstate_info_int64 = { > >> > >> /* 8 bit unsigned int */ > >> > >> -static int get_uint8(QEMUFile *f, void *pv, size_t size) > >> +static int get_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field) > >> { > >> uint8_t *v = pv; > >> qemu_get_8s(f, v); > >> return 0; > >> } > >> > >> -static void put_uint8(QEMUFile *f, void *pv, size_t size) > >> +static void put_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> uint8_t *v = pv; > >> qemu_put_8s(f, v); > >> @@ -631,14 +638,15 @@ const VMStateInfo vmstate_info_uint8 = { > >> > >> /* 16 bit unsigned int */ > >> > >> -static int get_uint16(QEMUFile *f, void *pv, size_t size) > >> +static int get_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field) > >> { > >> uint16_t *v = pv; > >> qemu_get_be16s(f, v); > >> return 0; > >> } > >> > >> -static void put_uint16(QEMUFile *f, void *pv, size_t size) > >> +static void put_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> uint16_t *v = pv; > >> qemu_put_be16s(f, v); > >> @@ -652,14 +660,15 @@ const VMStateInfo vmstate_info_uint16 = { > >> > >> /* 32 bit unsigned int */ > >> > >> -static int get_uint32(QEMUFile *f, void *pv, size_t size) > >> +static int get_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field) > >> { > >> uint32_t *v = pv; > >> qemu_get_be32s(f, v); > >> return 0; > >> } > >> > >> -static void put_uint32(QEMUFile *f, void *pv, size_t size) > >> +static void put_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> uint32_t *v = pv; > >> qemu_put_be32s(f, v); > >> @@ -674,7 +683,8 @@ const VMStateInfo vmstate_info_uint32 = { > >> /* 32 bit uint. See that the received value is the same than the one > >> in the field */ > >> > >> -static int get_uint32_equal(QEMUFile *f, void *pv, size_t size) > >> +static int get_uint32_equal(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field) > >> { > >> uint32_t *v = pv; > >> uint32_t v2; > >> @@ -694,14 +704,15 @@ const VMStateInfo vmstate_info_uint32_equal = { > >> > >> /* 64 bit unsigned int */ > >> > >> -static int get_uint64(QEMUFile *f, void *pv, size_t size) > >> +static int get_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field) > >> { > >> uint64_t *v = pv; > >> qemu_get_be64s(f, v); > >> return 0; > >> } > >> > >> -static void put_uint64(QEMUFile *f, void *pv, size_t size) > >> +static void put_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> uint64_t *v = pv; > >> qemu_put_be64s(f, v); > >> @@ -716,7 +727,8 @@ const VMStateInfo vmstate_info_uint64 = { > >> /* 64 bit unsigned int. See that the received value is the same than the one > >> in the field */ > >> > >> -static int get_uint64_equal(QEMUFile *f, void *pv, size_t size) > >> +static int get_uint64_equal(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field) > >> { > >> uint64_t *v = pv; > >> uint64_t v2; > >> @@ -737,7 +749,8 @@ const VMStateInfo vmstate_info_uint64_equal = { > >> /* 8 bit int. See that the received value is the same than the one > >> in the field */ > >> > >> -static int get_uint8_equal(QEMUFile *f, void *pv, size_t size) > >> +static int get_uint8_equal(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field) > >> { > >> uint8_t *v = pv; > >> uint8_t v2; > >> @@ -758,7 +771,8 @@ const VMStateInfo vmstate_info_uint8_equal = { > >> /* 16 bit unsigned int int. See that the received value is the same than the one > >> in the field */ > >> > >> -static int get_uint16_equal(QEMUFile *f, void *pv, size_t size) > >> +static int get_uint16_equal(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field) > >> { > >> uint16_t *v = pv; > >> uint16_t v2; > >> @@ -778,7 +792,8 @@ const VMStateInfo vmstate_info_uint16_equal = { > >> > >> /* floating point */ > >> > >> -static int get_float64(QEMUFile *f, void *pv, size_t size) > >> +static int get_float64(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field) > >> { > >> float64 *v = pv; > >> > >> @@ -786,7 +801,8 @@ static int get_float64(QEMUFile *f, void *pv, size_t size) > >> return 0; > >> } > >> > >> -static void put_float64(QEMUFile *f, void *pv, size_t size) > >> +static void put_float64(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> uint64_t *v = pv; > >> > >> @@ -801,7 +817,8 @@ const VMStateInfo vmstate_info_float64 = { > >> > >> /* CPU_DoubleU type */ > >> > >> -static int get_cpudouble(QEMUFile *f, void *pv, size_t size) > >> +static int get_cpudouble(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field) > >> { > >> CPU_DoubleU *v = pv; > >> qemu_get_be32s(f, &v->l.upper); > >> @@ -809,7 +826,8 @@ static int get_cpudouble(QEMUFile *f, void *pv, size_t size) > >> return 0; > >> } > >> > >> -static void put_cpudouble(QEMUFile *f, void *pv, size_t size) > >> +static void put_cpudouble(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field, QJSON *vmdesc) > >> { > >> CPU_DoubleU *v = pv; > >> qemu_put_be32s(f, &v->l.upper); > >> @@ -824,14 +842,16 @@ const VMStateInfo vmstate_info_cpudouble = { > >> > >> /* uint8_t buffers */ > >> > >> -static int get_buffer(QEMUFile *f, void *pv, size_t size) > >> +static int get_buffer(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field) > >> { > >> uint8_t *v = pv; > >> qemu_get_buffer(f, v, size); > >> return 0; > >> } > >> > >> -static void put_buffer(QEMUFile *f, void *pv, size_t size) > >> +static void put_buffer(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> uint8_t *v = pv; > >> qemu_put_buffer(f, v, size); > >> @@ -846,7 +866,8 @@ const VMStateInfo vmstate_info_buffer = { > >> /* unused buffers: space that was used for some fields that are > >> not useful anymore */ > >> > >> -static int get_unused_buffer(QEMUFile *f, void *pv, size_t size) > >> +static int get_unused_buffer(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field) > >> { > >> uint8_t buf[1024]; > >> int block_len; > >> @@ -859,7 +880,8 @@ static int get_unused_buffer(QEMUFile *f, void *pv, size_t size) > >> return 0; > >> } > >> > >> -static void put_unused_buffer(QEMUFile *f, void *pv, size_t size) > >> +static void put_unused_buffer(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field, QJSON *vmdesc) > >> { > >> static const uint8_t buf[1024]; > >> int block_len; > >> @@ -884,7 +906,7 @@ const VMStateInfo vmstate_info_unused_buffer = { > >> */ > >> /* This is the number of 64 bit words sent over the wire */ > >> #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64) > >> -static int get_bitmap(QEMUFile *f, void *pv, size_t size) > >> +static int get_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field) > >> { > >> unsigned long *bmp = pv; > >> int i, idx = 0; > >> @@ -898,7 +920,8 @@ static int get_bitmap(QEMUFile *f, void *pv, size_t size) > >> return 0; > >> } > >> > >> -static void put_bitmap(QEMUFile *f, void *pv, size_t size) > >> +static void put_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> unsigned long *bmp = pv; > >> int i, idx = 0; > >> diff --git a/target-alpha/machine.c b/target-alpha/machine.c > >> index 710b783..48e3278 100644 > >> --- a/target-alpha/machine.c > >> +++ b/target-alpha/machine.c > >> @@ -5,14 +5,15 @@ > >> #include "hw/boards.h" > >> #include "migration/cpu.h" > >> > >> -static int get_fpcr(QEMUFile *f, void *opaque, size_t size) > >> +static int get_fpcr(QEMUFile *f, void *opaque, size_t size, VMStateField *field) > >> { > >> CPUAlphaState *env = opaque; > >> cpu_alpha_store_fpcr(env, qemu_get_be64(f)); > >> return 0; > >> } > >> > >> -static void put_fpcr(QEMUFile *f, void *opaque, size_t size) > >> +static void put_fpcr(QEMUFile *f, void *opaque, size_t size, > >> + VMStateField *field, QJSON *vmdesc) > >> { > >> CPUAlphaState *env = opaque; > >> qemu_put_be64(f, cpu_alpha_load_fpcr(env)); > >> diff --git a/target-arm/machine.c b/target-arm/machine.c > >> index 7a6ca31..41a0de9 100644 > >> --- a/target-arm/machine.c > >> +++ b/target-arm/machine.c > >> @@ -17,7 +17,8 @@ static bool vfp_needed(void *opaque) > >> return arm_feature(env, ARM_FEATURE_VFP); > >> } > >> > >> -static int get_fpscr(QEMUFile *f, void *opaque, size_t size) > >> +static int get_fpscr(QEMUFile *f, void *opaque, size_t size, > >> + VMStateField *field) > >> { > >> ARMCPU *cpu = opaque; > >> CPUARMState *env = &cpu->env; > >> @@ -27,7 +28,8 @@ static int get_fpscr(QEMUFile *f, void *opaque, size_t size) > >> return 0; > >> } > >> > >> -static void put_fpscr(QEMUFile *f, void *opaque, size_t size) > >> +static void put_fpscr(QEMUFile *f, void *opaque, size_t size, > >> + VMStateField *field, QJSON *vmdesc) > >> { > >> ARMCPU *cpu = opaque; > >> CPUARMState *env = &cpu->env; > >> @@ -163,7 +165,8 @@ static const VMStateDescription vmstate_pmsav7 = { > >> } > >> }; > >> > >> -static int get_cpsr(QEMUFile *f, void *opaque, size_t size) > >> +static int get_cpsr(QEMUFile *f, void *opaque, size_t size, > >> + VMStateField *field) > >> { > >> ARMCPU *cpu = opaque; > >> CPUARMState *env = &cpu->env; > >> @@ -180,7 +183,8 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size) > >> return 0; > >> } > >> > >> -static void put_cpsr(QEMUFile *f, void *opaque, size_t size) > >> +static void put_cpsr(QEMUFile *f, void *opaque, size_t size, > >> + VMStateField *field, QJSON *vmdesc) > >> { > >> ARMCPU *cpu = opaque; > >> CPUARMState *env = &cpu->env; > >> diff --git a/target-i386/machine.c b/target-i386/machine.c > >> index 71c0e4d..1df19e2 100644 > >> --- a/target-i386/machine.c > >> +++ b/target-i386/machine.c > >> @@ -139,7 +139,8 @@ static const VMStateDescription vmstate_mtrr_var = { > >> #define VMSTATE_MTRR_VARS(_field, _state, _n, _v) \ > >> VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar) > >> > >> -static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size) > >> +static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size, > >> + VMStateField *field, QJSON *vmdesc) > >> { > >> fprintf(stderr, "call put_fpreg() with invalid arguments\n"); > >> exit(0); > >> @@ -167,7 +168,8 @@ static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp) > >> p->exp = e; > >> } > >> > >> -static int get_fpreg(QEMUFile *f, void *opaque, size_t size) > >> +static int get_fpreg(QEMUFile *f, void *opaque, size_t size, > >> + VMStateField *field) > >> { > >> FPReg *fp_reg = opaque; > >> uint64_t mant; > >> @@ -179,7 +181,8 @@ static int get_fpreg(QEMUFile *f, void *opaque, size_t size) > >> return 0; > >> } > >> > >> -static void put_fpreg(QEMUFile *f, void *opaque, size_t size) > >> +static void put_fpreg(QEMUFile *f, void *opaque, size_t size, > >> + VMStateField *field, QJSON *vmdesc) > >> { > >> FPReg *fp_reg = opaque; > >> uint64_t mant; > >> @@ -197,7 +200,8 @@ static const VMStateInfo vmstate_fpreg = { > >> .put = put_fpreg, > >> }; > >> > >> -static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size) > >> +static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size, > >> + VMStateField *field) > >> { > >> union x86_longdouble *p = opaque; > >> uint64_t mant; > >> @@ -214,7 +218,8 @@ static const VMStateInfo vmstate_fpreg_1_mmx = { > >> .put = put_fpreg_error, > >> }; > >> > >> -static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size) > >> +static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size, > >> + VMStateField *field) > >> { > >> union x86_longdouble *p = opaque; > >> uint64_t mant; > >> @@ -276,14 +281,16 @@ static bool less_than_7(void *opaque, int version_id) > >> return version_id < 7; > >> } > >> > >> -static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size) > >> +static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field) > >> { > >> uint64_t *v = pv; > >> *v = qemu_get_be32(f); > >> return 0; > >> } > >> > >> -static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size) > >> +static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size, > >> + VMStateField *field, QJSON *vmdesc) > >> { > >> uint64_t *v = pv; > >> qemu_put_be32(f, *v); > >> diff --git a/target-mips/machine.c b/target-mips/machine.c > >> index a27f2f1..179084c 100644 > >> --- a/target-mips/machine.c > >> +++ b/target-mips/machine.c > >> @@ -20,7 +20,7 @@ static int cpu_post_load(void *opaque, int version_id) > >> > >> /* FPU state */ > >> > >> -static int get_fpr(QEMUFile *f, void *pv, size_t size) > >> +static int get_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field) > >> { > >> int i; > >> fpr_t *v = pv; > >> @@ -31,7 +31,8 @@ static int get_fpr(QEMUFile *f, void *pv, size_t size) > >> return 0; > >> } > >> > >> -static void put_fpr(QEMUFile *f, void *pv, size_t size) > >> +static void put_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> int i; > >> fpr_t *v = pv; > >> @@ -125,7 +126,7 @@ const VMStateDescription vmstate_mvp = { > >> > >> /* TLB state */ > >> > >> -static int get_tlb(QEMUFile *f, void *pv, size_t size) > >> +static int get_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field) > >> { > >> r4k_tlb_t *v = pv; > >> uint16_t flags; > >> @@ -152,7 +153,8 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size) > >> return 0; > >> } > >> > >> -static void put_tlb(QEMUFile *f, void *pv, size_t size) > >> +static void put_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> r4k_tlb_t *v = pv; > >> > >> diff --git a/target-ppc/machine.c b/target-ppc/machine.c > >> index 4820f22..0e1822c 100644 > >> --- a/target-ppc/machine.c > >> +++ b/target-ppc/machine.c > >> @@ -106,7 +106,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id) > >> return 0; > >> } > >> > >> -static int get_avr(QEMUFile *f, void *pv, size_t size) > >> +static int get_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field) > >> { > >> ppc_avr_t *v = pv; > >> > >> @@ -116,7 +116,8 @@ static int get_avr(QEMUFile *f, void *pv, size_t size) > >> return 0; > >> } > >> > >> -static void put_avr(QEMUFile *f, void *pv, size_t size) > >> +static void put_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> ppc_avr_t *v = pv; > >> > >> @@ -324,7 +325,7 @@ static const VMStateDescription vmstate_sr = { > >> }; > >> > >> #ifdef TARGET_PPC64 > >> -static int get_slbe(QEMUFile *f, void *pv, size_t size) > >> +static int get_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field) > >> { > >> ppc_slb_t *v = pv; > >> > >> @@ -334,7 +335,8 @@ static int get_slbe(QEMUFile *f, void *pv, size_t size) > >> return 0; > >> } > >> > >> -static void put_slbe(QEMUFile *f, void *pv, size_t size) > >> +static void put_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> ppc_slb_t *v = pv; > >> > >> diff --git a/target-sparc/machine.c b/target-sparc/machine.c > >> index 59c92f7..3194e03 100644 > >> --- a/target-sparc/machine.c > >> +++ b/target-sparc/machine.c > >> @@ -59,7 +59,7 @@ static const VMStateDescription vmstate_tlb_entry = { > >> }; > >> #endif > >> > >> -static int get_psr(QEMUFile *f, void *opaque, size_t size) > >> +static int get_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field) > >> { > >> SPARCCPU *cpu = opaque; > >> CPUSPARCState *env = &cpu->env; > >> @@ -72,7 +72,8 @@ static int get_psr(QEMUFile *f, void *opaque, size_t size) > >> return 0; > >> } > >> > >> -static void put_psr(QEMUFile *f, void *opaque, size_t size) > >> +static void put_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field, > >> + QJSON *vmdesc) > >> { > >> SPARCCPU *cpu = opaque; > >> CPUSPARCState *env = &cpu->env; > >> -- > >> 1.9.1 > >> > >> > > -- > > Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK > > > -- Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
On Fri, Oct 07, 2016 at 07:42:12PM +0100, Dr. David Alan Gilbert wrote: > * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote: > > > > > > On 10/07/2016 05:08 AM, Dr. David Alan Gilbert wrote: > > > * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote: > > >> Current migration code cannot handle some data structures such as > > >> QTAILQ in qemu/queue.h. Here we extend the signatures of put/get > > >> in VMStateInfo so that customized handling is supported. > > >> > > >> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com> > > >> --- > > >> hw/net/vmxnet3.c | 18 ++++++--- > > >> hw/nvram/eeprom93xx.c | 6 ++- > > >> hw/nvram/fw_cfg.c | 6 ++- > > >> hw/pci/msix.c | 6 ++- > > >> hw/pci/pci.c | 12 ++++-- > > >> hw/pci/shpc.c | 5 ++- > > >> hw/scsi/scsi-bus.c | 6 ++- > > >> hw/timer/twl92230.c | 6 ++- > > >> hw/usb/redirect.c | 18 ++++++--- > > >> hw/virtio/virtio-pci.c | 6 ++- > > >> hw/virtio/virtio.c | 6 ++- > > >> include/migration/vmstate.h | 10 +++-- > > >> migration/savevm.c | 5 ++- > > >> migration/vmstate.c | 95 ++++++++++++++++++++++++++++----------------- > > >> target-alpha/machine.c | 5 ++- > > >> target-arm/machine.c | 12 ++++-- > > >> target-i386/machine.c | 21 ++++++---- > > >> target-mips/machine.c | 10 +++-- > > >> target-ppc/machine.c | 10 +++-- > > >> target-sparc/machine.c | 5 ++- > > >> 20 files changed, 171 insertions(+), 97 deletions(-) > > >> > > > > > > <snip> > > > > > >> diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c > > >> index 444672a..2ca4b46 100644 > > >> --- a/hw/usb/redirect.c > > >> +++ b/hw/usb/redirect.c > > >> @@ -2154,7 +2154,8 @@ static int usbredir_post_load(void *priv, int version_id) > > >> } > > >> > > >> /* For usbredirparser migration */ > > >> -static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused) > > >> +static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused, > > >> + void *opaque, QJSON *vmdesc) > > >> { > > >> USBRedirDevice *dev = priv; > > >> uint8_t *data; > > >> @@ -2174,7 +2175,8 @@ static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused) > > >> free(data); > > >> } > > >> > > >> -static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused) > > >> +static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused, > > >> + void *opaque) > > > > > > Neither of these built for me; I had to change those to VMStateField rather than void *; > > > > > > also is this series tested ontop of Halil's patches - because without them > > > I'm finding I also had to fix up most of the other virtio devices. > > > > > > Dave > > > > I built it on top of ppc-for-2.8 without problems. Is Hail's patch in > > ppc-for-2.8 yet? If it's not in master, and not ppc specific, it won't be in ppc-for-2.8. > I don't know about ppc-for-2.8; patches for inclusion should work on the current > head unless stated otherwise. Right. These started as ppc specific patches, for which being on top of ppc-for-2.8 would be the right choice (ppc-for-2.8 regularly rebases on master). However, they now include a bunch of generic migration changes, it should be done directly against master. This may require splitting the series into generic and ppc specific portions. > Also, make sure you have the usbredir libraries installed and as much else as possible > to make sure you cover all the .get/.put functions - they're all over! > > Dave > > > Thanks, > > Jianjun > > > > > > > > > > >> USBRedirDevice *dev = priv; > > >> uint8_t *data; > > >> @@ -2217,7 +2219,8 @@ static const VMStateInfo usbredir_parser_vmstate_info = { > > >> > > >> > > >> /* For buffered packets (iso/irq) queue migration */ > > >> -static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused) > > >> +static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused, > > >> + VMStateField *field, QJSON *vmdesc) > > >> { > > >> struct endp_data *endp = priv; > > >> USBRedirDevice *dev = endp->dev; > > >> @@ -2237,7 +2240,8 @@ static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused) > > >> assert(i == endp->bufpq_size); > > >> } > > >> > > >> -static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused) > > >> +static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused, > > >> + VMStateField *field) > > >> { > > >> struct endp_data *endp = priv; > > >> USBRedirDevice *dev = endp->dev; > > >> @@ -2340,7 +2344,8 @@ static const VMStateDescription usbredir_ep_vmstate = { > > >> > > >> > > >> /* For PacketIdQueue migration */ > > >> -static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused) > > >> +static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused, > > >> + VMStateField *field, QJSON *vmdesc) > > >> { > > >> struct PacketIdQueue *q = priv; > > >> USBRedirDevice *dev = q->dev; > > >> @@ -2356,7 +2361,8 @@ static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused) > > >> assert(remain == 0); > > >> } > > >> > > >> -static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused) > > >> +static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused, > > >> + VMStateField *field) > > >> { > > >> struct PacketIdQueue *q = priv; > > >> USBRedirDevice *dev = q->dev; > > >> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c > > >> index 2d60a00..38a7abd 100644 > > >> --- a/hw/virtio/virtio-pci.c > > >> +++ b/hw/virtio/virtio-pci.c > > >> @@ -108,7 +108,8 @@ static bool virtio_pci_has_extra_state(DeviceState *d) > > >> return proxy->flags & VIRTIO_PCI_FLAG_MIGRATE_EXTRA; > > >> } > > >> > > >> -static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size) > > >> +static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field) > > >> { > > >> VirtIOPCIProxy *proxy = pv; > > >> int i; > > >> @@ -137,7 +138,8 @@ static void virtio_pci_save_modern_queue_state(VirtIOPCIQueue *vq, > > >> qemu_put_be32(f, vq->used[1]); > > >> } > > >> > > >> -static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size) > > >> +static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field, QJSON *vmdesc) > > >> { > > >> VirtIOPCIProxy *proxy = pv; > > >> int i; > > >> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c > > >> index 18ce333..ade2683 100644 > > >> --- a/hw/virtio/virtio.c > > >> +++ b/hw/virtio/virtio.c > > >> @@ -1467,7 +1467,8 @@ static const VMStateDescription vmstate_virtio_ringsize = { > > >> } > > >> }; > > >> > > >> -static int get_extra_state(QEMUFile *f, void *pv, size_t size) > > >> +static int get_extra_state(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field) > > >> { > > >> VirtIODevice *vdev = pv; > > >> BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); > > >> @@ -1480,7 +1481,8 @@ static int get_extra_state(QEMUFile *f, void *pv, size_t size) > > >> } > > >> } > > >> > > >> -static void put_extra_state(QEMUFile *f, void *pv, size_t size) > > >> +static void put_extra_state(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field, QJSON *vmdesc) > > >> { > > >> VirtIODevice *vdev = pv; > > >> BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); > > >> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h > > >> index 1638ee5..459dd4a 100644 > > >> --- a/include/migration/vmstate.h > > >> +++ b/include/migration/vmstate.h > > >> @@ -81,11 +81,13 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque); > > >> > > >> typedef struct VMStateInfo VMStateInfo; > > >> typedef struct VMStateDescription VMStateDescription; > > >> +typedef struct VMStateField VMStateField; > > >> > > >> struct VMStateInfo { > > >> const char *name; > > >> - int (*get)(QEMUFile *f, void *pv, size_t size); > > >> - void (*put)(QEMUFile *f, void *pv, size_t size); > > >> + int (*get)(QEMUFile *f, void *pv, size_t size, VMStateField *field); > > >> + void (*put)(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc); > > >> }; > > >> > > >> enum VMStateFlags { > > >> @@ -186,7 +188,7 @@ enum VMStateFlags { > > >> VMS_MULTIPLY_ELEMENTS = 0x4000, > > >> }; > > >> > > >> -typedef struct { > > >> +struct VMStateField { > > >> const char *name; > > >> size_t offset; > > >> size_t size; > > >> @@ -199,7 +201,7 @@ typedef struct { > > >> const VMStateDescription *vmsd; > > >> int version_id; > > >> bool (*field_exists)(void *opaque, int version_id); > > >> -} VMStateField; > > >> +}; > > >> > > >> struct VMStateDescription { > > >> const char *name; > > >> diff --git a/migration/savevm.c b/migration/savevm.c > > >> index ef5c3d1..13b53ad 100644 > > >> --- a/migration/savevm.c > > >> +++ b/migration/savevm.c > > >> @@ -220,14 +220,15 @@ void timer_get(QEMUFile *f, QEMUTimer *ts) > > >> * Not in vmstate.c to not add qemu-timer.c as dependency to vmstate.c > > >> */ > > >> > > >> -static int get_timer(QEMUFile *f, void *pv, size_t size) > > >> +static int get_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field) > > >> { > > >> QEMUTimer *v = pv; > > >> timer_get(f, v); > > >> return 0; > > >> } > > >> > > >> -static void put_timer(QEMUFile *f, void *pv, size_t size) > > >> +static void put_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> QEMUTimer *v = pv; > > >> timer_put(f, v); > > >> diff --git a/migration/vmstate.c b/migration/vmstate.c > > >> index fc29acf..66802cb 100644 > > >> --- a/migration/vmstate.c > > >> +++ b/migration/vmstate.c > > >> @@ -122,7 +122,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, > > >> ret = vmstate_load_state(f, field->vmsd, addr, > > >> field->vmsd->version_id); > > >> } else { > > >> - ret = field->info->get(f, addr, size); > > >> + ret = field->info->get(f, addr, size, NULL); > > >> > > >> } > > >> if (ret >= 0) { > > >> @@ -328,7 +328,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, > > >> if (field->flags & VMS_STRUCT) { > > >> vmstate_save_state(f, field->vmsd, addr, vmdesc_loop); > > >> } else { > > >> - field->info->put(f, addr, size); > > >> + field->info->put(f, addr, size, NULL, NULL); > > >> } > > >> > > >> written_bytes = qemu_ftell_fast(f) - old_offset; > > >> @@ -461,14 +461,15 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, > > >> > > >> /* bool */ > > >> > > >> -static int get_bool(QEMUFile *f, void *pv, size_t size) > > >> +static int get_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field) > > >> { > > >> bool *v = pv; > > >> *v = qemu_get_byte(f); > > >> return 0; > > >> } > > >> > > >> -static void put_bool(QEMUFile *f, void *pv, size_t size) > > >> +static void put_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> bool *v = pv; > > >> qemu_put_byte(f, *v); > > >> @@ -482,14 +483,15 @@ const VMStateInfo vmstate_info_bool = { > > >> > > >> /* 8 bit int */ > > >> > > >> -static int get_int8(QEMUFile *f, void *pv, size_t size) > > >> +static int get_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field) > > >> { > > >> int8_t *v = pv; > > >> qemu_get_s8s(f, v); > > >> return 0; > > >> } > > >> > > >> -static void put_int8(QEMUFile *f, void *pv, size_t size) > > >> +static void put_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> int8_t *v = pv; > > >> qemu_put_s8s(f, v); > > >> @@ -503,14 +505,15 @@ const VMStateInfo vmstate_info_int8 = { > > >> > > >> /* 16 bit int */ > > >> > > >> -static int get_int16(QEMUFile *f, void *pv, size_t size) > > >> +static int get_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field) > > >> { > > >> int16_t *v = pv; > > >> qemu_get_sbe16s(f, v); > > >> return 0; > > >> } > > >> > > >> -static void put_int16(QEMUFile *f, void *pv, size_t size) > > >> +static void put_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> int16_t *v = pv; > > >> qemu_put_sbe16s(f, v); > > >> @@ -524,14 +527,15 @@ const VMStateInfo vmstate_info_int16 = { > > >> > > >> /* 32 bit int */ > > >> > > >> -static int get_int32(QEMUFile *f, void *pv, size_t size) > > >> +static int get_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field) > > >> { > > >> int32_t *v = pv; > > >> qemu_get_sbe32s(f, v); > > >> return 0; > > >> } > > >> > > >> -static void put_int32(QEMUFile *f, void *pv, size_t size) > > >> +static void put_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> int32_t *v = pv; > > >> qemu_put_sbe32s(f, v); > > >> @@ -546,7 +550,8 @@ const VMStateInfo vmstate_info_int32 = { > > >> /* 32 bit int. See that the received value is the same than the one > > >> in the field */ > > >> > > >> -static int get_int32_equal(QEMUFile *f, void *pv, size_t size) > > >> +static int get_int32_equal(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field) > > >> { > > >> int32_t *v = pv; > > >> int32_t v2; > > >> @@ -568,7 +573,7 @@ const VMStateInfo vmstate_info_int32_equal = { > > >> * and less than or equal to the one in the field. > > >> */ > > >> > > >> -static int get_int32_le(QEMUFile *f, void *pv, size_t size) > > >> +static int get_int32_le(QEMUFile *f, void *pv, size_t size, VMStateField *field) > > >> { > > >> int32_t *cur = pv; > > >> int32_t loaded; > > >> @@ -589,14 +594,15 @@ const VMStateInfo vmstate_info_int32_le = { > > >> > > >> /* 64 bit int */ > > >> > > >> -static int get_int64(QEMUFile *f, void *pv, size_t size) > > >> +static int get_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field) > > >> { > > >> int64_t *v = pv; > > >> qemu_get_sbe64s(f, v); > > >> return 0; > > >> } > > >> > > >> -static void put_int64(QEMUFile *f, void *pv, size_t size) > > >> +static void put_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> int64_t *v = pv; > > >> qemu_put_sbe64s(f, v); > > >> @@ -610,14 +616,15 @@ const VMStateInfo vmstate_info_int64 = { > > >> > > >> /* 8 bit unsigned int */ > > >> > > >> -static int get_uint8(QEMUFile *f, void *pv, size_t size) > > >> +static int get_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field) > > >> { > > >> uint8_t *v = pv; > > >> qemu_get_8s(f, v); > > >> return 0; > > >> } > > >> > > >> -static void put_uint8(QEMUFile *f, void *pv, size_t size) > > >> +static void put_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> uint8_t *v = pv; > > >> qemu_put_8s(f, v); > > >> @@ -631,14 +638,15 @@ const VMStateInfo vmstate_info_uint8 = { > > >> > > >> /* 16 bit unsigned int */ > > >> > > >> -static int get_uint16(QEMUFile *f, void *pv, size_t size) > > >> +static int get_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field) > > >> { > > >> uint16_t *v = pv; > > >> qemu_get_be16s(f, v); > > >> return 0; > > >> } > > >> > > >> -static void put_uint16(QEMUFile *f, void *pv, size_t size) > > >> +static void put_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> uint16_t *v = pv; > > >> qemu_put_be16s(f, v); > > >> @@ -652,14 +660,15 @@ const VMStateInfo vmstate_info_uint16 = { > > >> > > >> /* 32 bit unsigned int */ > > >> > > >> -static int get_uint32(QEMUFile *f, void *pv, size_t size) > > >> +static int get_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field) > > >> { > > >> uint32_t *v = pv; > > >> qemu_get_be32s(f, v); > > >> return 0; > > >> } > > >> > > >> -static void put_uint32(QEMUFile *f, void *pv, size_t size) > > >> +static void put_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> uint32_t *v = pv; > > >> qemu_put_be32s(f, v); > > >> @@ -674,7 +683,8 @@ const VMStateInfo vmstate_info_uint32 = { > > >> /* 32 bit uint. See that the received value is the same than the one > > >> in the field */ > > >> > > >> -static int get_uint32_equal(QEMUFile *f, void *pv, size_t size) > > >> +static int get_uint32_equal(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field) > > >> { > > >> uint32_t *v = pv; > > >> uint32_t v2; > > >> @@ -694,14 +704,15 @@ const VMStateInfo vmstate_info_uint32_equal = { > > >> > > >> /* 64 bit unsigned int */ > > >> > > >> -static int get_uint64(QEMUFile *f, void *pv, size_t size) > > >> +static int get_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field) > > >> { > > >> uint64_t *v = pv; > > >> qemu_get_be64s(f, v); > > >> return 0; > > >> } > > >> > > >> -static void put_uint64(QEMUFile *f, void *pv, size_t size) > > >> +static void put_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> uint64_t *v = pv; > > >> qemu_put_be64s(f, v); > > >> @@ -716,7 +727,8 @@ const VMStateInfo vmstate_info_uint64 = { > > >> /* 64 bit unsigned int. See that the received value is the same than the one > > >> in the field */ > > >> > > >> -static int get_uint64_equal(QEMUFile *f, void *pv, size_t size) > > >> +static int get_uint64_equal(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field) > > >> { > > >> uint64_t *v = pv; > > >> uint64_t v2; > > >> @@ -737,7 +749,8 @@ const VMStateInfo vmstate_info_uint64_equal = { > > >> /* 8 bit int. See that the received value is the same than the one > > >> in the field */ > > >> > > >> -static int get_uint8_equal(QEMUFile *f, void *pv, size_t size) > > >> +static int get_uint8_equal(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field) > > >> { > > >> uint8_t *v = pv; > > >> uint8_t v2; > > >> @@ -758,7 +771,8 @@ const VMStateInfo vmstate_info_uint8_equal = { > > >> /* 16 bit unsigned int int. See that the received value is the same than the one > > >> in the field */ > > >> > > >> -static int get_uint16_equal(QEMUFile *f, void *pv, size_t size) > > >> +static int get_uint16_equal(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field) > > >> { > > >> uint16_t *v = pv; > > >> uint16_t v2; > > >> @@ -778,7 +792,8 @@ const VMStateInfo vmstate_info_uint16_equal = { > > >> > > >> /* floating point */ > > >> > > >> -static int get_float64(QEMUFile *f, void *pv, size_t size) > > >> +static int get_float64(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field) > > >> { > > >> float64 *v = pv; > > >> > > >> @@ -786,7 +801,8 @@ static int get_float64(QEMUFile *f, void *pv, size_t size) > > >> return 0; > > >> } > > >> > > >> -static void put_float64(QEMUFile *f, void *pv, size_t size) > > >> +static void put_float64(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> uint64_t *v = pv; > > >> > > >> @@ -801,7 +817,8 @@ const VMStateInfo vmstate_info_float64 = { > > >> > > >> /* CPU_DoubleU type */ > > >> > > >> -static int get_cpudouble(QEMUFile *f, void *pv, size_t size) > > >> +static int get_cpudouble(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field) > > >> { > > >> CPU_DoubleU *v = pv; > > >> qemu_get_be32s(f, &v->l.upper); > > >> @@ -809,7 +826,8 @@ static int get_cpudouble(QEMUFile *f, void *pv, size_t size) > > >> return 0; > > >> } > > >> > > >> -static void put_cpudouble(QEMUFile *f, void *pv, size_t size) > > >> +static void put_cpudouble(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field, QJSON *vmdesc) > > >> { > > >> CPU_DoubleU *v = pv; > > >> qemu_put_be32s(f, &v->l.upper); > > >> @@ -824,14 +842,16 @@ const VMStateInfo vmstate_info_cpudouble = { > > >> > > >> /* uint8_t buffers */ > > >> > > >> -static int get_buffer(QEMUFile *f, void *pv, size_t size) > > >> +static int get_buffer(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field) > > >> { > > >> uint8_t *v = pv; > > >> qemu_get_buffer(f, v, size); > > >> return 0; > > >> } > > >> > > >> -static void put_buffer(QEMUFile *f, void *pv, size_t size) > > >> +static void put_buffer(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> uint8_t *v = pv; > > >> qemu_put_buffer(f, v, size); > > >> @@ -846,7 +866,8 @@ const VMStateInfo vmstate_info_buffer = { > > >> /* unused buffers: space that was used for some fields that are > > >> not useful anymore */ > > >> > > >> -static int get_unused_buffer(QEMUFile *f, void *pv, size_t size) > > >> +static int get_unused_buffer(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field) > > >> { > > >> uint8_t buf[1024]; > > >> int block_len; > > >> @@ -859,7 +880,8 @@ static int get_unused_buffer(QEMUFile *f, void *pv, size_t size) > > >> return 0; > > >> } > > >> > > >> -static void put_unused_buffer(QEMUFile *f, void *pv, size_t size) > > >> +static void put_unused_buffer(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field, QJSON *vmdesc) > > >> { > > >> static const uint8_t buf[1024]; > > >> int block_len; > > >> @@ -884,7 +906,7 @@ const VMStateInfo vmstate_info_unused_buffer = { > > >> */ > > >> /* This is the number of 64 bit words sent over the wire */ > > >> #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64) > > >> -static int get_bitmap(QEMUFile *f, void *pv, size_t size) > > >> +static int get_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field) > > >> { > > >> unsigned long *bmp = pv; > > >> int i, idx = 0; > > >> @@ -898,7 +920,8 @@ static int get_bitmap(QEMUFile *f, void *pv, size_t size) > > >> return 0; > > >> } > > >> > > >> -static void put_bitmap(QEMUFile *f, void *pv, size_t size) > > >> +static void put_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> unsigned long *bmp = pv; > > >> int i, idx = 0; > > >> diff --git a/target-alpha/machine.c b/target-alpha/machine.c > > >> index 710b783..48e3278 100644 > > >> --- a/target-alpha/machine.c > > >> +++ b/target-alpha/machine.c > > >> @@ -5,14 +5,15 @@ > > >> #include "hw/boards.h" > > >> #include "migration/cpu.h" > > >> > > >> -static int get_fpcr(QEMUFile *f, void *opaque, size_t size) > > >> +static int get_fpcr(QEMUFile *f, void *opaque, size_t size, VMStateField *field) > > >> { > > >> CPUAlphaState *env = opaque; > > >> cpu_alpha_store_fpcr(env, qemu_get_be64(f)); > > >> return 0; > > >> } > > >> > > >> -static void put_fpcr(QEMUFile *f, void *opaque, size_t size) > > >> +static void put_fpcr(QEMUFile *f, void *opaque, size_t size, > > >> + VMStateField *field, QJSON *vmdesc) > > >> { > > >> CPUAlphaState *env = opaque; > > >> qemu_put_be64(f, cpu_alpha_load_fpcr(env)); > > >> diff --git a/target-arm/machine.c b/target-arm/machine.c > > >> index 7a6ca31..41a0de9 100644 > > >> --- a/target-arm/machine.c > > >> +++ b/target-arm/machine.c > > >> @@ -17,7 +17,8 @@ static bool vfp_needed(void *opaque) > > >> return arm_feature(env, ARM_FEATURE_VFP); > > >> } > > >> > > >> -static int get_fpscr(QEMUFile *f, void *opaque, size_t size) > > >> +static int get_fpscr(QEMUFile *f, void *opaque, size_t size, > > >> + VMStateField *field) > > >> { > > >> ARMCPU *cpu = opaque; > > >> CPUARMState *env = &cpu->env; > > >> @@ -27,7 +28,8 @@ static int get_fpscr(QEMUFile *f, void *opaque, size_t size) > > >> return 0; > > >> } > > >> > > >> -static void put_fpscr(QEMUFile *f, void *opaque, size_t size) > > >> +static void put_fpscr(QEMUFile *f, void *opaque, size_t size, > > >> + VMStateField *field, QJSON *vmdesc) > > >> { > > >> ARMCPU *cpu = opaque; > > >> CPUARMState *env = &cpu->env; > > >> @@ -163,7 +165,8 @@ static const VMStateDescription vmstate_pmsav7 = { > > >> } > > >> }; > > >> > > >> -static int get_cpsr(QEMUFile *f, void *opaque, size_t size) > > >> +static int get_cpsr(QEMUFile *f, void *opaque, size_t size, > > >> + VMStateField *field) > > >> { > > >> ARMCPU *cpu = opaque; > > >> CPUARMState *env = &cpu->env; > > >> @@ -180,7 +183,8 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size) > > >> return 0; > > >> } > > >> > > >> -static void put_cpsr(QEMUFile *f, void *opaque, size_t size) > > >> +static void put_cpsr(QEMUFile *f, void *opaque, size_t size, > > >> + VMStateField *field, QJSON *vmdesc) > > >> { > > >> ARMCPU *cpu = opaque; > > >> CPUARMState *env = &cpu->env; > > >> diff --git a/target-i386/machine.c b/target-i386/machine.c > > >> index 71c0e4d..1df19e2 100644 > > >> --- a/target-i386/machine.c > > >> +++ b/target-i386/machine.c > > >> @@ -139,7 +139,8 @@ static const VMStateDescription vmstate_mtrr_var = { > > >> #define VMSTATE_MTRR_VARS(_field, _state, _n, _v) \ > > >> VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar) > > >> > > >> -static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size) > > >> +static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size, > > >> + VMStateField *field, QJSON *vmdesc) > > >> { > > >> fprintf(stderr, "call put_fpreg() with invalid arguments\n"); > > >> exit(0); > > >> @@ -167,7 +168,8 @@ static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp) > > >> p->exp = e; > > >> } > > >> > > >> -static int get_fpreg(QEMUFile *f, void *opaque, size_t size) > > >> +static int get_fpreg(QEMUFile *f, void *opaque, size_t size, > > >> + VMStateField *field) > > >> { > > >> FPReg *fp_reg = opaque; > > >> uint64_t mant; > > >> @@ -179,7 +181,8 @@ static int get_fpreg(QEMUFile *f, void *opaque, size_t size) > > >> return 0; > > >> } > > >> > > >> -static void put_fpreg(QEMUFile *f, void *opaque, size_t size) > > >> +static void put_fpreg(QEMUFile *f, void *opaque, size_t size, > > >> + VMStateField *field, QJSON *vmdesc) > > >> { > > >> FPReg *fp_reg = opaque; > > >> uint64_t mant; > > >> @@ -197,7 +200,8 @@ static const VMStateInfo vmstate_fpreg = { > > >> .put = put_fpreg, > > >> }; > > >> > > >> -static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size) > > >> +static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size, > > >> + VMStateField *field) > > >> { > > >> union x86_longdouble *p = opaque; > > >> uint64_t mant; > > >> @@ -214,7 +218,8 @@ static const VMStateInfo vmstate_fpreg_1_mmx = { > > >> .put = put_fpreg_error, > > >> }; > > >> > > >> -static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size) > > >> +static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size, > > >> + VMStateField *field) > > >> { > > >> union x86_longdouble *p = opaque; > > >> uint64_t mant; > > >> @@ -276,14 +281,16 @@ static bool less_than_7(void *opaque, int version_id) > > >> return version_id < 7; > > >> } > > >> > > >> -static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size) > > >> +static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field) > > >> { > > >> uint64_t *v = pv; > > >> *v = qemu_get_be32(f); > > >> return 0; > > >> } > > >> > > >> -static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size) > > >> +static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size, > > >> + VMStateField *field, QJSON *vmdesc) > > >> { > > >> uint64_t *v = pv; > > >> qemu_put_be32(f, *v); > > >> diff --git a/target-mips/machine.c b/target-mips/machine.c > > >> index a27f2f1..179084c 100644 > > >> --- a/target-mips/machine.c > > >> +++ b/target-mips/machine.c > > >> @@ -20,7 +20,7 @@ static int cpu_post_load(void *opaque, int version_id) > > >> > > >> /* FPU state */ > > >> > > >> -static int get_fpr(QEMUFile *f, void *pv, size_t size) > > >> +static int get_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field) > > >> { > > >> int i; > > >> fpr_t *v = pv; > > >> @@ -31,7 +31,8 @@ static int get_fpr(QEMUFile *f, void *pv, size_t size) > > >> return 0; > > >> } > > >> > > >> -static void put_fpr(QEMUFile *f, void *pv, size_t size) > > >> +static void put_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> int i; > > >> fpr_t *v = pv; > > >> @@ -125,7 +126,7 @@ const VMStateDescription vmstate_mvp = { > > >> > > >> /* TLB state */ > > >> > > >> -static int get_tlb(QEMUFile *f, void *pv, size_t size) > > >> +static int get_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field) > > >> { > > >> r4k_tlb_t *v = pv; > > >> uint16_t flags; > > >> @@ -152,7 +153,8 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size) > > >> return 0; > > >> } > > >> > > >> -static void put_tlb(QEMUFile *f, void *pv, size_t size) > > >> +static void put_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> r4k_tlb_t *v = pv; > > >> > > >> diff --git a/target-ppc/machine.c b/target-ppc/machine.c > > >> index 4820f22..0e1822c 100644 > > >> --- a/target-ppc/machine.c > > >> +++ b/target-ppc/machine.c > > >> @@ -106,7 +106,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id) > > >> return 0; > > >> } > > >> > > >> -static int get_avr(QEMUFile *f, void *pv, size_t size) > > >> +static int get_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field) > > >> { > > >> ppc_avr_t *v = pv; > > >> > > >> @@ -116,7 +116,8 @@ static int get_avr(QEMUFile *f, void *pv, size_t size) > > >> return 0; > > >> } > > >> > > >> -static void put_avr(QEMUFile *f, void *pv, size_t size) > > >> +static void put_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> ppc_avr_t *v = pv; > > >> > > >> @@ -324,7 +325,7 @@ static const VMStateDescription vmstate_sr = { > > >> }; > > >> > > >> #ifdef TARGET_PPC64 > > >> -static int get_slbe(QEMUFile *f, void *pv, size_t size) > > >> +static int get_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field) > > >> { > > >> ppc_slb_t *v = pv; > > >> > > >> @@ -334,7 +335,8 @@ static int get_slbe(QEMUFile *f, void *pv, size_t size) > > >> return 0; > > >> } > > >> > > >> -static void put_slbe(QEMUFile *f, void *pv, size_t size) > > >> +static void put_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> ppc_slb_t *v = pv; > > >> > > >> diff --git a/target-sparc/machine.c b/target-sparc/machine.c > > >> index 59c92f7..3194e03 100644 > > >> --- a/target-sparc/machine.c > > >> +++ b/target-sparc/machine.c > > >> @@ -59,7 +59,7 @@ static const VMStateDescription vmstate_tlb_entry = { > > >> }; > > >> #endif > > >> > > >> -static int get_psr(QEMUFile *f, void *opaque, size_t size) > > >> +static int get_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field) > > >> { > > >> SPARCCPU *cpu = opaque; > > >> CPUSPARCState *env = &cpu->env; > > >> @@ -72,7 +72,8 @@ static int get_psr(QEMUFile *f, void *opaque, size_t size) > > >> return 0; > > >> } > > >> > > >> -static void put_psr(QEMUFile *f, void *opaque, size_t size) > > >> +static void put_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field, > > >> + QJSON *vmdesc) > > >> { > > >> SPARCCPU *cpu = opaque; > > >> CPUSPARCState *env = &cpu->env; > > >> > > >> > >
On 10/03/2016 08:24 PM, Jianjun Duan wrote: > Current migration code cannot handle some data structures such as > QTAILQ in qemu/queue.h. Here we extend the signatures of put/get > in VMStateInfo so that customized handling is supported. > > Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com> > --- > hw/net/vmxnet3.c | 18 ++++++--- > hw/nvram/eeprom93xx.c | 6 ++- > hw/nvram/fw_cfg.c | 6 ++- > hw/pci/msix.c | 6 ++- > hw/pci/pci.c | 12 ++++-- > hw/pci/shpc.c | 5 ++- > hw/scsi/scsi-bus.c | 6 ++- > hw/timer/twl92230.c | 6 ++- > hw/usb/redirect.c | 18 ++++++--- > hw/virtio/virtio-pci.c | 6 ++- > hw/virtio/virtio.c | 6 ++- > include/migration/vmstate.h | 10 +++-- > migration/savevm.c | 5 ++- > migration/vmstate.c | 95 ++++++++++++++++++++++++++++----------------- > target-alpha/machine.c | 5 ++- > target-arm/machine.c | 12 ++++-- > target-i386/machine.c | 21 ++++++---- > target-mips/machine.c | 10 +++-- > target-ppc/machine.c | 10 +++-- > target-sparc/machine.c | 5 ++- > 20 files changed, 171 insertions(+), 97 deletions(-) Hi Jianjun! I'm not happy with the intrusive nature of this patch. We end up with a bunch of unused parameters. Have you considered something like: typedef struct { [..] union{ const VMStateInfo *info; const VMStateLinked *linked; }; enum VMStateFlags flags; [..] } VMStateField; /** * Handle linked datastructures. VMStateField.liked s to be used * in conjunction with VMStateField.vmsd which describes a node of * the datastucture without the pointers representing the links. * The links are embedded in the node starting at VMStateField.start. * The on wire representation of the information contained in links * and the head element if the responsibility of a particular VMStateField * instance. VMStateLinked is responsible for saving/loading the whole * sub-tree whose root is the field in question including the allocation of * memory for the nodes. The presence of VMStateField.linked is indicated * by the VMS_LINKED flag in VMStateField.flags. */ struct VMStateLinked { const char *name; void (*save)(QEMUFile *f, void *pv, VMStateField *field, QJSON *vmdesc); int (*load)(QEMUFile *f, void *pv, VMStateField *field); /* Maybe: size_t offset_links; */ }; IMHO this would: * allow us to keep the good old MVStateInfo objects unmodified and the semantic of VMStateInfo unchanged * make clear that VMStateLinked does not care about the calculated size and provide a new anchor for documentation * if overloading the semantic of VMStateField.start is not desired we could put it into VMStateLinked, if needed we could also put more stuff in there * have clearer separation between special handling for (linked/certain) data structures and the usual scenario with the DAG. I would also suggest unit tests in test/test-vmstate.c. Maybe with that the vmstate migration of QTAILQ could be factored out as a separate patch series. Cheers, Halil
On 12/10/2016 13:59, Halil Pasic wrote: > IMHO this would: > * allow us to keep the good old MVStateInfo objects unmodified and > the semantic of VMStateInfo unchanged > * make clear that VMStateLinked does not care about the calculated size > and provide a new anchor for documentation > * if overloading the semantic of VMStateField.start is not desired we > could put it into VMStateLinked, if needed we could also put more > stuff in there > * have clearer separation between special handling for (linked/certain) > data structures and the usual scenario with the DAG. No, I disagree. We shouldn't be worried about making intrusive changes to all invocations or declarations, if that leads to a simpler API. I agree that overloading .start can be a bit ugly but you can choose to overload .num_offset instead, which is already better. > I would also suggest unit tests in test/test-vmstate.c. Maybe with > that the vmstate migration of QTAILQ could be factored out as a separate > patch series. Yes, definitely. Paolo
On 10/12/2016 02:07 PM, Paolo Bonzini wrote: > > On 12/10/2016 13:59, Halil Pasic wrote: >> > IMHO this would: >> > * allow us to keep the good old MVStateInfo objects unmodified and >> > the semantic of VMStateInfo unchanged >> > * make clear that VMStateLinked does not care about the calculated size >> > and provide a new anchor for documentation >> > * if overloading the semantic of VMStateField.start is not desired we >> > could put it into VMStateLinked, if needed we could also put more >> > stuff in there >> > * have clearer separation between special handling for (linked/certain) >> > data structures and the usual scenario with the DAG. > No, I disagree. We shouldn't be worried about making intrusive changes > to all invocations or declarations, if that leads to a simpler API. Paolo I agree on a theoretical level. It's just I do not see why this particular change makes the API simpler. In my opinion this complicates things because now all VMStateInfo's can do funky stuff. Having additional state you can poke is rarely a simplification. Same goes for lots of arguments especially if some of them are barely ever used. These additional parameters contribute nothing for the large majority of the cases (except maybe some head scratching when reading the code). No strong opinion here, it's just that I don't understand. I think one trait of a simple API is that it is easy to document. Unfortunately the documentation is quite sparse and in the patch the signature change goes undocumented. Well as I said, just an idea, motivated by how I understood he role of VMStateInfo form reading the code. Cheers, Halil
* Halil Pasic (pasic@linux.vnet.ibm.com) wrote: > > > On 10/12/2016 02:07 PM, Paolo Bonzini wrote: > > > > On 12/10/2016 13:59, Halil Pasic wrote: > >> > IMHO this would: > >> > * allow us to keep the good old MVStateInfo objects unmodified and > >> > the semantic of VMStateInfo unchanged > >> > * make clear that VMStateLinked does not care about the calculated size > >> > and provide a new anchor for documentation > >> > * if overloading the semantic of VMStateField.start is not desired we > >> > could put it into VMStateLinked, if needed we could also put more > >> > stuff in there > >> > * have clearer separation between special handling for (linked/certain) > >> > data structures and the usual scenario with the DAG. > > No, I disagree. We shouldn't be worried about making intrusive changes > > to all invocations or declarations, if that leads to a simpler API. > > Paolo I agree on a theoretical level. It's just I do not see why this > particular change makes the API simpler. In my opinion this complicates > things because now all VMStateInfo's can do funky stuff. Having additional > state you can poke is rarely a simplification. Same goes for lots > of arguments especially if some of them are barely ever used. These > additional parameters contribute nothing for the large majority > of the cases (except maybe some head scratching when reading > the code). I think it might depend how many VMStateInfo's we have. My ideal rule would be there are no .get/.put implementations outside of migration/ and we can trust that they would never do anything silly (right?); so the extra parameters aren't going to be misused too badly. However, we're probably quite a way from pulling all of the weirder .get/.put implementations back in. Dave > No strong opinion here, it's just that I don't understand. I think one > trait of a simple API is that it is easy to document. Unfortunately > the documentation is quite sparse and in the patch the signature > change goes undocumented. > > Well as I said, just an idea, motivated by how I understood he role of > VMStateInfo form reading the code. > > Cheers, > Halil > -- Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
On 10/12/2016 05:07 AM, Paolo Bonzini wrote: > > > On 12/10/2016 13:59, Halil Pasic wrote: >> IMHO this would: >> * allow us to keep the good old MVStateInfo objects unmodified and >> the semantic of VMStateInfo unchanged >> * make clear that VMStateLinked does not care about the calculated size >> and provide a new anchor for documentation >> * if overloading the semantic of VMStateField.start is not desired we >> could put it into VMStateLinked, if needed we could also put more >> stuff in there >> * have clearer separation between special handling for (linked/certain) >> data structures and the usual scenario with the DAG. > > No, I disagree. We shouldn't be worried about making intrusive changes > to all invocations or declarations, if that leads to a simpler API. > If VMStateInfo was meant for complete customization, then it was missing some parts. I think the API is indeed simpler. Just like definition for VMStateField. Not all of its fields are used all time. > I agree that overloading .start can be a bit ugly but you can choose to > overload .num_offset instead, which is already better. > I did considered num_offset. But it is associated with an actual field. On the other hand, start means the start position of the q in the structure. So it is not that far stretched. >> I would also suggest unit tests in test/test-vmstate.c. Maybe with >> that the vmstate migration of QTAILQ could be factored out as a separate >> patch series. > > Yes, definitely. > This sounds a good idea. Will do it. > Paolo > Thanks, Jianjun
> > No, I disagree. We shouldn't be worried about making intrusive changes > > to all invocations or declarations, if that leads to a simpler API. > > If VMStateInfo was meant for complete customization, then it was missing > some parts. I think the API is indeed simpler. Just like > definition for VMStateField. Not all of its fields are used all time. Code moves. We can decide how much customization to allow of VMStateInfo. You said it: "Not all of its fields are used all time". Likewise, not all arguments are used all time for get/put, but it's not an issue if they are still there! So this patch is good, but at the same time VMS_LINKED is pointless. Paolo > > I agree that overloading .start can be a bit ugly but you can choose to > > overload .num_offset instead, which is already better. > > > I did considered num_offset. But it is associated with an actual field. > On the other hand, start means the start position of the q in the > structure. So it is not that far stretched. > > >> I would also suggest unit tests in test/test-vmstate.c. Maybe with > >> that the vmstate migration of QTAILQ could be factored out as a separate > >> patch series. > > > > Yes, definitely. > > > This sounds a good idea. Will do it. > > > Paolo > > > Thanks, > Jianjun > >
On 10/12/2016 04:59 PM, Dr. David Alan Gilbert wrote: >> Paolo I agree on a theoretical level. It's just I do not see why this >> > particular change makes the API simpler. In my opinion this complicates >> > things because now all VMStateInfo's can do funky stuff. Having additional >> > state you can poke is rarely a simplification. Same goes for lots >> > of arguments especially if some of them are barely ever used. These >> > additional parameters contribute nothing for the large majority >> > of the cases (except maybe some head scratching when reading >> > the code). > I think it might depend how many VMStateInfo's we have. > My ideal rule would be there are no .get/.put implementations outside > of migration/ and we can trust that they would never do anything silly (right?); Your statement about ideally no .get/.put implementations outside of migration/ is consistent with my initial understanding of VMStateInfo: It's there to take care of the marshaling between the on wire representation and the in memory representation of a single and preferably primitive vmstate field (not consisting of further fields). Complex stuff like arrays, structs, indirection via pointers and possibly allocation is preferably handled elsewhere. So VMStateInfo is the basic building stones, and the only place which should write to/read from the stream (in ideal vmstate). So in a perfect vmstate world complete type of VMStateInfo is not part of the API (you do not care about how it's done outside vmstate/), but only the (possibly pointers to) VMStateInfo's supported by the vmstate API. Of course this is not realistic, at least at the moment. On the other hand if VMStateInfo is meant for complete customization, as Jianjun has put it, then it obviously has to be a full fledged member of the API, and I think then your ideal rule makes no sense to me. I also do think we will always need something for handling special cases because we need to maintain compatibility -- see virtio migration for example. > so the extra parameters aren't going to be misused too badly. > What would you consider bad misuse? I do not see this as a big concern at the moment. Cheers, Halil > However, we're probably quite a way from pulling all of the weirder > .get/.put implementations back in. > > Dave >
On 10/13/2016 10:22 AM, Paolo Bonzini wrote: >>> No, I disagree. We shouldn't be worried about making intrusive changes >>> > > to all invocations or declarations, if that leads to a simpler API. >> > >> > If VMStateInfo was meant for complete customization, then it was missing >> > some parts. I think the API is indeed simpler. Just like >> > definition for VMStateField. Not all of its fields are used all time. > Code moves. We can decide how much customization to allow of VMStateInfo. > > You said it: "Not all of its fields are used all time". Likewise, not > all arguments are used all time for get/put, but it's not an issue if they > are still there! So this patch is good, but at the same time VMS_LINKED is > pointless. > > Paolo > I'm fine with this. I just think, it would be nice if the contract between the vmstate-core and the client code implementing VMStateInfo callbacks could be documented, including when are certain parameters valid, what they stand for, and how are they supposed to be used for the next version of the patch. Just to improve readability. Would this be OK with everybody? By the way the flag VMS_SINGLE is documented as ignored. Should we drop it?
* Halil Pasic (pasic@linux.vnet.ibm.com) wrote: > > > On 10/12/2016 04:59 PM, Dr. David Alan Gilbert wrote: > >> Paolo I agree on a theoretical level. It's just I do not see why this > >> > particular change makes the API simpler. In my opinion this complicates > >> > things because now all VMStateInfo's can do funky stuff. Having additional > >> > state you can poke is rarely a simplification. Same goes for lots > >> > of arguments especially if some of them are barely ever used. These > >> > additional parameters contribute nothing for the large majority > >> > of the cases (except maybe some head scratching when reading > >> > the code). > > I think it might depend how many VMStateInfo's we have. > > My ideal rule would be there are no .get/.put implementations outside > > of migration/ and we can trust that they would never do anything silly (right?); > > Your statement about ideally no .get/.put implementations outside > of migration/ is consistent with my initial understanding of VMStateInfo: > It's there to take care of the marshaling between the on wire representation > and the in memory representation of a single and preferably primitive > vmstate field (not consisting of further fields). Complex stuff like > arrays, structs, indirection via pointers and possibly allocation is > preferably handled elsewhere. So VMStateInfo is the basic building stones, > and the only place which should write to/read from the stream (in > ideal vmstate). > > So in a perfect vmstate world complete type of VMStateInfo is not part of the > API (you do not care about how it's done outside vmstate/), but only the > (possibly pointers to) VMStateInfo's supported by the vmstate API. > > Of course this is not realistic, at least at the moment. > > On the other hand if VMStateInfo is meant for complete customization, > as Jianjun has put it, then it obviously has to be a full fledged member > of the API, and I think then your ideal rule makes no sense to me. > > I also do think we will always need something for handling special > cases because we need to maintain compatibility -- see virtio migration > for example. > > > so the extra parameters aren't going to be misused too badly. > > > > What would you consider bad misuse? I do not see this as a big concern > at the moment. I don't know; but the only justification for needing the VMS_LINKED flag was that only those functions that were marked with VMS_LINKED would be passed the new field. Dave > Cheers, > Halil > > > However, we're probably quite a way from pulling all of the weirder > > .get/.put implementations back in. > > > > Dave > > > -- Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
On 13/10/2016 12:48, Halil Pasic wrote: >> > > I'm fine with this. I just think, it would be nice if the contract between > the vmstate-core and the client code implementing VMStateInfo callbacks > could be documented, including when are certain parameters valid, what > they stand for, and how are they supposed to be used for the next version of > the patch. Just to improve readability. Would this be OK with everybody? > > By the way the flag VMS_SINGLE is documented as ignored. Should we drop > it? Yes, I think so. Paolo
On 10/13/2016 03:48 AM, Halil Pasic wrote: > > > On 10/13/2016 10:22 AM, Paolo Bonzini wrote: >>>> No, I disagree. We shouldn't be worried about making intrusive changes >>>>>> to all invocations or declarations, if that leads to a simpler API. >>>> >>>> If VMStateInfo was meant for complete customization, then it was missing >>>> some parts. I think the API is indeed simpler. Just like >>>> definition for VMStateField. Not all of its fields are used all time. >> Code moves. We can decide how much customization to allow of VMStateInfo. >> >> You said it: "Not all of its fields are used all time". Likewise, not >> all arguments are used all time for get/put, but it's not an issue if they >> are still there! So this patch is good, but at the same time VMS_LINKED is >> pointless. >> >> Paolo >> > > I'm fine with this. I just think, it would be nice if the contract between > the vmstate-core and the client code implementing VMStateInfo callbacks > could be documented, including when are certain parameters valid, what > they stand for, and how are they supposed to be used for the next version of > the patch. Just to improve readability. Would this be OK with everybody? > > By the way the flag VMS_SINGLE is documented as ignored. Should we drop > it? > I will prepare the VMStateInfo and QTAIL stuff as a separated series. If indeed VMS_SINGLE is ignored, I can drop it here. It is similar to VMS_LINKED situation. Thanks, Jianjun >
On 10/13/2016 06:23 PM, Jianjun Duan wrote: > > > On 10/13/2016 03:48 AM, Halil Pasic wrote: >> >> >> On 10/13/2016 10:22 AM, Paolo Bonzini wrote: >>>>> No, I disagree. We shouldn't be worried about making intrusive changes >>>>>>> to all invocations or declarations, if that leads to a simpler API. >>>>> >>>>> If VMStateInfo was meant for complete customization, then it was missing >>>>> some parts. I think the API is indeed simpler. Just like >>>>> definition for VMStateField. Not all of its fields are used all time. >>> Code moves. We can decide how much customization to allow of VMStateInfo. >>> >>> You said it: "Not all of its fields are used all time". Likewise, not >>> all arguments are used all time for get/put, but it's not an issue if they >>> are still there! So this patch is good, but at the same time VMS_LINKED is >>> pointless. >>> >>> Paolo >>> >> >> I'm fine with this. I just think, it would be nice if the contract between >> the vmstate-core and the client code implementing VMStateInfo callbacks >> could be documented, including when are certain parameters valid, what >> they stand for, and how are they supposed to be used for the next version of >> the patch. Just to improve readability. Would this be OK with everybody? >> >> By the way the flag VMS_SINGLE is documented as ignored. Should we drop >> it? >> > I will prepare the VMStateInfo and QTAIL stuff as a separated series. If > indeed VMS_SINGLE is ignored, I can drop it here. It is similar to > VMS_LINKED situation. > > Thanks, > Jianjun I think it's completely unrelated, so I would not lump it together with the QTAILQ stuff. How do you feel about the apidoc part? Cheers, Halil
On 10/13/2016 09:32 AM, Halil Pasic wrote: > > > On 10/13/2016 06:23 PM, Jianjun Duan wrote: >> >> >> On 10/13/2016 03:48 AM, Halil Pasic wrote: >>> >>> >>> On 10/13/2016 10:22 AM, Paolo Bonzini wrote: >>>>>> No, I disagree. We shouldn't be worried about making intrusive changes >>>>>>>> to all invocations or declarations, if that leads to a simpler API. >>>>>> >>>>>> If VMStateInfo was meant for complete customization, then it was missing >>>>>> some parts. I think the API is indeed simpler. Just like >>>>>> definition for VMStateField. Not all of its fields are used all time. >>>> Code moves. We can decide how much customization to allow of VMStateInfo. >>>> >>>> You said it: "Not all of its fields are used all time". Likewise, not >>>> all arguments are used all time for get/put, but it's not an issue if they >>>> are still there! So this patch is good, but at the same time VMS_LINKED is >>>> pointless. >>>> >>>> Paolo >>>> >>> >>> I'm fine with this. I just think, it would be nice if the contract between >>> the vmstate-core and the client code implementing VMStateInfo callbacks >>> could be documented, including when are certain parameters valid, what >>> they stand for, and how are they supposed to be used for the next version of >>> the patch. Just to improve readability. Would this be OK with everybody? >>> >>> By the way the flag VMS_SINGLE is documented as ignored. Should we drop >>> it? >>> >> I will prepare the VMStateInfo and QTAIL stuff as a separated series. If >> indeed VMS_SINGLE is ignored, I can drop it here. It is similar to >> VMS_LINKED situation. >> >> Thanks, >> Jianjun > > I think it's completely unrelated, so I would not lump it together with > the QTAILQ stuff. > > How do you feel about the apidoc part? > I will add some comments inside vmstate_save/load_state about it. Thanks, Jianjun > Cheers, > Halil >
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 90f6943..943a960 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -2450,7 +2450,8 @@ static void vmxnet3_put_tx_stats_to_file(QEMUFile *f, qemu_put_be64(f, tx_stat->pktsTxDiscard); } -static int vmxnet3_get_txq_descr(QEMUFile *f, void *pv, size_t size) +static int vmxnet3_get_txq_descr(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { Vmxnet3TxqDescr *r = pv; @@ -2464,7 +2465,8 @@ static int vmxnet3_get_txq_descr(QEMUFile *f, void *pv, size_t size) return 0; } -static void vmxnet3_put_txq_descr(QEMUFile *f, void *pv, size_t size) +static void vmxnet3_put_txq_descr(QEMUFile *f, void *pv, size_t size, + VMStateField *field, QJSON *vmdesc) { Vmxnet3TxqDescr *r = pv; @@ -2511,7 +2513,8 @@ static void vmxnet3_put_rx_stats_to_file(QEMUFile *f, qemu_put_be64(f, rx_stat->pktsRxError); } -static int vmxnet3_get_rxq_descr(QEMUFile *f, void *pv, size_t size) +static int vmxnet3_get_rxq_descr(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { Vmxnet3RxqDescr *r = pv; int i; @@ -2529,7 +2532,8 @@ static int vmxnet3_get_rxq_descr(QEMUFile *f, void *pv, size_t size) return 0; } -static void vmxnet3_put_rxq_descr(QEMUFile *f, void *pv, size_t size) +static void vmxnet3_put_rxq_descr(QEMUFile *f, void *pv, size_t size, + VMStateField *field, QJSON *vmdesc) { Vmxnet3RxqDescr *r = pv; int i; @@ -2574,7 +2578,8 @@ static const VMStateInfo rxq_descr_info = { .put = vmxnet3_put_rxq_descr }; -static int vmxnet3_get_int_state(QEMUFile *f, void *pv, size_t size) +static int vmxnet3_get_int_state(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { Vmxnet3IntState *r = pv; @@ -2585,7 +2590,8 @@ static int vmxnet3_get_int_state(QEMUFile *f, void *pv, size_t size) return 0; } -static void vmxnet3_put_int_state(QEMUFile *f, void *pv, size_t size) +static void vmxnet3_put_int_state(QEMUFile *f, void *pv, size_t size, + VMStateField *field, QJSON *vmdesc) { Vmxnet3IntState *r = pv; diff --git a/hw/nvram/eeprom93xx.c b/hw/nvram/eeprom93xx.c index 2c16fc2..76d5f41 100644 --- a/hw/nvram/eeprom93xx.c +++ b/hw/nvram/eeprom93xx.c @@ -94,14 +94,16 @@ struct _eeprom_t { This is a Big hack, but it is how the old state did it. */ -static int get_uint16_from_uint8(QEMUFile *f, void *pv, size_t size) +static int get_uint16_from_uint8(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { uint16_t *v = pv; *v = qemu_get_ubyte(f); return 0; } -static void put_unused(QEMUFile *f, void *pv, size_t size) +static void put_unused(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { fprintf(stderr, "uint16_from_uint8 is used only for backwards compatibility.\n"); fprintf(stderr, "Never should be used to write a new state.\n"); diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 92aa563..a8a4a7a 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -524,14 +524,16 @@ static void fw_cfg_reset(DeviceState *d) Or we broke compatibility in the state, or we can't use struct tm */ -static int get_uint32_as_uint16(QEMUFile *f, void *pv, size_t size) +static int get_uint32_as_uint16(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { uint32_t *v = pv; *v = qemu_get_be16(f); return 0; } -static void put_unused(QEMUFile *f, void *pv, size_t size) +static void put_unused(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { fprintf(stderr, "uint32_as_uint16 is only used for backward compatibility.\n"); fprintf(stderr, "This functions shouldn't be called.\n"); diff --git a/hw/pci/msix.c b/hw/pci/msix.c index 0ec1cb1..69e7a50 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -587,12 +587,14 @@ void msix_unset_vector_notifiers(PCIDevice *dev) dev->msix_vector_poll_notifier = NULL; } -static void put_msix_state(QEMUFile *f, void *pv, size_t size) +static void put_msix_state(QEMUFile *f, void *pv, size_t size, + VMStateField *field, QJSON *vmdesc) { msix_save(pv, f); } -static int get_msix_state(QEMUFile *f, void *pv, size_t size) +static int get_msix_state(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { msix_load(pv, f); return 0; diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 24fae16..08c4547 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -445,7 +445,8 @@ int pci_bus_numa_node(PCIBus *bus) return PCI_BUS_GET_CLASS(bus)->numa_node(bus); } -static int get_pci_config_device(QEMUFile *f, void *pv, size_t size) +static int get_pci_config_device(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { PCIDevice *s = container_of(pv, PCIDevice, config); PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(s); @@ -484,7 +485,8 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size) } /* just put buffer */ -static void put_pci_config_device(QEMUFile *f, void *pv, size_t size) +static void put_pci_config_device(QEMUFile *f, void *pv, size_t size, + VMStateField *field, QJSON *vmdesc) { const uint8_t **v = pv; assert(size == pci_config_size(container_of(pv, PCIDevice, config))); @@ -497,7 +499,8 @@ static VMStateInfo vmstate_info_pci_config = { .put = put_pci_config_device, }; -static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size) +static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { PCIDevice *s = container_of(pv, PCIDevice, irq_state); uint32_t irq_state[PCI_NUM_PINS]; @@ -518,7 +521,8 @@ static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size) return 0; } -static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size) +static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size, + VMStateField *field, QJSON *vmdesc) { int i; PCIDevice *s = container_of(pv, PCIDevice, irq_state); diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c index 3dcd472..9f82aa6 100644 --- a/hw/pci/shpc.c +++ b/hw/pci/shpc.c @@ -695,13 +695,14 @@ void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l) shpc_cap_update_dword(d); } -static void shpc_save(QEMUFile *f, void *pv, size_t size) +static void shpc_save(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { PCIDevice *d = container_of(pv, PCIDevice, shpc); qemu_put_buffer(f, d->shpc->config, SHPC_SIZEOF(d)); } -static int shpc_load(QEMUFile *f, void *pv, size_t size) +static int shpc_load(QEMUFile *f, void *pv, size_t size, VMStateField *field) { PCIDevice *d = container_of(pv, PCIDevice, shpc); int ret = qemu_get_buffer(f, d->shpc->config, SHPC_SIZEOF(d)); diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 297216d..f40c10b 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -1945,7 +1945,8 @@ SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun) /* SCSI request list. For simplicity, pv points to the whole device */ -static void put_scsi_requests(QEMUFile *f, void *pv, size_t size) +static void put_scsi_requests(QEMUFile *f, void *pv, size_t size, + VMStateField *field, QJSON *vmdesc) { SCSIDevice *s = pv; SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus); @@ -1970,7 +1971,8 @@ static void put_scsi_requests(QEMUFile *f, void *pv, size_t size) qemu_put_sbyte(f, 0); } -static int get_scsi_requests(QEMUFile *f, void *pv, size_t size) +static int get_scsi_requests(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { SCSIDevice *s = pv; SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus); diff --git a/hw/timer/twl92230.c b/hw/timer/twl92230.c index 7ba4e9a..95eb7f3 100644 --- a/hw/timer/twl92230.c +++ b/hw/timer/twl92230.c @@ -747,14 +747,16 @@ static int menelaus_rx(I2CSlave *i2c) Or we broke compatibility in the state, or we can't use struct tm */ -static int get_int32_as_uint16(QEMUFile *f, void *pv, size_t size) +static int get_int32_as_uint16(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { int *v = pv; *v = qemu_get_be16(f); return 0; } -static void put_int32_as_uint16(QEMUFile *f, void *pv, size_t size) +static void put_int32_as_uint16(QEMUFile *f, void *pv, size_t size, + VMStateField *field, QJSON *vmdesc) { int *v = pv; qemu_put_be16(f, *v); diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 444672a..2ca4b46 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -2154,7 +2154,8 @@ static int usbredir_post_load(void *priv, int version_id) } /* For usbredirparser migration */ -static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused) +static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused, + void *opaque, QJSON *vmdesc) { USBRedirDevice *dev = priv; uint8_t *data; @@ -2174,7 +2175,8 @@ static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused) free(data); } -static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused) +static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused, + void *opaque) { USBRedirDevice *dev = priv; uint8_t *data; @@ -2217,7 +2219,8 @@ static const VMStateInfo usbredir_parser_vmstate_info = { /* For buffered packets (iso/irq) queue migration */ -static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused) +static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused, + VMStateField *field, QJSON *vmdesc) { struct endp_data *endp = priv; USBRedirDevice *dev = endp->dev; @@ -2237,7 +2240,8 @@ static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused) assert(i == endp->bufpq_size); } -static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused) +static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused, + VMStateField *field) { struct endp_data *endp = priv; USBRedirDevice *dev = endp->dev; @@ -2340,7 +2344,8 @@ static const VMStateDescription usbredir_ep_vmstate = { /* For PacketIdQueue migration */ -static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused) +static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused, + VMStateField *field, QJSON *vmdesc) { struct PacketIdQueue *q = priv; USBRedirDevice *dev = q->dev; @@ -2356,7 +2361,8 @@ static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused) assert(remain == 0); } -static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused) +static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused, + VMStateField *field) { struct PacketIdQueue *q = priv; USBRedirDevice *dev = q->dev; diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 2d60a00..38a7abd 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -108,7 +108,8 @@ static bool virtio_pci_has_extra_state(DeviceState *d) return proxy->flags & VIRTIO_PCI_FLAG_MIGRATE_EXTRA; } -static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size) +static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { VirtIOPCIProxy *proxy = pv; int i; @@ -137,7 +138,8 @@ static void virtio_pci_save_modern_queue_state(VirtIOPCIQueue *vq, qemu_put_be32(f, vq->used[1]); } -static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size) +static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size, + VMStateField *field, QJSON *vmdesc) { VirtIOPCIProxy *proxy = pv; int i; diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 18ce333..ade2683 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -1467,7 +1467,8 @@ static const VMStateDescription vmstate_virtio_ringsize = { } }; -static int get_extra_state(QEMUFile *f, void *pv, size_t size) +static int get_extra_state(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { VirtIODevice *vdev = pv; BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); @@ -1480,7 +1481,8 @@ static int get_extra_state(QEMUFile *f, void *pv, size_t size) } } -static void put_extra_state(QEMUFile *f, void *pv, size_t size) +static void put_extra_state(QEMUFile *f, void *pv, size_t size, + VMStateField *field, QJSON *vmdesc) { VirtIODevice *vdev = pv; BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index 1638ee5..459dd4a 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -81,11 +81,13 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque); typedef struct VMStateInfo VMStateInfo; typedef struct VMStateDescription VMStateDescription; +typedef struct VMStateField VMStateField; struct VMStateInfo { const char *name; - int (*get)(QEMUFile *f, void *pv, size_t size); - void (*put)(QEMUFile *f, void *pv, size_t size); + int (*get)(QEMUFile *f, void *pv, size_t size, VMStateField *field); + void (*put)(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc); }; enum VMStateFlags { @@ -186,7 +188,7 @@ enum VMStateFlags { VMS_MULTIPLY_ELEMENTS = 0x4000, }; -typedef struct { +struct VMStateField { const char *name; size_t offset; size_t size; @@ -199,7 +201,7 @@ typedef struct { const VMStateDescription *vmsd; int version_id; bool (*field_exists)(void *opaque, int version_id); -} VMStateField; +}; struct VMStateDescription { const char *name; diff --git a/migration/savevm.c b/migration/savevm.c index ef5c3d1..13b53ad 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -220,14 +220,15 @@ void timer_get(QEMUFile *f, QEMUTimer *ts) * Not in vmstate.c to not add qemu-timer.c as dependency to vmstate.c */ -static int get_timer(QEMUFile *f, void *pv, size_t size) +static int get_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field) { QEMUTimer *v = pv; timer_get(f, v); return 0; } -static void put_timer(QEMUFile *f, void *pv, size_t size) +static void put_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { QEMUTimer *v = pv; timer_put(f, v); diff --git a/migration/vmstate.c b/migration/vmstate.c index fc29acf..66802cb 100644 --- a/migration/vmstate.c +++ b/migration/vmstate.c @@ -122,7 +122,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, ret = vmstate_load_state(f, field->vmsd, addr, field->vmsd->version_id); } else { - ret = field->info->get(f, addr, size); + ret = field->info->get(f, addr, size, NULL); } if (ret >= 0) { @@ -328,7 +328,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, if (field->flags & VMS_STRUCT) { vmstate_save_state(f, field->vmsd, addr, vmdesc_loop); } else { - field->info->put(f, addr, size); + field->info->put(f, addr, size, NULL, NULL); } written_bytes = qemu_ftell_fast(f) - old_offset; @@ -461,14 +461,15 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, /* bool */ -static int get_bool(QEMUFile *f, void *pv, size_t size) +static int get_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field) { bool *v = pv; *v = qemu_get_byte(f); return 0; } -static void put_bool(QEMUFile *f, void *pv, size_t size) +static void put_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { bool *v = pv; qemu_put_byte(f, *v); @@ -482,14 +483,15 @@ const VMStateInfo vmstate_info_bool = { /* 8 bit int */ -static int get_int8(QEMUFile *f, void *pv, size_t size) +static int get_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field) { int8_t *v = pv; qemu_get_s8s(f, v); return 0; } -static void put_int8(QEMUFile *f, void *pv, size_t size) +static void put_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { int8_t *v = pv; qemu_put_s8s(f, v); @@ -503,14 +505,15 @@ const VMStateInfo vmstate_info_int8 = { /* 16 bit int */ -static int get_int16(QEMUFile *f, void *pv, size_t size) +static int get_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field) { int16_t *v = pv; qemu_get_sbe16s(f, v); return 0; } -static void put_int16(QEMUFile *f, void *pv, size_t size) +static void put_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { int16_t *v = pv; qemu_put_sbe16s(f, v); @@ -524,14 +527,15 @@ const VMStateInfo vmstate_info_int16 = { /* 32 bit int */ -static int get_int32(QEMUFile *f, void *pv, size_t size) +static int get_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field) { int32_t *v = pv; qemu_get_sbe32s(f, v); return 0; } -static void put_int32(QEMUFile *f, void *pv, size_t size) +static void put_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { int32_t *v = pv; qemu_put_sbe32s(f, v); @@ -546,7 +550,8 @@ const VMStateInfo vmstate_info_int32 = { /* 32 bit int. See that the received value is the same than the one in the field */ -static int get_int32_equal(QEMUFile *f, void *pv, size_t size) +static int get_int32_equal(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { int32_t *v = pv; int32_t v2; @@ -568,7 +573,7 @@ const VMStateInfo vmstate_info_int32_equal = { * and less than or equal to the one in the field. */ -static int get_int32_le(QEMUFile *f, void *pv, size_t size) +static int get_int32_le(QEMUFile *f, void *pv, size_t size, VMStateField *field) { int32_t *cur = pv; int32_t loaded; @@ -589,14 +594,15 @@ const VMStateInfo vmstate_info_int32_le = { /* 64 bit int */ -static int get_int64(QEMUFile *f, void *pv, size_t size) +static int get_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field) { int64_t *v = pv; qemu_get_sbe64s(f, v); return 0; } -static void put_int64(QEMUFile *f, void *pv, size_t size) +static void put_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { int64_t *v = pv; qemu_put_sbe64s(f, v); @@ -610,14 +616,15 @@ const VMStateInfo vmstate_info_int64 = { /* 8 bit unsigned int */ -static int get_uint8(QEMUFile *f, void *pv, size_t size) +static int get_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field) { uint8_t *v = pv; qemu_get_8s(f, v); return 0; } -static void put_uint8(QEMUFile *f, void *pv, size_t size) +static void put_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { uint8_t *v = pv; qemu_put_8s(f, v); @@ -631,14 +638,15 @@ const VMStateInfo vmstate_info_uint8 = { /* 16 bit unsigned int */ -static int get_uint16(QEMUFile *f, void *pv, size_t size) +static int get_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field) { uint16_t *v = pv; qemu_get_be16s(f, v); return 0; } -static void put_uint16(QEMUFile *f, void *pv, size_t size) +static void put_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { uint16_t *v = pv; qemu_put_be16s(f, v); @@ -652,14 +660,15 @@ const VMStateInfo vmstate_info_uint16 = { /* 32 bit unsigned int */ -static int get_uint32(QEMUFile *f, void *pv, size_t size) +static int get_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field) { uint32_t *v = pv; qemu_get_be32s(f, v); return 0; } -static void put_uint32(QEMUFile *f, void *pv, size_t size) +static void put_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { uint32_t *v = pv; qemu_put_be32s(f, v); @@ -674,7 +683,8 @@ const VMStateInfo vmstate_info_uint32 = { /* 32 bit uint. See that the received value is the same than the one in the field */ -static int get_uint32_equal(QEMUFile *f, void *pv, size_t size) +static int get_uint32_equal(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { uint32_t *v = pv; uint32_t v2; @@ -694,14 +704,15 @@ const VMStateInfo vmstate_info_uint32_equal = { /* 64 bit unsigned int */ -static int get_uint64(QEMUFile *f, void *pv, size_t size) +static int get_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field) { uint64_t *v = pv; qemu_get_be64s(f, v); return 0; } -static void put_uint64(QEMUFile *f, void *pv, size_t size) +static void put_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { uint64_t *v = pv; qemu_put_be64s(f, v); @@ -716,7 +727,8 @@ const VMStateInfo vmstate_info_uint64 = { /* 64 bit unsigned int. See that the received value is the same than the one in the field */ -static int get_uint64_equal(QEMUFile *f, void *pv, size_t size) +static int get_uint64_equal(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { uint64_t *v = pv; uint64_t v2; @@ -737,7 +749,8 @@ const VMStateInfo vmstate_info_uint64_equal = { /* 8 bit int. See that the received value is the same than the one in the field */ -static int get_uint8_equal(QEMUFile *f, void *pv, size_t size) +static int get_uint8_equal(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { uint8_t *v = pv; uint8_t v2; @@ -758,7 +771,8 @@ const VMStateInfo vmstate_info_uint8_equal = { /* 16 bit unsigned int int. See that the received value is the same than the one in the field */ -static int get_uint16_equal(QEMUFile *f, void *pv, size_t size) +static int get_uint16_equal(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { uint16_t *v = pv; uint16_t v2; @@ -778,7 +792,8 @@ const VMStateInfo vmstate_info_uint16_equal = { /* floating point */ -static int get_float64(QEMUFile *f, void *pv, size_t size) +static int get_float64(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { float64 *v = pv; @@ -786,7 +801,8 @@ static int get_float64(QEMUFile *f, void *pv, size_t size) return 0; } -static void put_float64(QEMUFile *f, void *pv, size_t size) +static void put_float64(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { uint64_t *v = pv; @@ -801,7 +817,8 @@ const VMStateInfo vmstate_info_float64 = { /* CPU_DoubleU type */ -static int get_cpudouble(QEMUFile *f, void *pv, size_t size) +static int get_cpudouble(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { CPU_DoubleU *v = pv; qemu_get_be32s(f, &v->l.upper); @@ -809,7 +826,8 @@ static int get_cpudouble(QEMUFile *f, void *pv, size_t size) return 0; } -static void put_cpudouble(QEMUFile *f, void *pv, size_t size) +static void put_cpudouble(QEMUFile *f, void *pv, size_t size, + VMStateField *field, QJSON *vmdesc) { CPU_DoubleU *v = pv; qemu_put_be32s(f, &v->l.upper); @@ -824,14 +842,16 @@ const VMStateInfo vmstate_info_cpudouble = { /* uint8_t buffers */ -static int get_buffer(QEMUFile *f, void *pv, size_t size) +static int get_buffer(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { uint8_t *v = pv; qemu_get_buffer(f, v, size); return 0; } -static void put_buffer(QEMUFile *f, void *pv, size_t size) +static void put_buffer(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { uint8_t *v = pv; qemu_put_buffer(f, v, size); @@ -846,7 +866,8 @@ const VMStateInfo vmstate_info_buffer = { /* unused buffers: space that was used for some fields that are not useful anymore */ -static int get_unused_buffer(QEMUFile *f, void *pv, size_t size) +static int get_unused_buffer(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { uint8_t buf[1024]; int block_len; @@ -859,7 +880,8 @@ static int get_unused_buffer(QEMUFile *f, void *pv, size_t size) return 0; } -static void put_unused_buffer(QEMUFile *f, void *pv, size_t size) +static void put_unused_buffer(QEMUFile *f, void *pv, size_t size, + VMStateField *field, QJSON *vmdesc) { static const uint8_t buf[1024]; int block_len; @@ -884,7 +906,7 @@ const VMStateInfo vmstate_info_unused_buffer = { */ /* This is the number of 64 bit words sent over the wire */ #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64) -static int get_bitmap(QEMUFile *f, void *pv, size_t size) +static int get_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field) { unsigned long *bmp = pv; int i, idx = 0; @@ -898,7 +920,8 @@ static int get_bitmap(QEMUFile *f, void *pv, size_t size) return 0; } -static void put_bitmap(QEMUFile *f, void *pv, size_t size) +static void put_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { unsigned long *bmp = pv; int i, idx = 0; diff --git a/target-alpha/machine.c b/target-alpha/machine.c index 710b783..48e3278 100644 --- a/target-alpha/machine.c +++ b/target-alpha/machine.c @@ -5,14 +5,15 @@ #include "hw/boards.h" #include "migration/cpu.h" -static int get_fpcr(QEMUFile *f, void *opaque, size_t size) +static int get_fpcr(QEMUFile *f, void *opaque, size_t size, VMStateField *field) { CPUAlphaState *env = opaque; cpu_alpha_store_fpcr(env, qemu_get_be64(f)); return 0; } -static void put_fpcr(QEMUFile *f, void *opaque, size_t size) +static void put_fpcr(QEMUFile *f, void *opaque, size_t size, + VMStateField *field, QJSON *vmdesc) { CPUAlphaState *env = opaque; qemu_put_be64(f, cpu_alpha_load_fpcr(env)); diff --git a/target-arm/machine.c b/target-arm/machine.c index 7a6ca31..41a0de9 100644 --- a/target-arm/machine.c +++ b/target-arm/machine.c @@ -17,7 +17,8 @@ static bool vfp_needed(void *opaque) return arm_feature(env, ARM_FEATURE_VFP); } -static int get_fpscr(QEMUFile *f, void *opaque, size_t size) +static int get_fpscr(QEMUFile *f, void *opaque, size_t size, + VMStateField *field) { ARMCPU *cpu = opaque; CPUARMState *env = &cpu->env; @@ -27,7 +28,8 @@ static int get_fpscr(QEMUFile *f, void *opaque, size_t size) return 0; } -static void put_fpscr(QEMUFile *f, void *opaque, size_t size) +static void put_fpscr(QEMUFile *f, void *opaque, size_t size, + VMStateField *field, QJSON *vmdesc) { ARMCPU *cpu = opaque; CPUARMState *env = &cpu->env; @@ -163,7 +165,8 @@ static const VMStateDescription vmstate_pmsav7 = { } }; -static int get_cpsr(QEMUFile *f, void *opaque, size_t size) +static int get_cpsr(QEMUFile *f, void *opaque, size_t size, + VMStateField *field) { ARMCPU *cpu = opaque; CPUARMState *env = &cpu->env; @@ -180,7 +183,8 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size) return 0; } -static void put_cpsr(QEMUFile *f, void *opaque, size_t size) +static void put_cpsr(QEMUFile *f, void *opaque, size_t size, + VMStateField *field, QJSON *vmdesc) { ARMCPU *cpu = opaque; CPUARMState *env = &cpu->env; diff --git a/target-i386/machine.c b/target-i386/machine.c index 71c0e4d..1df19e2 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -139,7 +139,8 @@ static const VMStateDescription vmstate_mtrr_var = { #define VMSTATE_MTRR_VARS(_field, _state, _n, _v) \ VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar) -static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size) +static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size, + VMStateField *field, QJSON *vmdesc) { fprintf(stderr, "call put_fpreg() with invalid arguments\n"); exit(0); @@ -167,7 +168,8 @@ static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp) p->exp = e; } -static int get_fpreg(QEMUFile *f, void *opaque, size_t size) +static int get_fpreg(QEMUFile *f, void *opaque, size_t size, + VMStateField *field) { FPReg *fp_reg = opaque; uint64_t mant; @@ -179,7 +181,8 @@ static int get_fpreg(QEMUFile *f, void *opaque, size_t size) return 0; } -static void put_fpreg(QEMUFile *f, void *opaque, size_t size) +static void put_fpreg(QEMUFile *f, void *opaque, size_t size, + VMStateField *field, QJSON *vmdesc) { FPReg *fp_reg = opaque; uint64_t mant; @@ -197,7 +200,8 @@ static const VMStateInfo vmstate_fpreg = { .put = put_fpreg, }; -static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size) +static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size, + VMStateField *field) { union x86_longdouble *p = opaque; uint64_t mant; @@ -214,7 +218,8 @@ static const VMStateInfo vmstate_fpreg_1_mmx = { .put = put_fpreg_error, }; -static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size) +static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size, + VMStateField *field) { union x86_longdouble *p = opaque; uint64_t mant; @@ -276,14 +281,16 @@ static bool less_than_7(void *opaque, int version_id) return version_id < 7; } -static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size) +static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size, + VMStateField *field) { uint64_t *v = pv; *v = qemu_get_be32(f); return 0; } -static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size) +static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size, + VMStateField *field, QJSON *vmdesc) { uint64_t *v = pv; qemu_put_be32(f, *v); diff --git a/target-mips/machine.c b/target-mips/machine.c index a27f2f1..179084c 100644 --- a/target-mips/machine.c +++ b/target-mips/machine.c @@ -20,7 +20,7 @@ static int cpu_post_load(void *opaque, int version_id) /* FPU state */ -static int get_fpr(QEMUFile *f, void *pv, size_t size) +static int get_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field) { int i; fpr_t *v = pv; @@ -31,7 +31,8 @@ static int get_fpr(QEMUFile *f, void *pv, size_t size) return 0; } -static void put_fpr(QEMUFile *f, void *pv, size_t size) +static void put_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { int i; fpr_t *v = pv; @@ -125,7 +126,7 @@ const VMStateDescription vmstate_mvp = { /* TLB state */ -static int get_tlb(QEMUFile *f, void *pv, size_t size) +static int get_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field) { r4k_tlb_t *v = pv; uint16_t flags; @@ -152,7 +153,8 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size) return 0; } -static void put_tlb(QEMUFile *f, void *pv, size_t size) +static void put_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { r4k_tlb_t *v = pv; diff --git a/target-ppc/machine.c b/target-ppc/machine.c index 4820f22..0e1822c 100644 --- a/target-ppc/machine.c +++ b/target-ppc/machine.c @@ -106,7 +106,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id) return 0; } -static int get_avr(QEMUFile *f, void *pv, size_t size) +static int get_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field) { ppc_avr_t *v = pv; @@ -116,7 +116,8 @@ static int get_avr(QEMUFile *f, void *pv, size_t size) return 0; } -static void put_avr(QEMUFile *f, void *pv, size_t size) +static void put_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { ppc_avr_t *v = pv; @@ -324,7 +325,7 @@ static const VMStateDescription vmstate_sr = { }; #ifdef TARGET_PPC64 -static int get_slbe(QEMUFile *f, void *pv, size_t size) +static int get_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field) { ppc_slb_t *v = pv; @@ -334,7 +335,8 @@ static int get_slbe(QEMUFile *f, void *pv, size_t size) return 0; } -static void put_slbe(QEMUFile *f, void *pv, size_t size) +static void put_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field, + QJSON *vmdesc) { ppc_slb_t *v = pv; diff --git a/target-sparc/machine.c b/target-sparc/machine.c index 59c92f7..3194e03 100644 --- a/target-sparc/machine.c +++ b/target-sparc/machine.c @@ -59,7 +59,7 @@ static const VMStateDescription vmstate_tlb_entry = { }; #endif -static int get_psr(QEMUFile *f, void *opaque, size_t size) +static int get_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field) { SPARCCPU *cpu = opaque; CPUSPARCState *env = &cpu->env; @@ -72,7 +72,8 @@ static int get_psr(QEMUFile *f, void *opaque, size_t size) return 0; } -static void put_psr(QEMUFile *f, void *opaque, size_t size) +static void put_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field, + QJSON *vmdesc) { SPARCCPU *cpu = opaque; CPUSPARCState *env = &cpu->env;
Current migration code cannot handle some data structures such as QTAILQ in qemu/queue.h. Here we extend the signatures of put/get in VMStateInfo so that customized handling is supported. Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com> --- hw/net/vmxnet3.c | 18 ++++++--- hw/nvram/eeprom93xx.c | 6 ++- hw/nvram/fw_cfg.c | 6 ++- hw/pci/msix.c | 6 ++- hw/pci/pci.c | 12 ++++-- hw/pci/shpc.c | 5 ++- hw/scsi/scsi-bus.c | 6 ++- hw/timer/twl92230.c | 6 ++- hw/usb/redirect.c | 18 ++++++--- hw/virtio/virtio-pci.c | 6 ++- hw/virtio/virtio.c | 6 ++- include/migration/vmstate.h | 10 +++-- migration/savevm.c | 5 ++- migration/vmstate.c | 95 ++++++++++++++++++++++++++++----------------- target-alpha/machine.c | 5 ++- target-arm/machine.c | 12 ++++-- target-i386/machine.c | 21 ++++++---- target-mips/machine.c | 10 +++-- target-ppc/machine.c | 10 +++-- target-sparc/machine.c | 5 ++- 20 files changed, 171 insertions(+), 97 deletions(-)