0a122b
From ad9077535a9a32543cd3e7a6d1cacbc37bc27125 Mon Sep 17 00:00:00 2001
0a122b
From: Markus Armbruster <armbru@redhat.com>
0a122b
Date: Thu, 23 Jan 2014 14:03:40 +0100
0a122b
Subject: [PATCH 13/14] virtio-pci: add device_unplugged callback
0a122b
0a122b
RH-Author: Markus Armbruster <armbru@redhat.com>
0a122b
Message-id: <1390485820-7585-11-git-send-email-armbru@redhat.com>
0a122b
Patchwork-id: 56929
0a122b
O-Subject: [PATCH 7.0 qemu-kvm 10/10] virtio-pci: add device_unplugged callback
0a122b
Bugzilla: 983344
0a122b
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
0a122b
RH-Acked-by: Marcel Apfelbaum <marcel.a@redhat.com>
0a122b
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
0a122b
0a122b
From: Paolo Bonzini <pbonzini@redhat.com>
0a122b
0a122b
This fixes a crash in hot-unplug of virtio-pci devices behind a PCIe
0a122b
switch.  The crash happens because the ioeventfd is still set whent the
0a122b
child is destroyed (destruction happens in postorder).  Then the proxy
0a122b
tries to unset to ioeventfd, but the virtqueue structure that holds the
0a122b
EventNotifier has been trashed in the meanwhile.  kvm_set_ioeventfd_pio
0a122b
does not expect failure and aborts.
0a122b
0a122b
The fix is simply to move parts of uninitialization to a new
0a122b
device_unplugged callback, which is called before the child is destroyed.
0a122b
0a122b
Cc: qemu-stable@nongnu.org
0a122b
Acked-by: Andreas Faerber <afaerber@suse.de>
0a122b
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
0a122b
(cherry picked from commit 06a1307379fcd6c551185ad87679cd7ed896b9ea)
0a122b
Signed-off-by: Markus Armbruster <armbru@redhat.com>
0a122b
---
0a122b
 hw/virtio/virtio-pci.c | 12 ++++++++++--
0a122b
 1 file changed, 10 insertions(+), 2 deletions(-)
0a122b
0a122b
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
0a122b
---
0a122b
 hw/virtio/virtio-pci.c |   12 ++++++++++--
0a122b
 1 files changed, 10 insertions(+), 2 deletions(-)
0a122b
0a122b
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
0a122b
index 02ddbe9..00df4aa 100644
0a122b
--- a/hw/virtio/virtio-pci.c
0a122b
+++ b/hw/virtio/virtio-pci.c
0a122b
@@ -1007,6 +1007,15 @@ static void virtio_pci_device_plugged(DeviceState *d)
0a122b
                                                       proxy->host_features);
0a122b
 }
0a122b
 
0a122b
+static void virtio_pci_device_unplugged(DeviceState *d)
0a122b
+{
0a122b
+    PCIDevice *pci_dev = PCI_DEVICE(d);
0a122b
+    VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
0a122b
+
0a122b
+    virtio_pci_stop_ioeventfd(proxy);
0a122b
+    msix_uninit_exclusive_bar(pci_dev);
0a122b
+}
0a122b
+
0a122b
 static int virtio_pci_init(PCIDevice *pci_dev)
0a122b
 {
0a122b
     VirtIOPCIProxy *dev = VIRTIO_PCI(pci_dev);
0a122b
@@ -1021,9 +1030,7 @@ static int virtio_pci_init(PCIDevice *pci_dev)
0a122b
 static void virtio_pci_exit(PCIDevice *pci_dev)
0a122b
 {
0a122b
     VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev);
0a122b
-    virtio_pci_stop_ioeventfd(proxy);
0a122b
     memory_region_destroy(&proxy->bar);
0a122b
-    msix_uninit_exclusive_bar(pci_dev);
0a122b
 }
0a122b
 
0a122b
 static void virtio_pci_reset(DeviceState *qdev)
0a122b
@@ -1557,6 +1564,7 @@ static void virtio_pci_bus_class_init(ObjectClass *klass, void *data)
0a122b
     k->set_guest_notifiers = virtio_pci_set_guest_notifiers;
0a122b
     k->vmstate_change = virtio_pci_vmstate_change;
0a122b
     k->device_plugged = virtio_pci_device_plugged;
0a122b
+    k->device_unplugged = virtio_pci_device_unplugged;
0a122b
 }
0a122b
 
0a122b
 static const TypeInfo virtio_pci_bus_info = {
0a122b
-- 
0a122b
1.7.1
0a122b