cryptospore / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone
2382db
From bdd720aafc6099e126b682f70e4163e1b2097594 Mon Sep 17 00:00:00 2001
2382db
From: Alex Williamson <alex.williamson@redhat.com>
2382db
Date: Thu, 7 Aug 2014 21:03:14 +0200
2382db
Subject: [PATCH 06/10] vfio: Fix MSI-X vector expansion
2382db
2382db
Message-id: <20140807210314.11689.89693.stgit@gimli.home>
2382db
Patchwork-id: 60482
2382db
O-Subject: [RHEL7.0/z qemu-kvm PATCH v2 5/6] vfio: Fix MSI-X vector expansion
2382db
Bugzilla: 1110693 1110695
2382db
RH-Acked-by: Bandan Das <bsd@redhat.com>
2382db
RH-Acked-by: Amos Kong <akong@redhat.com>
2382db
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
2382db
2382db
Upstream: c048be5cc92ae201c339d46984476c4629275ed6
2382db
2382db
When new MSI-X vectors are enabled we need to disable MSI-X and
2382db
re-enable it with the correct number of vectors.  That means we need
2382db
to reprogram the eventfd triggers for each vector.  Prior to f4d45d47
2382db
vector->use tracked whether a vector was masked or unmasked and we
2382db
could always pick the KVM path when available for unmasked vectors.
2382db
Now vfio doesn't track mask state itself and vector->use and virq
2382db
remains configured even for masked vectors.  Therefore we need to ask
2382db
the MSI-X code whether a vector is masked in order to select the
2382db
correct signaling path.  As noted in the comment, MSI relies on
2382db
hardware to handle masking.
2382db
2382db
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
2382db
Cc: qemu-stable@nongnu.org # QEMU 2.1
2382db
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
2382db
---
2382db
 hw/misc/vfio.c |   38 +++++++++++++++++++++++++++++---------
2382db
 1 files changed, 29 insertions(+), 9 deletions(-)
2382db
2382db
diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
2382db
index bd37924..688e2ef 100644
2382db
--- a/hw/misc/vfio.c
2382db
+++ b/hw/misc/vfio.c
2382db
@@ -119,11 +119,20 @@ typedef struct VFIOINTx {
2382db
 } VFIOINTx;
2382db
 
2382db
 typedef struct VFIOMSIVector {
2382db
-    EventNotifier interrupt; /* eventfd triggered on interrupt */
2382db
-    EventNotifier kvm_interrupt; /* eventfd triggered for KVM irqfd bypass */
2382db
+    /*
2382db
+     * Two interrupt paths are configured per vector.  The first, is only used
2382db
+     * for interrupts injected via QEMU.  This is typically the non-accel path,
2382db
+     * but may also be used when we want QEMU to handle masking and pending
2382db
+     * bits.  The KVM path bypasses QEMU and is therefore higher performance,
2382db
+     * but requires masking at the device.  virq is used to track the MSI route
2382db
+     * through KVM, thus kvm_interrupt is only available when virq is set to a
2382db
+     * valid (>= 0) value.
2382db
+     */
2382db
+    EventNotifier interrupt;
2382db
+    EventNotifier kvm_interrupt;
2382db
     struct VFIODevice *vdev; /* back pointer to device */
2382db
     MSIMessage msg; /* cache the MSI message so we know when it changes */
2382db
-    int virq; /* KVM irqchip route for QEMU bypass */
2382db
+    int virq;
2382db
     bool use;
2382db
 } VFIOMSIVector;
2382db
 
2382db
@@ -662,13 +671,24 @@ static int vfio_enable_vectors(VFIODevice *vdev, bool msix)
2382db
     fds = (int32_t *)&irq_set->data;
2382db
 
2382db
     for (i = 0; i < vdev->nr_vectors; i++) {
2382db
-        if (!vdev->msi_vectors[i].use) {
2382db
-            fds[i] = -1;
2382db
-        } else if (vdev->msi_vectors[i].virq >= 0) {
2382db
-            fds[i] = event_notifier_get_fd(&vdev->msi_vectors[i].kvm_interrupt);
2382db
-        } else {
2382db
-            fds[i] = event_notifier_get_fd(&vdev->msi_vectors[i].interrupt);
2382db
+        int fd = -1;
2382db
+
2382db
+        /*
2382db
+         * MSI vs MSI-X - The guest has direct access to MSI mask and pending
2382db
+         * bits, therefore we always use the KVM signaling path when setup.
2382db
+         * MSI-X mask and pending bits are emulated, so we want to use the
2382db
+         * KVM signaling path only when configured and unmasked.
2382db
+         */
2382db
+        if (vdev->msi_vectors[i].use) {
2382db
+            if (vdev->msi_vectors[i].virq < 0 ||
2382db
+                (msix && msix_is_masked(&vdev->pdev, i))) {
2382db
+                fd = event_notifier_get_fd(&vdev->msi_vectors[i].interrupt);
2382db
+            } else {
2382db
+                fd = event_notifier_get_fd(&vdev->msi_vectors[i].kvm_interrupt);
2382db
+            }
2382db
         }
2382db
+
2382db
+        fds[i] = fd;
2382db
     }
2382db
 
2382db
     ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
2382db
-- 
2382db
1.7.1
2382db