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