diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2017-01-24 19:25:19 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2017-01-24 19:25:19 +0000 |
commit | d264871209400fa22796d403c9e1ab288d4a5c6b (patch) | |
tree | 42b20911ca6a03218a1181185ac0b9a4630f7dc8 /hw | |
parent | a9e404600a9bd1e6a26431fc89e5069092e67f14 (diff) | |
parent | 46a02a745176e1ef30de41706b5da4f1bc7fc495 (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.c | 33 | ||||
-rw-r--r-- | hw/display/virtio-gpu.c | 40 | ||||
-rw-r--r-- | hw/intc/arm_gic_kvm.c | 17 | ||||
-rw-r--r-- | hw/intc/arm_gicv3_its_kvm.c | 20 | ||||
-rw-r--r-- | hw/intc/arm_gicv3_kvm.c | 19 | ||||
-rw-r--r-- | hw/intc/s390_flic_kvm.c | 8 | ||||
-rw-r--r-- | hw/misc/ivshmem.c | 14 | ||||
-rw-r--r-- | hw/net/e1000e.c | 2 | ||||
-rw-r--r-- | hw/net/vmxnet3.c | 26 | ||||
-rw-r--r-- | hw/nvram/eeprom93xx.c | 8 | ||||
-rw-r--r-- | hw/nvram/fw_cfg.c | 8 | ||||
-rw-r--r-- | hw/pci-bridge/ioh3420.c | 2 | ||||
-rw-r--r-- | hw/pci-bridge/xio3130_downstream.c | 2 | ||||
-rw-r--r-- | hw/pci-bridge/xio3130_upstream.c | 2 | ||||
-rw-r--r-- | hw/pci/msix.c | 8 | ||||
-rw-r--r-- | hw/pci/pci.c | 57 | ||||
-rw-r--r-- | hw/pci/shpc.c | 7 | ||||
-rw-r--r-- | hw/scsi/megasas.c | 2 | ||||
-rw-r--r-- | hw/scsi/scsi-bus.c | 8 | ||||
-rw-r--r-- | hw/scsi/vhost-scsi.c | 25 | ||||
-rw-r--r-- | hw/scsi/vmw_pvscsi.c | 2 | ||||
-rw-r--r-- | hw/timer/twl92230.c | 8 | ||||
-rw-r--r-- | hw/usb/bus.c | 19 | ||||
-rw-r--r-- | hw/usb/hcd-xhci.c | 2 | ||||
-rw-r--r-- | hw/usb/redirect.c | 26 | ||||
-rw-r--r-- | hw/virtio/vhost.c | 8 | ||||
-rw-r--r-- | hw/virtio/virtio-pci.c | 8 | ||||
-rw-r--r-- | hw/virtio/virtio.c | 15 |
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)); |