[RFC PATCH 01/10] vfio/pci: Use the write side of EventNotifier for IRQ signaling

Scott J. Goldman posted 10 patches 6 days, 11 hours ago
Maintainers: Paolo Bonzini <pbonzini@redhat.com>, Roman Bolshakov <rbolshakov@ddn.com>, Phil Dennis-Jordan <phil@philjordan.eu>, "Michael S. Tsirkin" <mst@redhat.com>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, Pierrick Bouvier <pierrick.bouvier@linaro.org>, John Levon <john.levon@nutanix.com>, Thanos Makatos <thanos.makatos@nutanix.com>, "Cédric Le Goater" <clg@redhat.com>, Alex Williamson <alex@shazbot.org>, Tony Krowiak <akrowiak@linux.ibm.com>, Halil Pasic <pasic@linux.ibm.com>, Jason Herne <jjherne@linux.ibm.com>, Cornelia Huck <cohuck@redhat.com>, Eric Farman <farman@linux.ibm.com>, Matthew Rosato <mjrosato@linux.ibm.com>, "Scott J. Goldman" <scottjgo@gmail.com>, "Marc-André Lureau" <marcandre.lureau@redhat.com>, "Daniel P. Berrangé" <berrange@redhat.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>
[RFC PATCH 01/10] vfio/pci: Use the write side of EventNotifier for IRQ signaling
Posted by Scott J. Goldman 6 days, 11 hours ago
When passing an fd to a vfio-user server for interrupt signaling, the
write side of the EventNotifier must be used. For eventfd-backed
notifiers the read and write descriptors are the same, so the existing
kernel VFIO path is unchanged. However, on hosts that emulate
EventNotifier with a pipe pair (e.g. macOS), event_notifier_get_fd()
returns the read side, which the vfio-user server cannot write to.

Introduce vfio_irq_signal_fd() which returns event_notifier_get_wfd()
and use it at every site in vfio/pci that hands an fd to
vfio_device_irq_set_signaling() or the bulk IRQ path. The
qemu_set_fd_handler() calls continue to use the read fd as before.

Signed-off-by: Scott J. Goldman <scottjgo@gmail.com>
---
 hw/vfio/pci.c | 33 +++++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 1945751ffd..ee1a42e7e0 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -80,6 +80,17 @@ static bool vfio_notifier_init(VFIOPCIDevice *vdev, EventNotifier *e,
     return true;
 }
 
+/*
+ * Return the fd that the vfio kernel driver or vfio-user server should
+ * write to in order to signal an interrupt.  For eventfd-backed notifiers
+ * this is the same descriptor QEMU reads, but on hosts that emulate
+ * EventNotifier with a pipe pair the write side must be used instead.
+ */
+static int vfio_irq_signal_fd(EventNotifier *e)
+{
+    return event_notifier_get_wfd(e);
+}
+
 static void vfio_notifier_cleanup(VFIOPCIDevice *vdev, EventNotifier *e,
                                   const char *name, int nr)
 {
@@ -378,7 +389,9 @@ static bool vfio_intx_enable(VFIOPCIDevice *vdev, Error **errp)
     }
 
     if (!vfio_device_irq_set_signaling(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX, 0,
-                                VFIO_IRQ_SET_ACTION_TRIGGER, fd, errp)) {
+                                VFIO_IRQ_SET_ACTION_TRIGGER,
+                                vfio_irq_signal_fd(&vdev->intx.interrupt),
+                                errp)) {
         qemu_set_fd_handler(fd, NULL, NULL, vdev);
         vfio_notifier_cleanup(vdev, &vdev->intx.interrupt, "intx-interrupt", 0);
         return false;
@@ -548,9 +561,9 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix)
         if (vdev->msi_vectors[i].use) {
             if (vdev->msi_vectors[i].virq < 0 ||
                 (msix && msix_is_masked(pdev, i))) {
-                fd = event_notifier_get_fd(&vdev->msi_vectors[i].interrupt);
+                fd = vfio_irq_signal_fd(&vdev->msi_vectors[i].interrupt);
             } else {
-                fd = event_notifier_get_fd(&vdev->msi_vectors[i].kvm_interrupt);
+                fd = vfio_irq_signal_fd(&vdev->msi_vectors[i].kvm_interrupt);
             }
         }
 
@@ -628,9 +641,9 @@ static void set_irq_signalling(VFIODevice *vbasedev, VFIOMSIVector *vector,
     int32_t fd;
 
     if (vector->virq >= 0) {
-        fd = event_notifier_get_fd(&vector->kvm_interrupt);
+        fd = vfio_irq_signal_fd(&vector->kvm_interrupt);
     } else {
-        fd = event_notifier_get_fd(&vector->interrupt);
+        fd = vfio_irq_signal_fd(&vector->interrupt);
     }
 
     if (!vfio_device_irq_set_signaling(vbasedev, VFIO_PCI_MSIX_IRQ_INDEX, nr,
@@ -770,7 +783,7 @@ static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr)
      * be re-asserted on unmask.  Nothing to do if already using QEMU mode.
      */
     if (vector->virq >= 0) {
-        int32_t fd = event_notifier_get_fd(&vector->interrupt);
+        int32_t fd = vfio_irq_signal_fd(&vector->interrupt);
         Error *err = NULL;
 
         if (!vfio_device_irq_set_signaling(&vdev->vbasedev, VFIO_PCI_MSIX_IRQ_INDEX,
@@ -3181,7 +3194,9 @@ void vfio_pci_register_err_notifier(VFIOPCIDevice *vdev)
     }
 
     if (!vfio_device_irq_set_signaling(&vdev->vbasedev, VFIO_PCI_ERR_IRQ_INDEX, 0,
-                                       VFIO_IRQ_SET_ACTION_TRIGGER, fd, &err)) {
+                                       VFIO_IRQ_SET_ACTION_TRIGGER,
+                                       vfio_irq_signal_fd(&vdev->err_notifier),
+                                       &err)) {
         error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
         qemu_set_fd_handler(fd, NULL, NULL, vdev);
         vfio_notifier_cleanup(vdev, &vdev->err_notifier, "err_notifier", 0);
@@ -3254,7 +3269,9 @@ void vfio_pci_register_req_notifier(VFIOPCIDevice *vdev)
     }
 
     if (!vfio_device_irq_set_signaling(&vdev->vbasedev, VFIO_PCI_REQ_IRQ_INDEX, 0,
-                                       VFIO_IRQ_SET_ACTION_TRIGGER, fd, &err)) {
+                                       VFIO_IRQ_SET_ACTION_TRIGGER,
+                                       vfio_irq_signal_fd(&vdev->req_notifier),
+                                       &err)) {
         error_reportf_err(err, VFIO_MSG_PREFIX, vdev->vbasedev.name);
         qemu_set_fd_handler(fd, NULL, NULL, vdev);
         vfio_notifier_cleanup(vdev, &vdev->req_notifier, "req_notifier", 0);
-- 
2.50.1 (Apple Git-155)