aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-01-24 19:25:19 +0000
committerPeter Maydell <peter.maydell@linaro.org>2017-01-24 19:25:19 +0000
commitd264871209400fa22796d403c9e1ab288d4a5c6b (patch)
tree42b20911ca6a03218a1181185ac0b9a4630f7dc8 /hw
parenta9e404600a9bd1e6a26431fc89e5069092e67f14 (diff)
parent46a02a745176e1ef30de41706b5da4f1bc7fc495 (diff)
Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20170124b' into staging
Migration 1 My maintainer change 2 Jianjun's qtailq 3 Ashijeet's only-migratable 4 Zhanghailiang's re-active images 5 Pankaj's change name of migration thread 6 My PCI migration merge 7 Juan's debug to tracing 8 My tracing on save # gpg: Signature made Tue 24 Jan 2017 18:39:35 GMT # gpg: using RSA key 0x0516331EBC5BFDE7 # gpg: Good signature from "Dr. David Alan Gilbert (RH2) <dgilbert@redhat.com>" # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 45F5 C71B 4A0C B7FB 977A 9FA9 0516 331E BC5B FDE7 * remotes/dgilbert/tags/pull-migration-20170124b: migration/tracing: Add tracing on save migration: transform remaining DPRINTF into trace_ PCI/migration merge vmstate_pci_device and vmstate_pcie_device migration: Change name of live migration thread migration: re-active images while migration been canceled after inactive them migration: Fail migration blocker for --only-migratable migration: disallow migrate_add_blocker during migration migration: Allow "device add" options to only add migratable devices migration: Add a new option to enable only-migratable block/vvfat: Remove the undesirable comment migration: add error_report tests/migration: Add test for QTAILQ migration migration: migrate QTAILQ migration: extend VMStateInfo MAINTAINERS: Add myself as a migration submaintainer Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/9pfs/9p.c33
-rw-r--r--hw/display/virtio-gpu.c40
-rw-r--r--hw/intc/arm_gic_kvm.c17
-rw-r--r--hw/intc/arm_gicv3_its_kvm.c20
-rw-r--r--hw/intc/arm_gicv3_kvm.c19
-rw-r--r--hw/intc/s390_flic_kvm.c8
-rw-r--r--hw/misc/ivshmem.c14
-rw-r--r--hw/net/e1000e.c2
-rw-r--r--hw/net/vmxnet3.c26
-rw-r--r--hw/nvram/eeprom93xx.c8
-rw-r--r--hw/nvram/fw_cfg.c8
-rw-r--r--hw/pci-bridge/ioh3420.c2
-rw-r--r--hw/pci-bridge/xio3130_downstream.c2
-rw-r--r--hw/pci-bridge/xio3130_upstream.c2
-rw-r--r--hw/pci/msix.c8
-rw-r--r--hw/pci/pci.c57
-rw-r--r--hw/pci/shpc.c7
-rw-r--r--hw/scsi/megasas.c2
-rw-r--r--hw/scsi/scsi-bus.c8
-rw-r--r--hw/scsi/vhost-scsi.c25
-rw-r--r--hw/scsi/vmw_pvscsi.c2
-rw-r--r--hw/timer/twl92230.c8
-rw-r--r--hw/usb/bus.c19
-rw-r--r--hw/usb/hcd-xhci.c2
-rw-r--r--hw/usb/redirect.c26
-rw-r--r--hw/virtio/vhost.c8
-rw-r--r--hw/virtio/virtio-pci.c8
-rw-r--r--hw/virtio/virtio.c15
28 files changed, 271 insertions, 125 deletions
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index fa58877570..06b6e7ec66 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -979,6 +979,7 @@ static void coroutine_fn v9fs_attach(void *opaque)
size_t offset = 7;
V9fsQID qid;
ssize_t err;
+ Error *local_err = NULL;
v9fs_string_init(&uname);
v9fs_string_init(&aname);
@@ -1007,26 +1008,36 @@ static void coroutine_fn v9fs_attach(void *opaque)
clunk_fid(s, fid);
goto out;
}
- err = pdu_marshal(pdu, offset, "Q", &qid);
- if (err < 0) {
- clunk_fid(s, fid);
- goto out;
- }
- err += offset;
- memcpy(&s->root_qid, &qid, sizeof(qid));
- trace_v9fs_attach_return(pdu->tag, pdu->id,
- qid.type, qid.version, qid.path);
+
/*
* disable migration if we haven't done already.
* attach could get called multiple times for the same export.
*/
if (!s->migration_blocker) {
- s->root_fid = fid;
error_setg(&s->migration_blocker,
"Migration is disabled when VirtFS export path '%s' is mounted in the guest using mount_tag '%s'",
s->ctx.fs_root ? s->ctx.fs_root : "NULL", s->tag);
- migrate_add_blocker(s->migration_blocker);
+ err = migrate_add_blocker(s->migration_blocker, &local_err);
+ if (local_err) {
+ error_free(local_err);
+ error_free(s->migration_blocker);
+ s->migration_blocker = NULL;
+ clunk_fid(s, fid);
+ goto out;
+ }
+ s->root_fid = fid;
+ }
+
+ err = pdu_marshal(pdu, offset, "Q", &qid);
+ if (err < 0) {
+ clunk_fid(s, fid);
+ goto out;
}
+ err += offset;
+
+ memcpy(&s->root_qid, &qid, sizeof(qid));
+ trace_v9fs_attach_return(pdu->tag, pdu->id,
+ qid.type, qid.version, qid.path);
out:
put_fid(pdu, fidp);
out_nofid:
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 7a15c61c76..444ca064c1 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1003,7 +1003,8 @@ static const VMStateDescription vmstate_virtio_gpu_scanouts = {
},
};
-static void virtio_gpu_save(QEMUFile *f, void *opaque, size_t size)
+static int virtio_gpu_save(QEMUFile *f, void *opaque, size_t size,
+ VMStateField *field, QJSON *vmdesc)
{
VirtIOGPU *g = opaque;
struct virtio_gpu_simple_resource *res;
@@ -1028,9 +1029,12 @@ static void virtio_gpu_save(QEMUFile *f, void *opaque, size_t size)
qemu_put_be32(f, 0); /* end of list */
vmstate_save_state(f, &vmstate_virtio_gpu_scanouts, g, NULL);
+
+ return 0;
}
-static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size)
+static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
+ VMStateField *field)
{
VirtIOGPU *g = opaque;
struct virtio_gpu_simple_resource *res;
@@ -1132,6 +1136,7 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
VirtIOGPU *g = VIRTIO_GPU(qdev);
bool have_virgl;
+ Error *local_err = NULL;
int i;
if (g->conf.max_outputs > VIRTIO_GPU_MAX_SCANOUTS) {
@@ -1139,14 +1144,6 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
return;
}
- g->config_size = sizeof(struct virtio_gpu_config);
- g->virtio_config.num_scanouts = g->conf.max_outputs;
- virtio_init(VIRTIO_DEVICE(g), "virtio-gpu", VIRTIO_ID_GPU,
- g->config_size);
-
- g->req_state[0].width = 1024;
- g->req_state[0].height = 768;
-
g->use_virgl_renderer = false;
#if !defined(CONFIG_VIRGL) || defined(HOST_WORDS_BIGENDIAN)
have_virgl = false;
@@ -1158,6 +1155,24 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
}
if (virtio_gpu_virgl_enabled(g->conf)) {
+ error_setg(&g->migration_blocker, "virgl is not yet migratable");
+ migrate_add_blocker(g->migration_blocker, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ error_free(g->migration_blocker);
+ return;
+ }
+ }
+
+ g->config_size = sizeof(struct virtio_gpu_config);
+ g->virtio_config.num_scanouts = g->conf.max_outputs;
+ virtio_init(VIRTIO_DEVICE(g), "virtio-gpu", VIRTIO_ID_GPU,
+ g->config_size);
+
+ g->req_state[0].width = 1024;
+ g->req_state[0].height = 768;
+
+ if (virtio_gpu_virgl_enabled(g->conf)) {
/* use larger control queue in 3d mode */
g->ctrl_vq = virtio_add_queue(vdev, 256, virtio_gpu_handle_ctrl_cb);
g->cursor_vq = virtio_add_queue(vdev, 16, virtio_gpu_handle_cursor_cb);
@@ -1183,11 +1198,6 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
dpy_gfx_replace_surface(g->scanout[i].con, NULL);
}
}
-
- if (virtio_gpu_virgl_enabled(g->conf)) {
- error_setg(&g->migration_blocker, "virgl is not yet migratable");
- migrate_add_blocker(g->migration_blocker);
- }
}
static void virtio_gpu_device_unrealize(DeviceState *qdev, Error **errp)
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index 11729ee902..ec952ece93 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -510,6 +510,17 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
return;
}
+ if (!kvm_arm_gic_can_save_restore(s)) {
+ error_setg(&s->migration_blocker, "This operating system kernel does "
+ "not support vGICv2 migration");
+ migrate_add_blocker(s->migration_blocker, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ error_free(s->migration_blocker);
+ return;
+ }
+ }
+
gic_init_irqs_and_mmio(s, kvm_arm_gicv2_set_irq, NULL);
for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
@@ -558,12 +569,6 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
KVM_VGIC_V2_ADDR_TYPE_CPU,
s->dev_fd);
- if (!kvm_arm_gic_can_save_restore(s)) {
- error_setg(&s->migration_blocker, "This operating system kernel does "
- "not support vGICv2 migration");
- migrate_add_blocker(s->migration_blocker);
- }
-
if (kvm_has_gsi_routing()) {
/* set up irq routing */
kvm_init_irq_routing(kvm_state);
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
index fc246e0cb5..bd4f3aafc6 100644
--- a/hw/intc/arm_gicv3_its_kvm.c
+++ b/hw/intc/arm_gicv3_its_kvm.c
@@ -56,6 +56,19 @@ static int kvm_its_send_msi(GICv3ITSState *s, uint32_t value, uint16_t devid)
static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
{
GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
+ Error *local_err = NULL;
+
+ /*
+ * Block migration of a KVM GICv3 ITS device: the API for saving and
+ * restoring the state in the kernel is not yet available
+ */
+ error_setg(&s->migration_blocker, "vITS migration is not implemented");
+ migrate_add_blocker(s->migration_blocker, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ error_free(s->migration_blocker);
+ return;
+ }
s->dev_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_ITS, false);
if (s->dev_fd < 0) {
@@ -73,13 +86,6 @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
gicv3_its_init_mmio(s, NULL);
- /*
- * Block migration of a KVM GICv3 ITS device: the API for saving and
- * restoring the state in the kernel is not yet available
- */
- error_setg(&s->migration_blocker, "vITS migration is not implemented");
- migrate_add_blocker(s->migration_blocker);
-
kvm_msi_use_devid = true;
kvm_gsi_direct_mapping = false;
kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
index 199a439ccf..d69dc47370 100644
--- a/hw/intc/arm_gicv3_kvm.c
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -103,6 +103,18 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL);
+ /* Block migration of a KVM GICv3 device: the API for saving and restoring
+ * the state in the kernel is not yet finalised in the kernel or
+ * implemented in QEMU.
+ */
+ error_setg(&s->migration_blocker, "vGICv3 migration is not implemented");
+ migrate_add_blocker(s->migration_blocker, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ error_free(s->migration_blocker);
+ return;
+ }
+
/* Try to create the device via the device control API */
s->dev_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V3, false);
if (s->dev_fd < 0) {
@@ -122,13 +134,6 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
kvm_arm_register_device(&s->iomem_redist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd);
- /* Block migration of a KVM GICv3 device: the API for saving and restoring
- * the state in the kernel is not yet finalised in the kernel or
- * implemented in QEMU.
- */
- error_setg(&s->migration_blocker, "vGICv3 migration is not implemented");
- migrate_add_blocker(s->migration_blocker);
-
if (kvm_has_gsi_routing()) {
/* set up irq routing */
kvm_init_irq_routing(kvm_state);
diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
index c313166fbe..da8e4dfab6 100644
--- a/hw/intc/s390_flic_kvm.c
+++ b/hw/intc/s390_flic_kvm.c
@@ -286,7 +286,8 @@ static void kvm_s390_release_adapter_routes(S390FLICState *fs,
* increase until buffer is sufficient or maxium size is
* reached
*/
-static void kvm_flic_save(QEMUFile *f, void *opaque, size_t size)
+static int kvm_flic_save(QEMUFile *f, void *opaque, size_t size,
+ VMStateField *field, QJSON *vmdesc)
{
KVMS390FLICState *flic = opaque;
int len = FLIC_SAVE_INITIAL_SIZE;
@@ -319,6 +320,8 @@ static void kvm_flic_save(QEMUFile *f, void *opaque, size_t size)
count * sizeof(struct kvm_s390_irq));
}
g_free(buf);
+
+ return 0;
}
/**
@@ -331,7 +334,8 @@ static void kvm_flic_save(QEMUFile *f, void *opaque, size_t size)
* Note: Do nothing when no interrupts where stored
* in QEMUFile
*/
-static int kvm_flic_load(QEMUFile *f, void *opaque, size_t size)
+static int kvm_flic_load(QEMUFile *f, void *opaque, size_t size,
+ VMStateField *field)
{
uint64_t len = 0;
uint64_t count = 0;
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index abeaf3da08..fd14d7a07e 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -840,6 +840,7 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
uint8_t *pci_conf;
uint8_t attr = PCI_BASE_ADDRESS_SPACE_MEMORY |
PCI_BASE_ADDRESS_MEM_PREFETCH;
+ Error *local_err = NULL;
/* IRQFD requires MSI */
if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD) &&
@@ -903,9 +904,6 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
}
}
- vmstate_register_ram(s->ivshmem_bar2, DEVICE(s));
- pci_register_bar(PCI_DEVICE(s), 2, attr, s->ivshmem_bar2);
-
if (s->master == ON_OFF_AUTO_AUTO) {
s->master = s->vm_id == 0 ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
}
@@ -913,8 +911,16 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
if (!ivshmem_is_master(s)) {
error_setg(&s->migration_blocker,
"Migration is disabled when using feature 'peer mode' in device 'ivshmem'");
- migrate_add_blocker(s->migration_blocker);
+ migrate_add_blocker(s->migration_blocker, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ error_free(s->migration_blocker);
+ return;
+ }
}
+
+ vmstate_register_ram(s->ivshmem_bar2, DEVICE(s));
+ pci_register_bar(PCI_DEVICE(s), 2, attr, s->ivshmem_bar2);
}
static void ivshmem_exit(PCIDevice *dev)
diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
index 77a4b3e5bf..0e9a25b7ab 100644
--- a/hw/net/e1000e.c
+++ b/hw/net/e1000e.c
@@ -593,7 +593,7 @@ static const VMStateDescription e1000e_vmstate = {
.pre_save = e1000e_pre_save,
.post_load = e1000e_post_load,
.fields = (VMStateField[]) {
- VMSTATE_PCIE_DEVICE(parent_obj, E1000EState),
+ VMSTATE_PCI_DEVICE(parent_obj, E1000EState),
VMSTATE_MSIX(parent_obj, E1000EState),
VMSTATE_UINT32(ioaddr, E1000EState),
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 92f6af9620..2cb2731e29 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -2451,7 +2451,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;
@@ -2465,7 +2466,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 int vmxnet3_put_txq_descr(QEMUFile *f, void *pv, size_t size,
+ VMStateField *field, QJSON *vmdesc)
{
Vmxnet3TxqDescr *r = pv;
@@ -2474,6 +2476,8 @@ static void vmxnet3_put_txq_descr(QEMUFile *f, void *pv, size_t size)
qemu_put_byte(f, r->intr_idx);
qemu_put_be64(f, r->tx_stats_pa);
vmxnet3_put_tx_stats_to_file(f, &r->txq_stats);
+
+ return 0;
}
static const VMStateInfo txq_descr_info = {
@@ -2512,7 +2516,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;
@@ -2530,7 +2535,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 int vmxnet3_put_rxq_descr(QEMUFile *f, void *pv, size_t size,
+ VMStateField *field, QJSON *vmdesc)
{
Vmxnet3RxqDescr *r = pv;
int i;
@@ -2543,6 +2549,8 @@ static void vmxnet3_put_rxq_descr(QEMUFile *f, void *pv, size_t size)
qemu_put_byte(f, r->intr_idx);
qemu_put_be64(f, r->rx_stats_pa);
vmxnet3_put_rx_stats_to_file(f, &r->rxq_stats);
+
+ return 0;
}
static int vmxnet3_post_load(void *opaque, int version_id)
@@ -2575,7 +2583,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;
@@ -2586,13 +2595,16 @@ 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 int vmxnet3_put_int_state(QEMUFile *f, void *pv, size_t size,
+ VMStateField *field, QJSON *vmdesc)
{
Vmxnet3IntState *r = pv;
qemu_put_byte(f, r->is_masked);
qemu_put_byte(f, r->is_pending);
qemu_put_byte(f, r->is_asserted);
+
+ return 0;
}
static const VMStateInfo int_state_info = {
@@ -2619,7 +2631,7 @@ static const VMStateDescription vmstate_vmxnet3_pcie_device = {
.minimum_version_id = 1,
.needed = vmxnet3_vmstate_need_pcie_device,
.fields = (VMStateField[]) {
- VMSTATE_PCIE_DEVICE(parent_obj, VMXNET3State),
+ VMSTATE_PCI_DEVICE(parent_obj, VMXNET3State),
VMSTATE_END_OF_LIST()
}
};
diff --git a/hw/nvram/eeprom93xx.c b/hw/nvram/eeprom93xx.c
index 2c16fc23df..848692abc0 100644
--- a/hw/nvram/eeprom93xx.c
+++ b/hw/nvram/eeprom93xx.c
@@ -94,18 +94,22 @@ 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 int 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");
exit(0);
+
+ return 0;
}
static const VMStateInfo vmstate_hack_uint16_from_uint8 = {
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 523d585dcf..316fca9bc1 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -555,17 +555,21 @@ 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 int 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");
+
+ return 0;
}
static const VMStateInfo vmstate_hack_uint32_as_uint16 = {
diff --git a/hw/pci-bridge/ioh3420.c b/hw/pci-bridge/ioh3420.c
index 84b7946c31..0eef87a4f8 100644
--- a/hw/pci-bridge/ioh3420.c
+++ b/hw/pci-bridge/ioh3420.c
@@ -180,7 +180,7 @@ static const VMStateDescription vmstate_ioh3420 = {
.minimum_version_id = 1,
.post_load = pcie_cap_slot_post_load,
.fields = (VMStateField[]) {
- VMSTATE_PCIE_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot),
+ VMSTATE_PCI_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot),
VMSTATE_STRUCT(parent_obj.parent_obj.parent_obj.exp.aer_log,
PCIESlot, 0, vmstate_pcie_aer_log, PCIEAERLog),
VMSTATE_END_OF_LIST()
diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c
index 04b8e5b847..cfe8a3657f 100644
--- a/hw/pci-bridge/xio3130_downstream.c
+++ b/hw/pci-bridge/xio3130_downstream.c
@@ -166,7 +166,7 @@ static const VMStateDescription vmstate_xio3130_downstream = {
.minimum_version_id = 1,
.post_load = pcie_cap_slot_post_load,
.fields = (VMStateField[]) {
- VMSTATE_PCIE_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot),
+ VMSTATE_PCI_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot),
VMSTATE_STRUCT(parent_obj.parent_obj.parent_obj.exp.aer_log,
PCIESlot, 0, vmstate_pcie_aer_log, PCIEAERLog),
VMSTATE_END_OF_LIST()
diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c
index d1f59c8834..401c78452b 100644
--- a/hw/pci-bridge/xio3130_upstream.c
+++ b/hw/pci-bridge/xio3130_upstream.c
@@ -138,7 +138,7 @@ static const VMStateDescription vmstate_xio3130_upstream = {
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
- VMSTATE_PCIE_DEVICE(parent_obj.parent_obj, PCIEPort),
+ VMSTATE_PCI_DEVICE(parent_obj.parent_obj, PCIEPort),
VMSTATE_STRUCT(parent_obj.parent_obj.exp.aer_log, PCIEPort, 0,
vmstate_pcie_aer_log, PCIEAERLog),
VMSTATE_END_OF_LIST()
diff --git a/hw/pci/msix.c b/hw/pci/msix.c
index 0ec1cb14fc..ee1714d2cf 100644
--- a/hw/pci/msix.c
+++ b/hw/pci/msix.c
@@ -587,12 +587,16 @@ 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 int put_msix_state(QEMUFile *f, void *pv, size_t size,
+ VMStateField *field, QJSON *vmdesc)
{
msix_save(pv, f);
+
+ return 0;
}
-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 fe9acecbbf..47ca3af69a 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,11 +485,14 @@ 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 int 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)));
qemu_put_buffer(f, *v, size);
+
+ return 0;
}
static VMStateInfo vmstate_info_pci_config = {
@@ -497,7 +501,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 +523,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 int 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);
@@ -526,6 +532,8 @@ static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size)
for (i = 0; i < PCI_NUM_PINS; ++i) {
qemu_put_be32(f, pci_irq_state(s, i));
}
+
+ return 0;
}
static VMStateInfo vmstate_info_pci_irq_state = {
@@ -534,30 +542,29 @@ static VMStateInfo vmstate_info_pci_irq_state = {
.put = put_pci_irq_state,
};
+static bool migrate_is_pcie(void *opaque, int version_id)
+{
+ return pci_is_express((PCIDevice *)opaque);
+}
+
+static bool migrate_is_not_pcie(void *opaque, int version_id)
+{
+ return !pci_is_express((PCIDevice *)opaque);
+}
+
const VMStateDescription vmstate_pci_device = {
.name = "PCIDevice",
.version_id = 2,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_INT32_POSITIVE_LE(version_id, PCIDevice),
- VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
- vmstate_info_pci_config,
+ VMSTATE_BUFFER_UNSAFE_INFO_TEST(config, PCIDevice,
+ migrate_is_not_pcie,
+ 0, vmstate_info_pci_config,
PCI_CONFIG_SPACE_SIZE),
- VMSTATE_BUFFER_UNSAFE_INFO(irq_state, PCIDevice, 2,
- vmstate_info_pci_irq_state,
- PCI_NUM_PINS * sizeof(int32_t)),
- VMSTATE_END_OF_LIST()
- }
-};
-
-const VMStateDescription vmstate_pcie_device = {
- .name = "PCIEDevice",
- .version_id = 2,
- .minimum_version_id = 1,
- .fields = (VMStateField[]) {
- VMSTATE_INT32_POSITIVE_LE(version_id, PCIDevice),
- VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0,
- vmstate_info_pci_config,
+ VMSTATE_BUFFER_UNSAFE_INFO_TEST(config, PCIDevice,
+ migrate_is_pcie,
+ 0, vmstate_info_pci_config,
PCIE_CONFIG_SPACE_SIZE),
VMSTATE_BUFFER_UNSAFE_INFO(irq_state, PCIDevice, 2,
vmstate_info_pci_irq_state,
@@ -566,10 +573,6 @@ const VMStateDescription vmstate_pcie_device = {
}
};
-static inline const VMStateDescription *pci_get_vmstate(PCIDevice *s)
-{
- return pci_is_express(s) ? &vmstate_pcie_device : &vmstate_pci_device;
-}
void pci_device_save(PCIDevice *s, QEMUFile *f)
{
@@ -578,7 +581,7 @@ void pci_device_save(PCIDevice *s, QEMUFile *f)
* This makes us compatible with old devices
* which never set or clear this bit. */
s->config[PCI_STATUS] &= ~PCI_STATUS_INTERRUPT;
- vmstate_save_state(f, pci_get_vmstate(s), s, NULL);
+ vmstate_save_state(f, &vmstate_pci_device, s, NULL);
/* Restore the interrupt status bit. */
pci_update_irq_status(s);
}
@@ -586,7 +589,7 @@ void pci_device_save(PCIDevice *s, QEMUFile *f)
int pci_device_load(PCIDevice *s, QEMUFile *f)
{
int ret;
- ret = vmstate_load_state(f, pci_get_vmstate(s), s, s->version_id);
+ ret = vmstate_load_state(f, &vmstate_pci_device, s, s->version_id);
/* Restore the interrupt status bit. */
pci_update_irq_status(s);
return ret;
diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
index 3dcd472eba..42fafac91b 100644
--- a/hw/pci/shpc.c
+++ b/hw/pci/shpc.c
@@ -695,13 +695,16 @@ 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 int 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));
+
+ return 0;
}
-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/megasas.c b/hw/scsi/megasas.c
index 6233865494..6aad7c9a06 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -2289,7 +2289,7 @@ static const VMStateDescription vmstate_megasas_gen2 = {
.minimum_version_id = 0,
.minimum_version_id_old = 0,
.fields = (VMStateField[]) {
- VMSTATE_PCIE_DEVICE(parent_obj, MegasasState),
+ VMSTATE_PCI_DEVICE(parent_obj, MegasasState),
VMSTATE_MSIX(parent_obj, MegasasState),
VMSTATE_INT32(fw_state, MegasasState),
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 297216dfcb..5940cb160c 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 int 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);
@@ -1968,9 +1969,12 @@ static void put_scsi_requests(QEMUFile *f, void *pv, size_t size)
}
}
qemu_put_sbyte(f, 0);
+
+ return 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/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 5b2694615f..c491ece1f2 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -238,8 +238,16 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
vhost_dummy_handle_output);
if (err != NULL) {
error_propagate(errp, err);
- close(vhostfd);
- return;
+ goto close_fd;
+ }
+
+ error_setg(&s->migration_blocker,
+ "vhost-scsi does not support migration");
+ migrate_add_blocker(s->migration_blocker, &err);
+ if (err) {
+ error_propagate(errp, err);
+ error_free(s->migration_blocker);
+ goto close_fd;
}
s->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
@@ -252,7 +260,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
if (ret < 0) {
error_setg(errp, "vhost-scsi: vhost initialization failed: %s",
strerror(-ret));
- return;
+ goto free_vqs;
}
/* At present, channel and lun both are 0 for bootable vhost-scsi disk */
@@ -261,9 +269,14 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp)
/* Note: we can also get the minimum tpgt from kernel */
s->target = vs->conf.boot_tpgt;
- error_setg(&s->migration_blocker,
- "vhost-scsi does not support migration");
- migrate_add_blocker(s->migration_blocker);
+ return;
+
+ free_vqs:
+ migrate_del_blocker(s->migration_blocker);
+ g_free(s->dev.vqs);
+ close_fd:
+ close(vhostfd);
+ return;
}
static void vhost_scsi_unrealize(DeviceState *dev, Error **errp)
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index a5ce7dea8e..75575461e2 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -1207,7 +1207,7 @@ static const VMStateDescription vmstate_pvscsi_pcie_device = {
.name = "pvscsi/pcie",
.needed = pvscsi_vmstate_need_pcie_device,
.fields = (VMStateField[]) {
- VMSTATE_PCIE_DEVICE(parent_obj, PVSCSIState),
+ VMSTATE_PCI_DEVICE(parent_obj, PVSCSIState),
VMSTATE_END_OF_LIST()
}
};
diff --git a/hw/timer/twl92230.c b/hw/timer/twl92230.c
index b8d914e49b..c0aa8ae3de 100644
--- a/hw/timer/twl92230.c
+++ b/hw/timer/twl92230.c
@@ -749,17 +749,21 @@ 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 int put_int32_as_uint16(QEMUFile *f, void *pv, size_t size,
+ VMStateField *field, QJSON *vmdesc)
{
int *v = pv;
qemu_put_be16(f, *v);
+
+ return 0;
}
static const VMStateInfo vmstate_hack_int32_as_uint16 = {
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index 25913ad488..1dcc35c8f8 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -8,6 +8,7 @@
#include "monitor/monitor.h"
#include "trace.h"
#include "qemu/cutils.h"
+#include "migration/migration.h"
static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
@@ -686,6 +687,8 @@ USBDevice *usbdevice_create(const char *cmdline)
const char *params;
int len;
USBDevice *dev;
+ ObjectClass *klass;
+ DeviceClass *dc;
params = strchr(cmdline,':');
if (params) {
@@ -720,6 +723,22 @@ USBDevice *usbdevice_create(const char *cmdline)
return NULL;
}
+ klass = object_class_by_name(f->name);
+ if (klass == NULL) {
+ error_report("Device '%s' not found", f->name);
+ return NULL;
+ }
+
+ dc = DEVICE_CLASS(klass);
+
+ if (only_migratable) {
+ if (dc->vmsd->unmigratable) {
+ error_report("Device %s is not migratable, but --only-migratable "
+ "was specified", f->name);
+ return NULL;
+ }
+ }
+
if (f->usbdevice_init) {
dev = f->usbdevice_init(bus, params);
} else {
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 4acf0c6dd8..e0b516987f 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -3894,7 +3894,7 @@ static const VMStateDescription vmstate_xhci = {
.version_id = 1,
.post_load = usb_xhci_post_load,
.fields = (VMStateField[]) {
- VMSTATE_PCIE_DEVICE(parent_obj, XHCIState),
+ VMSTATE_PCI_DEVICE(parent_obj, XHCIState),
VMSTATE_MSIX(parent_obj, XHCIState),
VMSTATE_STRUCT_VARRAY_UINT32(ports, XHCIState, numports, 1,
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index a65723781e..4a0ebbfb32 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -2165,7 +2165,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 int usbredir_put_parser(QEMUFile *f, void *priv, size_t unused,
+ VMStateField *field, QJSON *vmdesc)
{
USBRedirDevice *dev = priv;
uint8_t *data;
@@ -2173,7 +2174,7 @@ static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
if (dev->parser == NULL) {
qemu_put_be32(f, 0);
- return;
+ return 0;
}
usbredirparser_serialize(dev->parser, &data, &len);
@@ -2183,9 +2184,12 @@ static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
qemu_put_buffer(f, data, len);
free(data);
+
+ return 0;
}
-static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused)
+static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused,
+ VMStateField *field)
{
USBRedirDevice *dev = priv;
uint8_t *data;
@@ -2228,7 +2232,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 int usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused,
+ VMStateField *field, QJSON *vmdesc)
{
struct endp_data *endp = priv;
USBRedirDevice *dev = endp->dev;
@@ -2246,9 +2251,12 @@ static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused)
i++;
}
assert(i == endp->bufpq_size);
+
+ return 0;
}
-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;
@@ -2351,7 +2359,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 int usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused,
+ VMStateField *field, QJSON *vmdesc)
{
struct PacketIdQueue *q = priv;
USBRedirDevice *dev = q->dev;
@@ -2365,9 +2374,12 @@ static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused)
remain--;
}
assert(remain == 0);
+
+ return 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/vhost.c b/hw/virtio/vhost.c
index 9cacf557f2..b124d97d7c 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1176,6 +1176,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
{
uint64_t features;
int i, r, n_initialized_vqs = 0;
+ Error *local_err = NULL;
hdev->vdev = NULL;
hdev->migration_blocker = NULL;
@@ -1256,7 +1257,12 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
}
if (hdev->migration_blocker != NULL) {
- migrate_add_blocker(hdev->migration_blocker);
+ r = migrate_add_blocker(hdev->migration_blocker, &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ error_free(hdev->migration_blocker);
+ goto fail_busyloop;
+ }
}
hdev->mem = g_malloc0(offsetof(struct vhost_memory, regions));
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 09230c05df..b5af2a00f3 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 int put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size,
+ VMStateField *field, QJSON *vmdesc)
{
VirtIOPCIProxy *proxy = pv;
int i;
@@ -149,6 +151,8 @@ static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size)
for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
virtio_pci_save_modern_queue_state(&proxy->vqs[i], f);
}
+
+ return 0;
}
static const VMStateInfo vmstate_info_virtio_pci_modern_state = {
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index cc17b97899..f292a53940 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1555,7 +1555,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));
@@ -1568,13 +1569,15 @@ 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 int 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));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
k->save_extra_state(qbus->parent, f);
+ return 0;
}
static const VMStateInfo vmstate_info_extra_state = {
@@ -1709,13 +1712,17 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
}
/* A wrapper for use as a VMState .put function */
-static void virtio_device_put(QEMUFile *f, void *opaque, size_t size)
+static int virtio_device_put(QEMUFile *f, void *opaque, size_t size,
+ VMStateField *field, QJSON *vmdesc)
{
virtio_save(VIRTIO_DEVICE(opaque), f);
+
+ return 0;
}
/* A wrapper for use as a VMState .get function */
-static int virtio_device_get(QEMUFile *f, void *opaque, size_t size)
+static int virtio_device_get(QEMUFile *f, void *opaque, size_t size,
+ VMStateField *field)
{
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
DeviceClass *dc = DEVICE_CLASS(VIRTIO_DEVICE_GET_CLASS(vdev));