From: Mostafa Saleh <smostafa@google.com>
To: kvm@vger.kernel.org
Cc: will@kernel.org, julien.thierry.kdev@gmail.com, praan@google.com,
eric.auger@redhat.com, alex@shazbot.org,
Mostafa Saleh <smostafa@google.com>
Subject: [PATCH kvmtool 2/9] vfio: Factor out wired IRQ setup and teardown
Date: Sat, 24 Oct 2026 16:18:55 +0000 [thread overview]
Message-ID: <20261024161902.2093581-3-smostafa@google.com> (raw)
In-Reply-To: <20261024161902.2093581-1-smostafa@google.com>
Factor the wired IRQ eventfd and KVM irqfd setup and teardown out of
vfio_pci_enable_intx() and vfio_pci_disable_intx() into
vfio_irq_enable() and vfio_irq_disable() in vfio/core.c, and move
union vfio_irq_eventfd to vfio.h so both PCI INTx and VFIO platform
devices can share them.
The is a mechanical code move, no functional change.
Signed-off-by: Mostafa Saleh <smostafa@google.com>
---
include/kvm/vfio.h | 27 +++++++++--
vfio/core.c | 107 +++++++++++++++++++++++++++++++++++++++++++
vfio/pci.c | 110 +++------------------------------------------
3 files changed, 137 insertions(+), 107 deletions(-)
diff --git a/include/kvm/vfio.h b/include/kvm/vfio.h
index ac7b622..9a5783e 100644
--- a/include/kvm/vfio.h
+++ b/include/kvm/vfio.h
@@ -6,6 +6,7 @@
#include "kvm/pci.h"
#include <linux/vfio.h>
+#include <string.h>
#define vfio_dev_err(vdev, fmt, ...) \
pr_err("%s: " fmt, (vdev)->params->name, ##__VA_ARGS__)
@@ -70,13 +71,17 @@ struct vfio_pci_msi_common {
#define VFIO_PCI_IRQ_MODE_MSI (1 << 1)
#define VFIO_PCI_IRQ_MODE_MSIX (1 << 2)
+struct vfio_irq {
+ int gsi;
+ int trigger_fd;
+ int unmask_fd;
+};
+
struct vfio_pci_device {
struct pci_device_header hdr;
unsigned long irq_modes;
- int intx_fd;
- int unmask_fd;
- unsigned int intx_gsi;
+ struct vfio_irq intx;
struct vfio_pci_msi_common msi;
struct vfio_pci_msi_common msix;
struct vfio_pci_msix_table msix_table;
@@ -119,10 +124,26 @@ struct vfio_group {
struct list_head list;
};
+/* Wrapper around UAPI vfio_irq_set */
+union vfio_irq_eventfd {
+ struct vfio_irq_set irq;
+ u8 buffer[sizeof(struct vfio_irq_set) + sizeof(int)];
+};
+
+static inline void set_vfio_irq_eventd_payload(union vfio_irq_eventfd *evfd,
+ int fd)
+{
+ memcpy(&evfd->irq.data, &fd, sizeof(fd));
+}
+
int vfio_device_parser(const struct option *opt, const char *arg, int unset);
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);
+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);
void vfio_pci_teardown_device(struct kvm *kvm, struct vfio_device *vdev);
diff --git a/vfio/core.c b/vfio/core.c
index e0c56ab..24d3f2d 100644
--- a/vfio/core.c
+++ b/vfio/core.c
@@ -1,8 +1,10 @@
+#include "kvm/irq.h"
#include "kvm/kvm.h"
#include "kvm/vfio.h"
#include "kvm/ioport.h"
#include <linux/list.h>
+#include <sys/eventfd.h>
#include <libgen.h>
#define VFIO_DEV_DIR "/dev/vfio"
@@ -282,6 +284,111 @@ void vfio_unmap_region(struct kvm *kvm, struct vfio_region *region)
}
}
+void vfio_irq_disable(struct kvm *kvm, struct vfio_device *vdev,
+ unsigned int index, struct vfio_irq *irq)
+{
+ int gsi = irq->gsi;
+ struct vfio_irq_set irq_set = {
+ .argsz = sizeof(irq_set),
+ .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER,
+ .index = index,
+ };
+
+ if (irq->trigger_fd == -1)
+ return;
+
+ ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
+ irq__del_irqfd(kvm, gsi, irq->trigger_fd);
+
+ close(irq->trigger_fd);
+ 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)
+{
+ int ret;
+ int trigger_fd, unmask_fd;
+ union vfio_irq_eventfd trigger;
+ union vfio_irq_eventfd unmask;
+ int gsi = irq->gsi;
+
+ if (irq->trigger_fd != -1)
+ return 0;
+
+ /*
+ * PCI IRQ is level-triggered, 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.
+ */
+ trigger_fd = eventfd(0, 0);
+ if (trigger_fd < 0) {
+ vfio_dev_err(vdev, "failed to create trigger eventfd");
+ 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;
+ }
+
+ ret = irq__add_irqfd(kvm, gsi, trigger_fd, unmask_fd);
+ if (ret)
+ goto err_close;
+
+ trigger.irq = (struct vfio_irq_set) {
+ .argsz = sizeof(trigger),
+ .flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER,
+ .index = index,
+ .start = 0,
+ .count = 1,
+ };
+ set_vfio_irq_eventd_payload(&trigger, trigger_fd);
+
+ ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &trigger);
+ if (ret < 0) {
+ vfio_dev_err(vdev, "failed to setup VFIO IRQ");
+ 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);
+
+ 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;
+ irq->unmask_fd = unmask_fd;
+
+ return 0;
+
+err_remove_event:
+ /* Remove trigger event */
+ trigger.irq.flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER;
+ trigger.irq.count = 0;
+ ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &trigger);
+
+err_delete_line:
+ irq__del_irqfd(kvm, gsi, trigger_fd);
+
+err_close:
+ close(trigger_fd);
+ close(unmask_fd);
+ return ret;
+}
+
static int vfio_configure_device(struct kvm *kvm, struct vfio_device *vdev)
{
int ret;
diff --git a/vfio/pci.c b/vfio/pci.c
index 0bcd60e..fb98435 100644
--- a/vfio/pci.c
+++ b/vfio/pci.c
@@ -17,17 +17,6 @@
#define PCI_CAP_EXP_RC_ENDPOINT_SIZEOF_V1 12
#endif
-/* Wrapper around UAPI vfio_irq_set */
-union vfio_irq_eventfd {
- struct vfio_irq_set irq;
- u8 buffer[sizeof(struct vfio_irq_set) + sizeof(int)];
-};
-
-static void set_vfio_irq_eventd_payload(union vfio_irq_eventfd *evfd, int fd)
-{
- memcpy(&evfd->irq.data, &fd, sizeof(fd));
-}
-
/*
* To support MSI and MSI-X with common code, track the host and guest states of
* the MSI/MSI-X capability, and of individual vectors.
@@ -1213,108 +1202,21 @@ static int vfio_pci_init_msis(struct kvm *kvm, struct vfio_device *vdev,
static void vfio_pci_disable_intx(struct kvm *kvm, struct vfio_device *vdev)
{
struct vfio_pci_device *pdev = &vdev->pci;
- int gsi = pdev->intx_gsi;
- struct vfio_irq_set irq_set = {
- .argsz = sizeof(irq_set),
- .flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER,
- .index = VFIO_PCI_INTX_IRQ_INDEX,
- };
+ int gsi = pdev->intx.gsi;
- if (pdev->intx_fd == -1)
+ if (pdev->intx.trigger_fd == -1)
return;
pr_debug("user requested MSI, disabling INTx %d", gsi);
- ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
- irq__del_irqfd(kvm, gsi, pdev->intx_fd);
-
- close(pdev->intx_fd);
- close(pdev->unmask_fd);
- pdev->intx_fd = -1;
+ vfio_irq_disable(kvm, vdev, VFIO_PCI_INTX_IRQ_INDEX, &pdev->intx);
}
static int vfio_pci_enable_intx(struct kvm *kvm, struct vfio_device *vdev)
{
- int ret;
- int trigger_fd, unmask_fd;
- union vfio_irq_eventfd trigger;
- union vfio_irq_eventfd unmask;
struct vfio_pci_device *pdev = &vdev->pci;
- int gsi = pdev->intx_gsi;
- if (pdev->intx_fd != -1)
- return 0;
-
- /*
- * PCI IRQ is level-triggered, 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.
- */
- trigger_fd = eventfd(0, 0);
- if (trigger_fd < 0) {
- vfio_dev_err(vdev, "failed to create trigger eventfd");
- 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;
- }
-
- ret = irq__add_irqfd(kvm, gsi, trigger_fd, unmask_fd);
- if (ret)
- goto err_close;
-
- trigger.irq = (struct vfio_irq_set) {
- .argsz = sizeof(trigger),
- .flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER,
- .index = VFIO_PCI_INTX_IRQ_INDEX,
- .start = 0,
- .count = 1,
- };
- set_vfio_irq_eventd_payload(&trigger, trigger_fd);
-
- ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &trigger);
- if (ret < 0) {
- vfio_dev_err(vdev, "failed to setup VFIO IRQ");
- 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 = VFIO_PCI_INTX_IRQ_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;
- }
-
- pdev->intx_fd = trigger_fd;
- pdev->unmask_fd = unmask_fd;
-
- return 0;
-
-err_remove_event:
- /* Remove trigger event */
- trigger.irq.flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_TRIGGER;
- trigger.irq.count = 0;
- ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &trigger);
-
-err_delete_line:
- irq__del_irqfd(kvm, gsi, trigger_fd);
-
-err_close:
- close(trigger_fd);
- close(unmask_fd);
- return ret;
+ return vfio_irq_enable(kvm, vdev, VFIO_PCI_INTX_IRQ_INDEX, &pdev->intx);
}
static int vfio_pci_init_intx(struct kvm *kvm, struct vfio_device *vdev)
@@ -1345,9 +1247,9 @@ static int vfio_pci_init_intx(struct kvm *kvm, struct vfio_device *vdev)
}
/* Guest is going to ovewrite our irq_line... */
- pdev->intx_gsi = pdev->hdr.irq_line - KVM_IRQ_OFFSET;
+ pdev->intx.gsi = pdev->hdr.irq_line - KVM_IRQ_OFFSET;
- pdev->intx_fd = -1;
+ pdev->intx.trigger_fd = -1;
return 0;
}
--
2.56.0.307.g5fe7bd680c-goog
next prev parent reply other threads:[~2026-10-24 16:20 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-24 16:18 [PATCH kvmtool 0/9] vfio: Add support for platform devices Mostafa Saleh
2026-10-24 16:18 ` [PATCH kvmtool 1/9] vfio: Fix fd leak in vfio_group_get_for_dev() Mostafa Saleh
2026-10-24 16:18 ` Mostafa Saleh [this message]
2026-10-24 16:18 ` [PATCH kvmtool 3/9] vfio: Support edge-triggered wired IRQs Mostafa Saleh
2026-10-24 16:18 ` [PATCH kvmtool 4/9] fdt: Allow fdt_irq_fn to generate multiple interrupts Mostafa Saleh
2026-10-24 16:18 ` [PATCH kvmtool 5/9] fdt: Add helper to copy an FDT node Mostafa Saleh
2026-10-24 16:18 ` [PATCH kvmtool 6/9] vfio: Reserve guest address space for VFIO platform Mostafa Saleh
2026-10-24 16:19 ` [PATCH kvmtool 7/9] vfio: Add basic support for vfio-platform Mostafa Saleh
2026-10-24 16:19 ` [PATCH kvmtool 8/9] vfio: platform: Add interrupts support Mostafa Saleh
2026-10-24 16:19 ` [PATCH kvmtool 9/9] vfio: platform: Take the guest node from a device tree template Mostafa Saleh
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261024161902.2093581-3-smostafa@google.com \
--to=smostafa@google.com \
--cc=alex@shazbot.org \
--cc=eric.auger@redhat.com \
--cc=julien.thierry.kdev@gmail.com \
--cc=kvm@vger.kernel.org \
--cc=praan@google.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox