|
|
bacd9b |
From 96412e68c312ae4d91d6febc2284951f8b295ef7 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
|
|
|
45bdef |
index be18e92..1a363ca 100644
|
|
|
298366 |
--- a/hw/virtio/virtio-pci.c
|
|
|
298366 |
+++ b/hw/virtio/virtio-pci.c
|
|
|
45bdef |
@@ -1001,6 +1001,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);
|
|
|
45bdef |
@@ -1015,9 +1024,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)
|
|
|
45bdef |
@@ -1552,6 +1559,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 = {
|