Kernel KVM virtualization development
 help / color / mirror / Atom feed
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 8/9] vfio: platform: Add interrupts support
Date: Sat, 24 Oct 2026 16:19:01 +0000	[thread overview]
Message-ID: <20261024161902.2093581-9-smostafa@google.com> (raw)
In-Reply-To: <20261024161902.2093581-1-smostafa@google.com>

Configures interrupts of the device, relying on the new common
VFIO interrupt code.

And generated the dt node for interrupts.

Signed-off-by: Mostafa Saleh <smostafa@google.com>
---
 include/kvm/vfio.h |   9 +++-
 vfio/platform.c    | 113 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 119 insertions(+), 3 deletions(-)

diff --git a/include/kvm/vfio.h b/include/kvm/vfio.h
index f641292..b3034a0 100644
--- a/include/kvm/vfio.h
+++ b/include/kvm/vfio.h
@@ -89,6 +89,10 @@ struct vfio_pci_device {
 	struct vfio_pci_msix_pba	msix_pba;
 };
 
+struct vfio_platform_device {
+	struct vfio_irq			*irqs;
+};
+
 struct vfio_region {
 	struct vfio_region_info		info;
 	struct vfio_device		*vdev;
@@ -109,7 +113,10 @@ struct vfio_device {
 
 	char				*sysfs_path;
 
-	struct vfio_pci_device		pci;
+	union {
+		struct vfio_pci_device		pci;
+		struct vfio_platform_device	platform;
+	};
 };
 
 struct vfio_device_params {
diff --git a/vfio/platform.c b/vfio/platform.c
index c5b447f..22052a6 100644
--- a/vfio/platform.c
+++ b/vfio/platform.c
@@ -1,5 +1,6 @@
 #include "linux/sizes.h"
 
+#include "kvm/irq.h"
 #include "kvm/kvm.h"
 #include "kvm/vfio.h"
 
@@ -28,6 +29,36 @@ static int vfio_mmio_alloc_io_space(u64 size, u64 *addr)
 }
 
 #ifdef CONFIG_HAS_LIBFDT
+static void generate_interrupts_prop(void *fdt, struct vfio_device *vdev,
+				     fdt_irq_fn generate_irq_prop)
+{
+	struct vfio_platform_device *pdev = &vdev->platform;
+	unsigned int i, num_irqs = vdev->info.num_irqs;
+	enum irq_type *irq_types = NULL;
+	u8 *irqs = NULL;
+
+	if (num_irqs) {
+		irqs = calloc(num_irqs, sizeof(*irqs));
+		irq_types = calloc(num_irqs, sizeof(*irq_types));
+		if (!irqs || !irq_types)
+			die("Failed to allocate the interrupts property");
+
+		for (i = 0; i < num_irqs; i++) {
+			struct vfio_irq *irq = &pdev->irqs[i];
+
+			irqs[i] = irq->gsi + KVM_IRQ_OFFSET;
+			irq_types[i] = irq->unmask_fd >= 0 ?
+				       IRQ_TYPE_LEVEL_HIGH :
+				       IRQ_TYPE_EDGE_RISING;
+		}
+	}
+
+	generate_irq_prop(fdt, irqs, irq_types, num_irqs);
+
+	free(irqs);
+	free(irq_types);
+}
+
 static void generate_mmio_fdt_node(void *fdt,
 				   struct device_header *dev_hdr,
 				   fdt_irq_fn generate_irq_prop)
@@ -53,6 +84,7 @@ static void generate_mmio_fdt_node(void *fdt,
 	_FDT(fdt_begin_node(fdt, node_name));
 	_FDT(fdt_property(fdt, "reg", reg_prop,
 			  2 * sizeof(*reg_prop) * num_regions));
+	generate_interrupts_prop(fdt, vdev, generate_irq_prop);
 	_FDT(fdt_end_node(fdt));
 
 	free(reg_prop);
@@ -123,8 +155,65 @@ err_unmap:
 	return ret;
 }
 
+static int vfio_platform_setup_irq(struct kvm *kvm, struct vfio_device *vdev,
+				   unsigned int index)
+{
+	struct vfio_irq *irq = &vdev->platform.irqs[index];
+	struct vfio_irq_info irq_info = {
+		.argsz	= sizeof(irq_info),
+		.index	= index,
+	};
+	int ret;
+
+	if (ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info)) {
+		ret = -errno;
+		vfio_dev_err(vdev, "failed to get irq[%u] info", index);
+		return ret;
+	}
+
+	if (!(irq_info.flags & VFIO_IRQ_INFO_EVENTFD)) {
+		vfio_dev_err(vdev, "irq[%u] is not eventfd capable", index);
+		return -EINVAL;
+	}
+
+	irq->gsi = irq__alloc_line() - KVM_IRQ_OFFSET;
+	irq->trigger_fd = -1;
+
+	return vfio_irq_enable(kvm, vdev, index,
+			       irq_info.flags & VFIO_IRQ_INFO_AUTOMASKED, irq);
+}
+
+static int vfio_platform_configure_dev_irqs(struct kvm *kvm, struct vfio_device *vdev)
+{
+	struct vfio_platform_device *pdev = &vdev->platform;
+	unsigned int i, num_irqs = vdev->info.num_irqs;
+	int ret;
+
+	if (!num_irqs)
+		return 0;
+
+	pdev->irqs = calloc(num_irqs, sizeof(*pdev->irqs));
+	if (!pdev->irqs)
+		return -ENOMEM;
+
+	for (i = 0; i < num_irqs; i++) {
+		ret = vfio_platform_setup_irq(kvm, vdev, i);
+		if (ret)
+			goto err_teardown;
+	}
+
+	return 0;
+
+err_teardown:
+	while (i--)
+		vfio_irq_disable(kvm, vdev, i, &pdev->irqs[i]);
+	free(pdev->irqs);
+	return ret;
+}
+
 int vfio_platform_setup_device(struct kvm *kvm, struct vfio_device *vdev)
 {
+	unsigned int i;
 	int ret;
 
 	ret = vfio_platform_configure_regs(kvm, vdev);
@@ -133,6 +222,12 @@ int vfio_platform_setup_device(struct kvm *kvm, struct vfio_device *vdev)
 		return ret;
 	}
 
