Blame 0016-virtio-pci-add-device_unplugged-callback.patch

298366
From cb2282d55ee34d04a67d74111d69ab098f765680 Mon Sep 17 00:00:00 2001
298366
From: Paolo Bonzini <pbonzini@redhat.com>
298366
Date: Fri, 20 Sep 2013 16:58:00 +0200
298366
Subject: [PATCH] virtio-pci: add device_unplugged callback
298366
298366
This fixes a crash in hot-unplug of virtio-pci devices behind a PCIe
298366
switch.  The crash happens because the ioeventfd is still set whent the
298366
child is destroyed (destruction happens in postorder).  Then the proxy
298366
tries to unset to ioeventfd, but the virtqueue structure that holds the
298366
EventNotifier has been trashed in the meanwhile.  kvm_set_ioeventfd_pio
298366
does not expect failure and aborts.
298366
298366
The fix is simply to move parts of uninitialization to a new
298366
device_unplugged callback, which is called before the child is destroyed.
298366
298366
Cc: qemu-stable@nongnu.org
298366
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
298366
---
298366
 hw/virtio/virtio-pci.c | 12 ++++++++++--
298366
 1 file changed, 10 insertions(+), 2 deletions(-)
298366
298366
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
298366
index 6fd6d6d..242ec3e 100644
298366
--- a/hw/virtio/virtio-pci.c
298366
+++ b/hw/virtio/virtio-pci.c
298366
@@ -1000,6 +1000,15 @@ static void virtio_pci_device_plugged(DeviceState *d)
298366
                                                       proxy->host_features);
298366
 }
298366
 
298366
+static void virtio_pci_device_unplugged(DeviceState *d)
298366
+{
298366
+    PCIDevice *pci_dev = PCI_DEVICE(d);
298366
+    VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
298366
+
298366
+    virtio_pci_stop_ioeventfd(proxy);
298366
+    msix_uninit_exclusive_bar(pci_dev);
298366
+}
298366
+
298366
 static int virtio_pci_init(PCIDevice *pci_dev)
298366
 {
298366
     VirtIOPCIProxy *dev = VIRTIO_PCI(pci_dev);
298366
@@ -1014,9 +1023,7 @@ static int virtio_pci_init(PCIDevice *pci_dev)
298366
 static void virtio_pci_exit(PCIDevice *pci_dev)
298366
 {
298366
     VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev);
298366
-    virtio_pci_stop_ioeventfd(proxy);
298366
     memory_region_destroy(&proxy->bar);
298366
-    msix_uninit_exclusive_bar(pci_dev);
298366
 }
298366
 
298366
 static void virtio_pci_reset(DeviceState *qdev)
298366
@@ -1550,6 +1557,7 @@ static void virtio_pci_bus_class_init(ObjectClass *klass, void *data)
298366
     k->set_guest_notifiers = virtio_pci_set_guest_notifiers;
298366
     k->vmstate_change = virtio_pci_vmstate_change;
298366
     k->device_plugged = virtio_pci_device_plugged;
298366
+    k->device_unplugged = virtio_pci_device_unplugged;
298366
 }
298366
 
298366
 static const TypeInfo virtio_pci_bus_info = {