|
|
958e1b |
From fdad8c197b91f1010e4f61147f27513a4f061e40 Mon Sep 17 00:00:00 2001
|
|
|
958e1b |
From: Alex Williamson <alex.williamson@redhat.com>
|
|
|
958e1b |
Date: Mon, 12 Jan 2015 04:52:17 +0100
|
|
|
958e1b |
Subject: [PATCH 1/3] vfio-pci: Fix interrupt disabling
|
|
|
958e1b |
|
|
|
958e1b |
Message-id: <20150112045144.9215.59820.stgit@gimli.home>
|
|
|
958e1b |
Patchwork-id: 63242
|
|
|
958e1b |
O-Subject: [RHEL7.1 qemu-kvm PATCH] vfio-pci: Fix interrupt disabling
|
|
|
958e1b |
Bugzilla: 1180942
|
|
|
958e1b |
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
958e1b |
RH-Acked-by: Bandan Das <bsd@redhat.com>
|
|
|
958e1b |
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
958e1b |
|
|
|
958e1b |
Upstream: b3e27c3aee8f5a96debfe0346e9c0e3a641a8516
|
|
|
958e1b |
|
|
|
958e1b |
When disabling MSI/X interrupts the disable functions will leave the
|
|
|
958e1b |
device in INTx mode (when available). This matches how hardware
|
|
|
958e1b |
operates, INTx is enabled unless MSI/X is enabled (DisINTx is handled
|
|
|
958e1b |
separately). Therefore when we really want to disable all interrupts,
|
|
|
958e1b |
such as when removing the device, and we start with the device in
|
|
|
958e1b |
MSI/X mode, we need to pass through INTx on our way to being
|
|
|
958e1b |
completely quiesced.
|
|
|
958e1b |
|
|
|
958e1b |
In well behaved situations, the guest driver will have shutdown the
|
|
|
958e1b |
device and it will start vfio_exitfn() in INTx mode, producing the
|
|
|
958e1b |
desired result. If hot-unplug causes the guest to crash, we may get
|
|
|
958e1b |
the device in MSI/X state, which will leave QEMU with a bogus handler
|
|
|
958e1b |
installed.
|
|
|
958e1b |
|
|
|
958e1b |
Fix this by re-ordering our disable routine so that it should always
|
|
|
958e1b |
finish in VFIO_INT_NONE state, which is what all callers expect.
|
|
|
958e1b |
|
|
|
958e1b |
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
|
|
|
958e1b |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
958e1b |
---
|
|
|
958e1b |
hw/misc/vfio.c | 21 ++++++++++++---------
|
|
|
958e1b |
1 file changed, 12 insertions(+), 9 deletions(-)
|
|
|
958e1b |
|
|
|
958e1b |
diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
|
|
|
958e1b |
index abaa4c1..40b0923 100644
|
|
|
958e1b |
--- a/hw/misc/vfio.c
|
|
|
958e1b |
+++ b/hw/misc/vfio.c
|
|
|
958e1b |
@@ -2353,16 +2353,19 @@ static void vfio_listener_release(VFIOContainer *container)
|
|
|
958e1b |
*/
|
|
|
958e1b |
static void vfio_disable_interrupts(VFIODevice *vdev)
|
|
|
958e1b |
{
|
|
|
958e1b |
- switch (vdev->interrupt) {
|
|
|
958e1b |
- case VFIO_INT_INTx:
|
|
|
958e1b |
- vfio_disable_intx(vdev);
|
|
|
958e1b |
- break;
|
|
|
958e1b |
- case VFIO_INT_MSI:
|
|
|
958e1b |
- vfio_disable_msi(vdev);
|
|
|
958e1b |
- break;
|
|
|
958e1b |
- case VFIO_INT_MSIX:
|
|
|
958e1b |
+ /*
|
|
|
958e1b |
+ * More complicated than it looks. Disabling MSI/X transitions the
|
|
|
958e1b |
+ * device to INTx mode (if supported). Therefore we need to first
|
|
|
958e1b |
+ * disable MSI/X and then cleanup by disabling INTx.
|
|
|
958e1b |
+ */
|
|
|
958e1b |
+ if (vdev->interrupt == VFIO_INT_MSIX) {
|
|
|
958e1b |
vfio_disable_msix(vdev);
|
|
|
958e1b |
- break;
|
|
|
958e1b |
+ } else if (vdev->interrupt == VFIO_INT_MSI) {
|
|
|
958e1b |
+ vfio_disable_msi(vdev);
|
|
|
958e1b |
+ }
|
|
|
958e1b |
+
|
|
|
958e1b |
+ if (vdev->interrupt == VFIO_INT_INTx) {
|
|
|
958e1b |
+ vfio_disable_intx(vdev);
|
|
|
958e1b |
}
|
|
|
958e1b |
}
|
|
|
958e1b |
|
|
|
958e1b |
--
|
|
|
958e1b |
1.8.3.1
|
|
|
958e1b |
|