+	ret = vfio_platform_configure_dev_irqs(kvm, vdev);
+	if (ret) {
+		vfio_dev_err(vdev, "failed to configure IRQs");
+		goto err_unmap;
+	}
+
 	vdev->dev_hdr = (struct device_header) {
 		.bus_type	= DEVICE_BUS_MMIO,
 #ifdef CONFIG_HAS_LIBFDT
@@ -143,16 +238,30 @@ int vfio_platform_setup_device(struct kvm *kvm, struct vfio_device *vdev)
 	ret = device__register(&vdev->dev_hdr);
 	if (ret) {
 		vfio_dev_err(vdev, "failed to register VFIO device");
-		vfio_platform_unmap_regions(kvm, vdev, vdev->info.num_regions);
-		return ret;
+		goto err_teardown_irqs;
 	}
 
 	return 0;
+
+err_teardown_irqs:
+	for (i = 0; i < vdev->info.num_irqs; i++)
+		vfio_irq_disable(kvm, vdev, i, &vdev->platform.irqs[i]);
+	free(vdev->platform.irqs);
+err_unmap:
+	vfio_platform_unmap_regions(kvm, vdev, vdev->info.num_regions);
+	return ret;
 }
 
 void vfio_platform_teardown_device(struct kvm *kvm, struct vfio_device *vdev)
 {
+	size_t i;
+	struct vfio_platform_device *pdev = &vdev->platform;
+
 	vfio_platform_unmap_regions(kvm, vdev, vdev->info.num_regions);
 
+	for (i = 0; i < vdev->info.num_irqs; ++i)
+		vfio_irq_disable(kvm, vdev, i, &pdev->irqs[i]);
+
 	device__unregister(&vdev->dev_hdr);
+	free(pdev->irqs);
 }
-- 
2.56.0.307.g5fe7bd680c-goog


  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 ` [PATCH kvmtool 2/9] vfio: Factor out wired IRQ setup and teardown Mostafa Saleh
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 ` Mostafa Saleh [this message]
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-9-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