summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-02-07 20:40:36 +0000
committerPeter Maydell <peter.maydell@linaro.org>2018-02-07 20:40:36 +0000
commit7b213bb4755dc99e447c19c532768ef5105b9771 (patch)
treecc13202d4cc96c90b7ff3964a45343c6ab8f797e /hw
parent17a5bbb44df9a4a79166332bc26e2d8ca6bd8fa8 (diff)
parent19306806ae30b7fb5fe61a9130c6995402acad00 (diff)
downloadqemu-7b213bb4755dc99e447c19c532768ef5105b9771.tar.gz
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* socket option parsing fix (Daniel) * SCSI fixes (Fam) * Readline double-free fix (Greg) * More HVF attribution fixes (Izik) * WHPX (Windows Hypervisor Platform Extensions) support (Justin) * POLLHUP handler (Klim) * ivshmem fixes (Ladi) * memfd memory backend (Marc-André) * improved error message (Marcelo) * Memory fixes (Peter Xu, Zhecheng) * Remove obsolete code and comments (Peter M.) * qdev API improvements (Philippe) * Add CONFIG_I2C switch (Thomas) # gpg: Signature made Wed 07 Feb 2018 15:24:08 GMT # gpg: using RSA key BFFBD25F78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: (47 commits) Add the WHPX acceleration enlightenments Introduce the WHPX impl Add the WHPX vcpu API Add the Windows Hypervisor Platform accelerator. tests/test-filter-redirector: move close() tests: use memfd in vhost-user-test vhost-user-test: make read-guest-mem setup its own qemu tests: keep compiling failing vhost-user tests Add memfd based hostmem memfd: add hugetlbsize argument memfd: add hugetlb support memfd: add error argument, instead of perror() cpus: join thread when removing a vCPU cpus: hvf: unregister thread with RCU cpus: tcg: unregister thread with RCU, fix exiting of loop on unplug cpus: dummy: unregister thread with RCU, exit loop on unplug cpus: kvm: unregister thread with RCU cpus: hax: register/unregister thread with RCU, exit loop on unplug ivshmem: Disable irqfd on device reset ivshmem: Improve MSI irqfd error handling ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org> # Conflicts: # cpus.c
Diffstat (limited to 'hw')
-rw-r--r--hw/core/qdev.c24
-rw-r--r--hw/display/exynos4210_fimd.c2
-rw-r--r--hw/i2c/Makefile.objs2
-rw-r--r--hw/i386/kvm/i8254.c4
-rw-r--r--hw/i386/kvm/i8259.c3
-rw-r--r--hw/input/adb-kbd.c4
-rw-r--r--hw/input/adb-mouse.c4
-rw-r--r--hw/intc/arm_gic.c3
-rw-r--r--hw/intc/arm_gic_kvm.c7
-rw-r--r--hw/intc/arm_gicv3.c3
-rw-r--r--hw/intc/arm_gicv3_its_kvm.c3
-rw-r--r--hw/intc/arm_gicv3_kvm.c7
-rw-r--r--hw/intc/i8259.c3
-rw-r--r--hw/misc/ivshmem.c79
-rw-r--r--hw/net/vmxnet3.c4
-rw-r--r--hw/nvram/Makefile.objs2
-rw-r--r--hw/pci-bridge/gen_pcie_root_port.c3
-rw-r--r--hw/scsi/scsi-generic.c9
-rw-r--r--hw/scsi/vmw_pvscsi.c4
-rw-r--r--hw/timer/i8254.c3
-rw-r--r--hw/vfio/amd-xgbe.c4
-rw-r--r--hw/vfio/calxeda-xgmac.c4
-rw-r--r--hw/vfio/common.c16
-rw-r--r--hw/virtio/trace-events6
-rw-r--r--hw/virtio/vhost.c19
-rw-r--r--hw/virtio/virtio-pci.c4
26 files changed, 152 insertions, 74 deletions
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 2456035d1a..11f8a27a69 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -1075,6 +1075,30 @@ static void device_class_init(ObjectClass *class, void *data)
dc->user_creatable = true;
}
+void device_class_set_parent_reset(DeviceClass *dc,
+ DeviceReset dev_reset,
+ DeviceReset *parent_reset)
+{
+ *parent_reset = dc->reset;
+ dc->reset = dev_reset;
+}
+
+void device_class_set_parent_realize(DeviceClass *dc,
+ DeviceRealize dev_realize,
+ DeviceRealize *parent_realize)
+{
+ *parent_realize = dc->realize;
+ dc->realize = dev_realize;
+}
+
+void device_class_set_parent_unrealize(DeviceClass *dc,
+ DeviceUnrealize dev_unrealize,
+ DeviceUnrealize *parent_unrealize)
+{
+ *parent_unrealize = dc->unrealize;
+ dc->unrealize = dev_unrealize;
+}
+
void device_reset(DeviceState *dev)
{
DeviceClass *klass = DEVICE_GET_CLASS(dev);
diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c
index fd0b2bec65..86e37e93e9 100644
--- a/hw/display/exynos4210_fimd.c
+++ b/hw/display/exynos4210_fimd.c
@@ -98,7 +98,7 @@
#define FIMD_WINCON_BUFSTATUS ((1 << 21) | (1 << 31))
#define FIMD_WINCON_BUF0_STAT ((0 << 21) | (0 << 31))
#define FIMD_WINCON_BUF1_STAT ((1 << 21) | (0 << 31))
-#define FIMD_WINCON_BUF2_STAT ((0 << 21) | (1 << 31))
+#define FIMD_WINCON_BUF2_STAT ((0 << 21) | (1U << 31))
#define FIMD_WINCON_BUFSELECT ((1 << 20) | (1 << 30))
#define FIMD_WINCON_BUF0_SEL ((0 << 20) | (0 << 30))
#define FIMD_WINCON_BUF1_SEL ((1 << 20) | (0 << 30))
diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs
index 0594dea3ae..37cacde978 100644
--- a/hw/i2c/Makefile.objs
+++ b/hw/i2c/Makefile.objs
@@ -1,4 +1,4 @@
-common-obj-y += core.o smbus.o smbus_eeprom.o
+common-obj-$(CONFIG_I2C) += core.o smbus.o smbus_eeprom.o
common-obj-$(CONFIG_DDC) += i2c-ddc.o
common-obj-$(CONFIG_VERSATILE_I2C) += versatile_i2c.o
common-obj-$(CONFIG_ACPI_X86) += smbus_ich9.o
diff --git a/hw/i386/kvm/i8254.c b/hw/i386/kvm/i8254.c
index 521a58498a..13f20f47d9 100644
--- a/hw/i386/kvm/i8254.c
+++ b/hw/i386/kvm/i8254.c
@@ -315,8 +315,8 @@ static void kvm_pit_class_init(ObjectClass *klass, void *data)
PITCommonClass *k = PIT_COMMON_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
- kpc->parent_realize = dc->realize;
- dc->realize = kvm_pit_realizefn;
+ device_class_set_parent_realize(dc, kvm_pit_realizefn,
+ &kpc->parent_realize);
k->set_channel_gate = kvm_pit_set_gate;
k->get_channel_info = kvm_pit_get_channel_info;
dc->reset = kvm_pit_reset;
diff --git a/hw/i386/kvm/i8259.c b/hw/i386/kvm/i8259.c
index b91e98074e..05394cdb7b 100644
--- a/hw/i386/kvm/i8259.c
+++ b/hw/i386/kvm/i8259.c
@@ -142,8 +142,7 @@ static void kvm_i8259_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
dc->reset = kvm_pic_reset;
- kpc->parent_realize = dc->realize;
- dc->realize = kvm_pic_realize;
+ device_class_set_parent_realize(dc, kvm_pic_realize, &kpc->parent_realize);
k->pre_save = kvm_pic_get;
k->post_load = kvm_pic_put;
}
diff --git a/hw/input/adb-kbd.c b/hw/input/adb-kbd.c
index 354f56e41e..266aed1b7b 100644
--- a/hw/input/adb-kbd.c
+++ b/hw/input/adb-kbd.c
@@ -374,8 +374,8 @@ static void adb_kbd_class_init(ObjectClass *oc, void *data)
ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
ADBKeyboardClass *akc = ADB_KEYBOARD_CLASS(oc);
- akc->parent_realize = dc->realize;
- dc->realize = adb_kbd_realizefn;
+ device_class_set_parent_realize(dc, adb_kbd_realizefn,
+ &akc->parent_realize);
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
adc->devreq = adb_kbd_request;
diff --git a/hw/input/adb-mouse.c b/hw/input/adb-mouse.c
index c9004233b8..47e88faf25 100644
--- a/hw/input/adb-mouse.c
+++ b/hw/input/adb-mouse.c
@@ -228,8 +228,8 @@ static void adb_mouse_class_init(ObjectClass *oc, void *data)
ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
ADBMouseClass *amc = ADB_MOUSE_CLASS(oc);
- amc->parent_realize = dc->realize;
- dc->realize = adb_mouse_realizefn;
+ device_class_set_parent_realize(dc, adb_mouse_realizefn,
+ &amc->parent_realize);
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
adc->devreq = adb_mouse_request;
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 724bc9fa61..ea0323f969 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -1461,8 +1461,7 @@ static void arm_gic_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
ARMGICClass *agc = ARM_GIC_CLASS(klass);
- agc->parent_realize = dc->realize;
- dc->realize = arm_gic_realize;
+ device_class_set_parent_realize(dc, arm_gic_realize, &agc->parent_realize);
}
static const TypeInfo arm_gic_info = {
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index ae095d08a3..6f467e68a8 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -591,10 +591,9 @@ static void kvm_arm_gic_class_init(ObjectClass *klass, void *data)
agcc->pre_save = kvm_arm_gic_get;
agcc->post_load = kvm_arm_gic_put;
- kgc->parent_realize = dc->realize;
- kgc->parent_reset = dc->reset;
- dc->realize = kvm_arm_gic_realize;
- dc->reset = kvm_arm_gic_reset;
+ device_class_set_parent_realize(dc, kvm_arm_gic_realize,
+ &kgc->parent_realize);
+ device_class_set_parent_reset(dc, kvm_arm_gic_reset, &kgc->parent_reset);
}
static const TypeInfo kvm_arm_gic_info = {
diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
index f0c967b304..479c66733c 100644
--- a/hw/intc/arm_gicv3.c
+++ b/hw/intc/arm_gicv3.c
@@ -385,8 +385,7 @@ static void arm_gicv3_class_init(ObjectClass *klass, void *data)
ARMGICv3Class *agc = ARM_GICV3_CLASS(klass);
agcc->post_load = arm_gicv3_post_load;
- agc->parent_realize = dc->realize;
- dc->realize = arm_gic_realize;
+ device_class_set_parent_realize(dc, arm_gic_realize, &agc->parent_realize);
}
static const TypeInfo arm_gicv3_info = {
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
index bf290b8bff..eea6a73df2 100644
--- a/hw/intc/arm_gicv3_its_kvm.c
+++ b/hw/intc/arm_gicv3_its_kvm.c
@@ -245,11 +245,10 @@ static void kvm_arm_its_class_init(ObjectClass *klass, void *data)
dc->realize = kvm_arm_its_realize;
dc->props = kvm_arm_its_props;
- ic->parent_reset = dc->reset;
+ device_class_set_parent_reset(dc, kvm_arm_its_reset, &ic->parent_reset);
icc->send_msi = kvm_its_send_msi;
icc->pre_save = kvm_arm_its_pre_save;
icc->post_load = kvm_arm_its_post_load;
- dc->reset = kvm_arm_its_reset;
}
static const TypeInfo kvm_arm_its_info = {
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
index 481fe5405a..ec371772b3 100644
--- a/hw/intc/arm_gicv3_kvm.c
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -795,10 +795,9 @@ static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data)
agcc->pre_save = kvm_arm_gicv3_get;
agcc->post_load = kvm_arm_gicv3_put;
- kgc->parent_realize = dc->realize;
- kgc->parent_reset = dc->reset;
- dc->realize = kvm_arm_gicv3_realize;
- dc->reset = kvm_arm_gicv3_reset;
+ device_class_set_parent_realize(dc, kvm_arm_gicv3_realize,
+ &kgc->parent_realize);
+ device_class_set_parent_reset(dc, kvm_arm_gicv3_reset, &kgc->parent_reset);
}
static const TypeInfo kvm_arm_gicv3_info = {
diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c
index 1602255a87..76f3d873b8 100644
--- a/hw/intc/i8259.c
+++ b/hw/intc/i8259.c
@@ -443,8 +443,7 @@ static void i8259_class_init(ObjectClass *klass, void *data)
PICClass *k = PIC_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
- k->parent_realize = dc->realize;
- dc->realize = pic_realize;
+ device_class_set_parent_realize(dc, pic_realize, &k->parent_realize);
dc->reset = pic_reset;
}
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 4919011f38..16f03701b7 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -76,6 +76,7 @@ typedef struct Peer {
typedef struct MSIVector {
PCIDevice *pdev;
int virq;
+ bool unmasked;
} MSIVector;
typedef struct IVShmemState {
@@ -316,6 +317,11 @@ static int ivshmem_vector_unmask(PCIDevice *dev, unsigned vector,
int ret;
IVSHMEM_DPRINTF("vector unmask %p %d\n", dev, vector);
+ if (!v->pdev) {
+ error_report("ivshmem: vector %d route does not exist", vector);
+ return -EINVAL;
+ }
+ assert(!v->unmasked);
ret = kvm_irqchip_update_msi_route(kvm_state, v->virq, msg, dev);
if (ret < 0) {
@@ -323,22 +329,35 @@ static int ivshmem_vector_unmask(PCIDevice *dev, unsigned vector,
}
kvm_irqchip_commit_routes(kvm_state);
- return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, v->virq);
+ ret = kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, v->virq);
+ if (ret < 0) {
+ return ret;
+ }
+ v->unmasked = true;
+
+ return 0;
}
static void ivshmem_vector_mask(PCIDevice *dev, unsigned vector)
{
IVShmemState *s = IVSHMEM_COMMON(dev);
EventNotifier *n = &s->peers[s->vm_id].eventfds[vector];
+ MSIVector *v = &s->msi_vectors[vector];
int ret;
IVSHMEM_DPRINTF("vector mask %p %d\n", dev, vector);
+ if (!v->pdev) {
+ error_report("ivshmem: vector %d route does not exist", vector);
+ return;
+ }
+ assert(v->unmasked);
- ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n,
- s->msi_vectors[vector].virq);
- if (ret != 0) {
+ ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n, v->virq);
+ if (ret < 0) {
error_report("remove_irqfd_notifier_gsi failed");
+ return;
}
+ v->unmasked = false;
}
static void ivshmem_vector_poll(PCIDevice *dev,
@@ -738,10 +757,14 @@ static void ivshmem_msix_vector_use(IVShmemState *s)
}
}
+static void ivshmem_disable_irqfd(IVShmemState *s);
+
static void ivshmem_reset(DeviceState *d)
{
IVShmemState *s = IVSHMEM_COMMON(d);
+ ivshmem_disable_irqfd(s);
+
s->intrstatus = 0;
s->intrmask = 0;
if (ivshmem_has_feature(s, IVSHMEM_MSI)) {
@@ -766,6 +789,20 @@ static int ivshmem_setup_interrupts(IVShmemState *s, Error **errp)
return 0;
}
+static void ivshmem_remove_kvm_msi_virq(IVShmemState *s, int vector)
+{
+ IVSHMEM_DPRINTF("ivshmem_remove_kvm_msi_virq vector:%d\n", vector);
+
+ if (s->msi_vectors[vector].pdev == NULL) {
+ return;
+ }
+
+ /* it was cleaned when masked in the frontend. */
+ kvm_irqchip_release_virq(kvm_state, s->msi_vectors[vector].virq);
+
+ s->msi_vectors[vector].pdev = NULL;
+}
+
static void ivshmem_enable_irqfd(IVShmemState *s)
{
PCIDevice *pdev = PCI_DEVICE(s);
@@ -777,7 +814,7 @@ static void ivshmem_enable_irqfd(IVShmemState *s)
ivshmem_add_kvm_msi_virq(s, i, &err);
if (err) {
error_report_err(err);
- /* TODO do we need to handle the error? */
+ goto undo;
}
}
@@ -786,21 +823,14 @@ static void ivshmem_enable_irqfd(IVShmemState *s)
ivshmem_vector_mask,
ivshmem_vector_poll)) {
error_report("ivshmem: msix_set_vector_notifiers failed");
+ goto undo;
}
-}
+ return;
-static void ivshmem_remove_kvm_msi_virq(IVShmemState *s, int vector)
-{
- IVSHMEM_DPRINTF("ivshmem_remove_kvm_msi_virq vector:%d\n", vector);
-
- if (s->msi_vectors[vector].pdev == NULL) {
- return;
+undo:
+ while (--i >= 0) {
+ ivshmem_remove_kvm_msi_virq(s, i);
}
-
- /* it was cleaned when masked in the frontend. */
- kvm_irqchip_release_virq(kvm_state, s->msi_vectors[vector].virq);
-
- s->msi_vectors[vector].pdev = NULL;
}
static void ivshmem_disable_irqfd(IVShmemState *s)
@@ -808,11 +838,24 @@ static void ivshmem_disable_irqfd(IVShmemState *s)
PCIDevice *pdev = PCI_DEVICE(s);
int i;
+ if (!pdev->msix_vector_use_notifier) {
+ return;
+ }
+
+ msix_unset_vector_notifiers(pdev);
+
for (i = 0; i < s->peers[s->vm_id].nb_eventfds; i++) {
+ /*
+ * MSI-X is already disabled here so msix_unset_vector_notifiers()
+ * didn't call our release notifier. Do it now to keep our masks and
+ * unmasks balanced.
+ */
+ if (s->msi_vectors[i].unmasked) {
+ ivshmem_vector_mask(pdev, i);
+ }
ivshmem_remove_kvm_msi_virq(s, i);
}
- msix_unset_vector_notifiers(pdev);
}
static void ivshmem_write_config(PCIDevice *pdev, uint32_t address,
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 0654d594c1..3648630386 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -2664,8 +2664,8 @@ static void vmxnet3_class_init(ObjectClass *class, void *data)
c->class_id = PCI_CLASS_NETWORK_ETHERNET;
c->subsystem_vendor_id = PCI_VENDOR_ID_VMWARE;
c->subsystem_id = PCI_DEVICE_ID_VMWARE_VMXNET3;
- vc->parent_dc_realize = dc->realize;
- dc->realize = vmxnet3_realize;
+ device_class_set_parent_realize(dc, vmxnet3_realize,
+ &vc->parent_dc_realize);
dc->desc = "VMWare Paravirtualized Ethernet v3";
dc->reset = vmxnet3_qdev_reset;
dc->vmsd = &vmstate_vmxnet3;
diff --git a/hw/nvram/Makefile.objs b/hw/nvram/Makefile.objs
index 0f4ee71dcb..a912d25391 100644
--- a/hw/nvram/Makefile.objs
+++ b/hw/nvram/Makefile.objs
@@ -1,6 +1,6 @@
common-obj-$(CONFIG_DS1225Y) += ds1225y.o
common-obj-y += eeprom93xx.o
-common-obj-y += eeprom_at24c.o
+common-obj-$(CONFIG_I2C) += eeprom_at24c.o
common-obj-y += fw_cfg.o
common-obj-y += chrp_nvram.o
common-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o
diff --git a/hw/pci-bridge/gen_pcie_root_port.c b/hw/pci-bridge/gen_pcie_root_port.c
index 0e2f2e8bf1..3dbacc6cea 100644
--- a/hw/pci-bridge/gen_pcie_root_port.c
+++ b/hw/pci-bridge/gen_pcie_root_port.c
@@ -137,8 +137,7 @@ static void gen_rp_dev_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_rp_dev;
dc->props = gen_rp_props;
- rpc->parent_realize = dc->realize;
- dc->realize = gen_rp_realize;
+ device_class_set_parent_realize(dc, gen_rp_realize, &rpc->parent_realize);
rpc->aer_vector = gen_rp_aer_vector;
rpc->interrupts_init = gen_rp_interrupts_init;
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
index ba70c0dc19..7414fe2d67 100644
--- a/hw/scsi/scsi-generic.c
+++ b/hw/scsi/scsi-generic.c
@@ -482,7 +482,6 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp)
int rc;
int sg_version;
struct sg_scsi_id scsiid;
- Error *local_err = NULL;
if (!s->conf.blk) {
error_setg(errp, "drive property not set");
@@ -516,11 +515,9 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp)
error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
return;
}
- blkconf_apply_backend_options(&s->conf,
- blk_is_read_only(s->conf.blk),
- true, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
+ if (!blkconf_apply_backend_options(&s->conf,
+ blk_is_read_only(s->conf.blk),
+ true, errp)) {
return;
}
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index 27749c0e42..a3a019e30a 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -1284,8 +1284,8 @@ static void pvscsi_class_init(ObjectClass *klass, void *data)
k->device_id = PCI_DEVICE_ID_VMWARE_PVSCSI;
k->class_id = PCI_CLASS_STORAGE_SCSI;
k->subsystem_id = 0x1000;
- pvs_k->parent_dc_realize = dc->realize;
- dc->realize = pvscsi_realize;
+ device_class_set_parent_realize(dc, pvscsi_realize,
+ &pvs_k->parent_dc_realize);
dc->reset = pvscsi_reset;
dc->vmsd = &vmstate_pvscsi;
dc->props = pvscsi_properties;
diff --git a/hw/timer/i8254.c b/hw/timer/i8254.c
index dbc4a0baec..1057850808 100644
--- a/hw/timer/i8254.c
+++ b/hw/timer/i8254.c
@@ -358,8 +358,7 @@ static void pit_class_initfn(ObjectClass *klass, void *data)
PITCommonClass *k = PIT_COMMON_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
- pc->parent_realize = dc->realize;
- dc->realize = pit_realizefn;
+ device_class_set_parent_realize(dc, pit_realizefn, &pc->parent_realize);
k->set_channel_gate = pit_set_channel_gate;
k->get_channel_info = pit_get_channel_info_common;
k->post_load = pit_post_load;
diff --git a/hw/vfio/amd-xgbe.c b/hw/vfio/amd-xgbe.c
index fab196cebf..0c4ec4ba25 100644
--- a/hw/vfio/amd-xgbe.c
+++ b/hw/vfio/amd-xgbe.c
@@ -34,8 +34,8 @@ static void vfio_amd_xgbe_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
VFIOAmdXgbeDeviceClass *vcxc =
VFIO_AMD_XGBE_DEVICE_CLASS(klass);
- vcxc->parent_realize = dc->realize;
- dc->realize = amd_xgbe_realize;
+ device_class_set_parent_realize(dc, amd_xgbe_realize,
+ &vcxc->parent_realize);
dc->desc = "VFIO AMD XGBE";
dc->vmsd = &vfio_platform_amd_xgbe_vmstate;
/* Supported by TYPE_VIRT_MACHINE */
diff --git a/hw/vfio/calxeda-xgmac.c b/hw/vfio/calxeda-xgmac.c
index 7bb17af7ad..24cee6d065 100644
--- a/hw/vfio/calxeda-xgmac.c
+++ b/hw/vfio/calxeda-xgmac.c
@@ -34,8 +34,8 @@ static void vfio_calxeda_xgmac_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
VFIOCalxedaXgmacDeviceClass *vcxc =
VFIO_CALXEDA_XGMAC_DEVICE_CLASS(klass);
- vcxc->parent_realize = dc->realize;
- dc->realize = calxeda_xgmac_realize;
+ device_class_set_parent_realize(dc, calxeda_xgmac_realize,
+ &vcxc->parent_realize);
dc->desc = "VFIO Calxeda XGMAC";
dc->vmsd = &vfio_platform_calxeda_xgmac_vmstate;
/* Supported by TYPE_VIRT_MACHINE */
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index ee9240daeb..f895e3c335 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -1187,19 +1187,27 @@ static void vfio_disconnect_container(VFIOGroup *group)
{
VFIOContainer *container = group->container;
+ QLIST_REMOVE(group, container_next);
+ group->container = NULL;
+
+ /*
+ * Explicitly release the listener first before unset container,
+ * since unset may destroy the backend container if it's the last
+ * group.
+ */
+ if (QLIST_EMPTY(&container->group_list)) {
+ vfio_listener_release(container);
+ }
+
if (ioctl(group->fd, VFIO_GROUP_UNSET_CONTAINER, &container->fd)) {
error_report("vfio: error disconnecting group %d from container",
group->groupid);
}
- QLIST_REMOVE(group, container_next);
- group->container = NULL;
-
if (QLIST_EMPTY(&container->group_list)) {
VFIOAddressSpace *space = container->space;
VFIOGuestIOMMU *giommu, *tmp;
- vfio_listener_release(container);
QLIST_REMOVE(container, next);
QLIST_FOREACH_SAFE(giommu, &container->giommu_list, giommu_next, tmp) {
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 775461ae98..2b8f81eb25 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -25,3 +25,9 @@ virtio_balloon_handle_output(const char *name, uint64_t gpa) "section name: %s g
virtio_balloon_get_config(uint32_t num_pages, uint32_t actual) "num_pages: %d actual: %d"
virtio_balloon_set_config(uint32_t actual, uint32_t oldactual) "actual: %d oldactual: %d"
virtio_balloon_to_target(uint64_t target, uint32_t num_pages) "balloon target: 0x%"PRIx64" num_pages: %d"
+
+# hw/virtio/vhost.c
+vhost_region_add(void *p, const char *mr) "dev %p mr %s"
+vhost_region_del(void *p, const char *mr) "dev %p mr %s"
+vhost_iommu_region_add(void *p, const char *mr) "dev %p mr %s"
+vhost_iommu_region_del(void *p, const char *mr) "dev %p mr %s"
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 386aef85be..338e4395b7 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -27,6 +27,7 @@
#include "hw/virtio/virtio-access.h"
#include "migration/blocker.h"
#include "sysemu/dma.h"
+#include "trace.h"
/* enabled until disconnected backend stabilizes */
#define _VHOST_DEBUG 1
@@ -329,6 +330,7 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev)
static struct vhost_log *vhost_log_alloc(uint64_t size, bool share)
{
+ Error *err = NULL;
struct vhost_log *log;
uint64_t logsize = size * sizeof(*(log->log));
int fd = -1;
@@ -337,7 +339,12 @@ static struct vhost_log *vhost_log_alloc(uint64_t size, bool share)
if (share) {
log->log = qemu_memfd_alloc("vhost-log", logsize,
F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL,
- &fd);
+ &fd, &err);
+ if (err) {
+ error_report_err(err);
+ g_free(log);
+ return NULL;
+ }
memset(log->log, 0, logsize);
} else {
log->log = g_malloc0(logsize);
@@ -687,6 +694,7 @@ static void vhost_region_add(MemoryListener *listener,
return;
}
+ trace_vhost_region_add(dev, section->mr->name ?: NULL);
++dev->n_mem_sections;
dev->mem_sections = g_renew(MemoryRegionSection, dev->mem_sections,
dev->n_mem_sections);
@@ -706,6 +714,7 @@ static void vhost_region_del(MemoryListener *listener,
return;
}
+ trace_vhost_region_del(dev, section->mr->name ?: NULL);
vhost_set_memory(listener, section, false);
memory_region_unref(section->mr);
for (i = 0; i < dev->n_mem_sections; ++i) {
@@ -743,6 +752,8 @@ static void vhost_iommu_region_add(MemoryListener *listener,
return;
}
+ trace_vhost_iommu_region_add(dev, section->mr->name ?: NULL);
+
iommu = g_malloc0(sizeof(*iommu));
end = int128_add(int128_make64(section->offset_within_region),
section->size);
@@ -771,6 +782,8 @@ static void vhost_iommu_region_del(MemoryListener *listener,
return;
}
+ trace_vhost_iommu_region_del(dev, section->mr->name ?: NULL);
+
QLIST_FOREACH(iommu, &dev->iommu_list, iommu_next) {
if (iommu->mr == section->mr &&
iommu->n.start == section->offset_within_region) {
@@ -1361,10 +1374,6 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
if (hdev->mem) {
/* those are only safe after successful init */
memory_listener_unregister(&hdev->memory_listener);
- for (i = 0; i < hdev->n_mem_sections; ++i) {
- MemoryRegionSection *section = &hdev->mem_sections[i];
- memory_region_unref(section->mr);
- }
QLIST_REMOVE(hdev, entry);
}
if (hdev->migration_blocker) {
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 9ae10f0cdd..c20537f31d 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1907,8 +1907,8 @@ static void virtio_pci_class_init(ObjectClass *klass, void *data)
k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
k->revision = VIRTIO_PCI_ABI_VERSION;
k->class_id = PCI_CLASS_OTHERS;
- vpciklass->parent_dc_realize = dc->realize;
- dc->realize = virtio_pci_dc_realize;
+ device_class_set_parent_realize(dc, virtio_pci_dc_realize,
+ &vpciklass->parent_dc_realize);
dc->reset = virtio_pci_reset;
}