PCI INTx is are level-triggered and automasked, but platform device interrupts can also be edge-triggered. Pass an automasked boolean to vfio_irq_enable() and only create and register unmask_fd when the interrupt is automasked. Signed-off-by: Mostafa Saleh --- include/kvm/vfio.h | 2 +- vfio/core.c | 51 ++++++++++++++++++++++++++-------------------- vfio/pci.c | 3 ++- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/include/kvm/vfio.h b/include/kvm/vfio.h index 9a5783e..0b2b105 100644 --- a/include/kvm/vfio.h +++ b/include/kvm/vfio.h @@ -141,7 +141,7 @@ int vfio_map_region(struct kvm *kvm, struct vfio_device *vdev, struct vfio_region *region); void vfio_unmap_region(struct kvm *kvm, struct vfio_region *region); int vfio_irq_enable(struct kvm *kvm, struct vfio_device *vdev, - unsigned int index, struct vfio_irq *irq); + unsigned int index, bool automasked, struct vfio_irq *irq); void vfio_irq_disable(struct kvm *kvm, struct vfio_device *vdev, unsigned int index, struct vfio_irq *irq); int vfio_pci_setup_device(struct kvm *kvm, struct vfio_device *device); diff --git a/vfio/core.c b/vfio/core.c index 24d3f2d..aa124d2 100644 --- a/vfio/core.c +++ b/vfio/core.c @@ -301,15 +301,16 @@ void vfio_irq_disable(struct kvm *kvm, struct vfio_device *vdev, irq__del_irqfd(kvm, gsi, irq->trigger_fd); close(irq->trigger_fd); - close(irq->unmask_fd); + if (irq->unmask_fd >= 0) + close(irq->unmask_fd); irq->trigger_fd = -1; } int vfio_irq_enable(struct kvm *kvm, struct vfio_device *vdev, - unsigned int index, struct vfio_irq *irq) + unsigned int index, bool automasked, struct vfio_irq *irq) { int ret; - int trigger_fd, unmask_fd; + int trigger_fd, unmask_fd = -1; union vfio_irq_eventfd trigger; union vfio_irq_eventfd unmask; int gsi = irq->gsi; @@ -318,7 +319,7 @@ int vfio_irq_enable(struct kvm *kvm, struct vfio_device *vdev, return 0; /* - * PCI IRQ is level-triggered, so we use two eventfds. trigger_fd + * Level-triggered IRQ is automasked, so we use two eventfds. trigger_fd * signals an interrupt from host to guest, and unmask_fd signals the * deassertion of the line from guest to host. */ @@ -328,11 +329,13 @@ int vfio_irq_enable(struct kvm *kvm, struct vfio_device *vdev, return trigger_fd; } - unmask_fd = eventfd(0, 0); - if (unmask_fd < 0) { - vfio_dev_err(vdev, "failed to create unmask eventfd"); - close(trigger_fd); - return unmask_fd; + if (automasked) { + unmask_fd = eventfd(0, 0); + if (unmask_fd < 0) { + vfio_dev_err(vdev, "failed to create unmask eventfd"); + close(trigger_fd); + return unmask_fd; + } } ret = irq__add_irqfd(kvm, gsi, trigger_fd, unmask_fd); @@ -354,19 +357,22 @@ int vfio_irq_enable(struct kvm *kvm, struct vfio_device *vdev, goto err_delete_line; } - unmask.irq = (struct vfio_irq_set) { - .argsz = sizeof(unmask), - .flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_UNMASK, - .index = index, - .start = 0, - .count = 1, - }; - set_vfio_irq_eventd_payload(&unmask, unmask_fd); + if (unmask_fd >= 0) { + unmask.irq = (struct vfio_irq_set) { + .argsz = sizeof(unmask), + .flags = VFIO_IRQ_SET_DATA_EVENTFD | + VFIO_IRQ_SET_ACTION_UNMASK, + .index = index, + .start = 0, + .count = 1, + }; + set_vfio_irq_eventd_payload(&unmask, unmask_fd); - ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &unmask); - if (ret < 0) { - vfio_dev_err(vdev, "failed to setup unmask IRQ"); - goto err_remove_event; + ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &unmask); + if (ret < 0) { + vfio_dev_err(vdev, "failed to setup unmask IRQ"); + goto err_remove_event; + } } irq->trigger_fd = trigger_fd; @@ -385,7 +391,8 @@ err_delete_line: err_close: close(trigger_fd); - close(unmask_fd); + if (unmask_fd >= 0) + close(unmask_fd); return ret; } diff --git a/vfio/pci.c b/vfio/pci.c index fb98435..9bf2f9e 100644 --- a/vfio/pci.c +++ b/vfio/pci.c @@ -1216,7 +1216,8 @@ static int vfio_pci_enable_intx(struct kvm *kvm, struct vfio_device *vdev) { struct vfio_pci_device *pdev = &vdev->pci; - return vfio_irq_enable(kvm, vdev, VFIO_PCI_INTX_IRQ_INDEX, &pdev->intx); + return vfio_irq_enable(kvm, vdev, VFIO_PCI_INTX_IRQ_INDEX, true, + &pdev->intx); } static int vfio_pci_init_intx(struct kvm *kvm, struct vfio_device *vdev) -- 2.56.0.307.g5fe7bd680c-goog