vfio/pci: Use kvm_irqchip_add_irqfd_notifier_gsi() for irqfds

VFIO is currently the only one left that is not using the generic
function (kvm_irqchip_add_irqfd_notifier_gsi()) to register irqfds.
Let VFIO use the common framework too.

Follow up patches will introduce extra features for kvm irqfd, so that
VFIO can easily leverage that after the switch.

Reviewed-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Alex Williamson <alex.williamson@redhat.com>
Acked-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
Message-Id: <20200318145204.74483-3-peterx@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Peter Xu 2020-03-18 10:52:01 -04:00 committed by Paolo Bonzini
parent 353f98c9ad
commit 97a3757616

View file

@ -115,11 +115,7 @@ static void vfio_intx_eoi(VFIODevice *vbasedev)
static void vfio_intx_enable_kvm(VFIOPCIDevice *vdev, Error **errp) static void vfio_intx_enable_kvm(VFIOPCIDevice *vdev, Error **errp)
{ {
#ifdef CONFIG_KVM #ifdef CONFIG_KVM
struct kvm_irqfd irqfd = { int irq_fd = event_notifier_get_fd(&vdev->intx.interrupt);
.fd = event_notifier_get_fd(&vdev->intx.interrupt),
.gsi = vdev->intx.route.irq,
.flags = KVM_IRQFD_FLAG_RESAMPLE,
};
Error *err = NULL; Error *err = NULL;
if (vdev->no_kvm_intx || !kvm_irqfds_enabled() || if (vdev->no_kvm_intx || !kvm_irqfds_enabled() ||
@ -129,7 +125,7 @@ static void vfio_intx_enable_kvm(VFIOPCIDevice *vdev, Error **errp)
} }
/* Get to a known interrupt state */ /* Get to a known interrupt state */
qemu_set_fd_handler(irqfd.fd, NULL, NULL, vdev); qemu_set_fd_handler(irq_fd, NULL, NULL, vdev);
vfio_mask_single_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX); vfio_mask_single_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
vdev->intx.pending = false; vdev->intx.pending = false;
pci_irq_deassert(&vdev->pdev); pci_irq_deassert(&vdev->pdev);
@ -140,17 +136,18 @@ static void vfio_intx_enable_kvm(VFIOPCIDevice *vdev, Error **errp)
goto fail; goto fail;
} }
/* KVM triggers it, VFIO listens for it */ if (kvm_irqchip_add_irqfd_notifier_gsi(kvm_state,
irqfd.resamplefd = event_notifier_get_fd(&vdev->intx.unmask); &vdev->intx.interrupt,
&vdev->intx.unmask,
if (kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd)) { vdev->intx.route.irq)) {
error_setg_errno(errp, errno, "failed to setup resample irqfd"); error_setg_errno(errp, errno, "failed to setup resample irqfd");
goto fail_irqfd; goto fail_irqfd;
} }
if (vfio_set_irq_signaling(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX, 0, if (vfio_set_irq_signaling(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX, 0,
VFIO_IRQ_SET_ACTION_UNMASK, VFIO_IRQ_SET_ACTION_UNMASK,
irqfd.resamplefd, &err)) { event_notifier_get_fd(&vdev->intx.unmask),
&err)) {
error_propagate(errp, err); error_propagate(errp, err);
goto fail_vfio; goto fail_vfio;
} }
@ -165,12 +162,12 @@ static void vfio_intx_enable_kvm(VFIOPCIDevice *vdev, Error **errp)
return; return;
fail_vfio: fail_vfio:
irqfd.flags = KVM_IRQFD_FLAG_DEASSIGN; kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, &vdev->intx.interrupt,
kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd); vdev->intx.route.irq);
fail_irqfd: fail_irqfd:
event_notifier_cleanup(&vdev->intx.unmask); event_notifier_cleanup(&vdev->intx.unmask);
fail: fail:
qemu_set_fd_handler(irqfd.fd, vfio_intx_interrupt, NULL, vdev); qemu_set_fd_handler(irq_fd, vfio_intx_interrupt, NULL, vdev);
vfio_unmask_single_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX); vfio_unmask_single_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
#endif #endif
} }
@ -178,12 +175,6 @@ fail:
static void vfio_intx_disable_kvm(VFIOPCIDevice *vdev) static void vfio_intx_disable_kvm(VFIOPCIDevice *vdev)
{ {
#ifdef CONFIG_KVM #ifdef CONFIG_KVM
struct kvm_irqfd irqfd = {
.fd = event_notifier_get_fd(&vdev->intx.interrupt),
.gsi = vdev->intx.route.irq,
.flags = KVM_IRQFD_FLAG_DEASSIGN,
};
if (!vdev->intx.kvm_accel) { if (!vdev->intx.kvm_accel) {
return; return;
} }
@ -197,7 +188,8 @@ static void vfio_intx_disable_kvm(VFIOPCIDevice *vdev)
pci_irq_deassert(&vdev->pdev); pci_irq_deassert(&vdev->pdev);
/* Tell KVM to stop listening for an INTx irqfd */ /* Tell KVM to stop listening for an INTx irqfd */
if (kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd)) { if (kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, &vdev->intx.interrupt,
vdev->intx.route.irq)) {
error_report("vfio: Error: Failed to disable INTx irqfd: %m"); error_report("vfio: Error: Failed to disable INTx irqfd: %m");
} }
@ -205,7 +197,8 @@ static void vfio_intx_disable_kvm(VFIOPCIDevice *vdev)
event_notifier_cleanup(&vdev->intx.unmask); event_notifier_cleanup(&vdev->intx.unmask);
/* QEMU starts listening for interrupt events. */ /* QEMU starts listening for interrupt events. */
qemu_set_fd_handler(irqfd.fd, vfio_intx_interrupt, NULL, vdev); qemu_set_fd_handler(event_notifier_get_fd(&vdev->intx.interrupt),
vfio_intx_interrupt, NULL, vdev);
vdev->intx.kvm_accel = false; vdev->intx.kvm_accel = false;