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