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