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 4/9] fdt: Allow fdt_irq_fn to generate multiple interrupts
Date: Sat, 24 Oct 2026 16:18:57 +0000 [thread overview]
Message-ID: <20261024161902.2093581-5-smostafa@google.com> (raw)
In-Reply-To: <20261024161902.2093581-1-smostafa@google.com>
fdt_irq_fn currently accepts a single interrupt line and trigger type,
which is sufficient for emulated MMIO devices with one interrupt.
Assigned platform devices can expose multiple interrupts that must be
written into a single "interrupts" property.
Update fdt_irq_fn and its arm64 and riscv implementations to accept an
array of interrupt lines and trigger types, and convert existing callers
to use the fdt_irq_fn typedef.
Signed-off-by: Mostafa Saleh <smostafa@google.com>
---
arm64/fdt.c | 36 ++++++++++++++++++++++++++----------
hw/cfi_flash.c | 4 +---
hw/rtc.c | 4 +---
hw/serial.c | 3 ++-
include/kvm/fdt.h | 4 +++-
riscv/fdt.c | 2 +-
riscv/include/kvm/kvm-arch.h | 4 +++-
riscv/irq.c | 27 +++++++++++++++++++--------
virtio/mmio.c | 10 ++++------
9 files changed, 60 insertions(+), 34 deletions(-)
diff --git a/arm64/fdt.c b/arm64/fdt.c
index 3cbd36e..e2c37ad 100644
--- a/arm64/fdt.c
+++ b/arm64/fdt.c
@@ -60,15 +60,29 @@ static void generate_cpu_nodes(void *fdt, struct kvm *kvm)
_FDT(fdt_end_node(fdt));
}
-static void generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type)
+static void generate_irq_prop(void *fdt, const u8 *irqs,
+ const enum irq_type *irq_types,
+ unsigned int num_irqs)
{
- u32 irq_prop[] = {
- cpu_to_fdt32(GIC_FDT_IRQ_TYPE_SPI),
- cpu_to_fdt32(irq - GIC_SPI_IRQ_BASE),
- cpu_to_fdt32(irq_type)
- };
+ unsigned int i;
+ u32 *irq_prop;
- _FDT(fdt_property(fdt, "interrupts", irq_prop, sizeof(irq_prop)));
+ if (!num_irqs)
+ return;
+
+ irq_prop = calloc(num_irqs, 3 * sizeof(*irq_prop));
+ if (!irq_prop)
+ die("Failed to allocate the interrupts property");
+
+ for (i = 0; i < num_irqs; i++) {
+ irq_prop[3 * i] = cpu_to_fdt32(GIC_FDT_IRQ_TYPE_SPI);
+ irq_prop[3 * i + 1] = cpu_to_fdt32(irqs[i] - GIC_SPI_IRQ_BASE);
+ irq_prop[3 * i + 2] = cpu_to_fdt32(irq_types[i]);
+ }
+
+ _FDT(fdt_property(fdt, "interrupts", irq_prop,
+ 3 * sizeof(*irq_prop) * num_irqs));
+ free(irq_prop);
}
static bool emit_dma_regions;
@@ -78,9 +92,11 @@ void generate_dma_region_prop(void *fdt)
_FDT(fdt_property_cell(fdt, "memory-region", PHANDLE_DMA));
}
-static void generate_aux_props(void *fdt, u8 irq, enum irq_type irq_type)
+static void generate_aux_props(void *fdt, const u8 *irqs,
+ const enum irq_type *irq_types,
+ unsigned int num_irqs)
{
- generate_irq_prop(fdt, irq, irq_type);
+ generate_irq_prop(fdt, irqs, irq_types, num_irqs);
generate_dma_region_prop(fdt);
}
@@ -125,7 +141,7 @@ static int setup_fdt(struct kvm *kvm)
void *fdt_dest = guest_flat_to_host(kvm,
kvm->arch.dtb_guest_start);
void (*generate_mmio_fdt_nodes)(void *, struct device_header *,
- void (*)(void *, u8, enum irq_type));
+ fdt_irq_fn);
void (*generate_cpu_peripheral_fdt_nodes)(void *, struct kvm *)
= kvm->cpus[0]->generate_fdt_nodes;
diff --git a/hw/cfi_flash.c b/hw/cfi_flash.c
index 4413955..5641af6 100644
--- a/hw/cfi_flash.c
+++ b/hw/cfi_flash.c
@@ -518,9 +518,7 @@ static void cfi_flash_mmio(struct kvm_cpu *vcpu,
#ifdef CONFIG_HAS_LIBFDT
static void generate_cfi_flash_fdt_node(void *fdt,
struct device_header *dev_hdr,
- void (*generate_irq_prop)(void *fdt,
- u8 irq,
- enum irq_type))
+ fdt_irq_fn generate_irq_prop)
{
struct cfi_flash_device *sfdev;
u64 reg_prop[2];
diff --git a/hw/rtc.c b/hw/rtc.c
index e3523a1..fc6533a 100644
--- a/hw/rtc.c
+++ b/hw/rtc.c
@@ -136,9 +136,7 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
#ifdef CONFIG_HAS_LIBFDT
static void generate_rtc_fdt_node(void *fdt,
struct device_header *dev_hdr,
- void (*generate_irq_prop)(void *fdt,
- u8 irq,
- enum irq_type))
+ fdt_irq_fn generate_irq_prop)
{
u64 reg_prop[2] = { cpu_to_fdt64(RTC_BASE_ADDRESS), cpu_to_fdt64(2) };
diff --git a/hw/serial.c b/hw/serial.c
index 68e6186..8e26837 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -434,6 +434,7 @@ void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
cpu_to_fdt64(addr),
cpu_to_fdt64(8),
};
+ enum irq_type irq_type = IRQ_TYPE_LEVEL_HIGH;
snprintf(dev_name, DEVICE_NAME_MAX_LEN, "U6_16550A@%llx", addr);
@@ -446,7 +447,7 @@ void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
_FDT(fdt_begin_node(fdt, dev_name));
_FDT(fdt_property_string(fdt, "compatible", "ns16550a"));
_FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop)));
- irq_fn(fdt, dev->irq, IRQ_TYPE_LEVEL_HIGH);
+ irq_fn(fdt, &dev->irq, &irq_type, 1);
_FDT(fdt_property_cell(fdt, "clock-frequency", 1843200));
_FDT(fdt_end_node(fdt));
}
diff --git a/include/kvm/fdt.h b/include/kvm/fdt.h
index 060c37b..e84c5c1 100644
--- a/include/kvm/fdt.h
+++ b/include/kvm/fdt.h
@@ -25,7 +25,9 @@ enum irq_type {
IRQ_TYPE_LEVEL_MASK = (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH),
};
-typedef void (*fdt_irq_fn)(void *fdt, u8 irq, enum irq_type irq_type);
+typedef void (*fdt_irq_fn)(void *fdt, const u8 *irqs,
+ const enum irq_type *irq_types,
+ unsigned int num_irqs);
extern char *fdt_stdout_path;
diff --git a/riscv/fdt.c b/riscv/fdt.c
index 1eb45fc..b571724 100644
--- a/riscv/fdt.c
+++ b/riscv/fdt.c
@@ -351,7 +351,7 @@ static int setup_fdt(struct kvm *kvm)
void *fdt_dest = guest_flat_to_host(kvm,
kvm->arch.dtb_guest_start);
void (*generate_mmio_fdt_nodes)(void *, struct device_header *,
- void (*)(void *, u8, enum irq_type));
+ fdt_irq_fn);
/* Create new tree without a reserve map */
_FDT(fdt_create(fdt, FDT_MAX_SIZE));
diff --git a/riscv/include/kvm/kvm-arch.h b/riscv/include/kvm/kvm-arch.h
index 1bb2d32..460b90b 100644
--- a/riscv/include/kvm/kvm-arch.h
+++ b/riscv/include/kvm/kvm-arch.h
@@ -117,7 +117,9 @@ void riscv__del_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd);
int riscv__setup_irqfd_lines(struct kvm *kvm);
-void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type);
+void riscv__generate_irq_prop(void *fdt, const u8 *irqs,
+ const enum irq_type *irq_types,
+ unsigned int num_irqs);
void riscv__irqchip_create(struct kvm *kvm);
diff --git a/riscv/irq.c b/riscv/irq.c
index 62dbaa8..2c35f25 100644
--- a/riscv/irq.c
+++ b/riscv/irq.c
@@ -119,18 +119,29 @@ int riscv__setup_irqfd_lines(struct kvm *kvm)
return 0;
}
-void riscv__generate_irq_prop(void *fdt, u8 irq, enum irq_type irq_type)
+void riscv__generate_irq_prop(void *fdt, const u8 *irqs,
+ const enum irq_type *irq_types,
+ unsigned int num_irqs)
{
- u32 prop[2], size;
+ unsigned int i, cells = riscv_irqchip_line_sensing ? 2 : 1;
+ u32 *prop;
- prop[0] = cpu_to_fdt32(irq);
- size = sizeof(u32);
- if (riscv_irqchip_line_sensing) {
- prop[1] = cpu_to_fdt32(irq_type);
- size += sizeof(u32);
+ if (!num_irqs)
+ return;
+
+ prop = calloc(num_irqs, cells * sizeof(*prop));
+ if (!prop)
+ die("Failed to allocate the interrupts property");
+
+ for (i = 0; i < num_irqs; i++) {
+ prop[cells * i] = cpu_to_fdt32(irqs[i]);
+ if (riscv_irqchip_line_sensing)
+ prop[cells * i + 1] = cpu_to_fdt32(irq_types[i]);
}
- _FDT(fdt_property(fdt, "interrupts", prop, size));
+ _FDT(fdt_property(fdt, "interrupts", prop,
+ cells * sizeof(*prop) * num_irqs));
+ free(prop);
}
static void (*riscv__irqchip_create_funcs[])(struct kvm *kvm) = {
diff --git a/virtio/mmio.c b/virtio/mmio.c
index fae73b5..0c66724 100644
--- a/virtio/mmio.c
+++ b/virtio/mmio.c
@@ -113,9 +113,7 @@ int virtio_mmio_signal_config(struct kvm *kvm, struct virtio_device *vdev)
static
void generate_virtio_mmio_fdt_node(void *fdt,
struct device_header *dev_hdr,
- void (*generate_irq_prop)(void *fdt,
- u8 irq,
- enum irq_type))
+ fdt_irq_fn generate_irq_prop)
{
char dev_name[DEVICE_NAME_MAX_LEN];
struct virtio_mmio *vmmio = container_of(dev_hdr,
@@ -126,6 +124,7 @@ void generate_virtio_mmio_fdt_node(void *fdt,
cpu_to_fdt64(addr),
cpu_to_fdt64(VIRTIO_MMIO_IO_SIZE),
};
+ enum irq_type irq_type = IRQ_TYPE_EDGE_RISING;
snprintf(dev_name, DEVICE_NAME_MAX_LEN, "virtio@%llx", addr);
@@ -133,14 +132,13 @@ void generate_virtio_mmio_fdt_node(void *fdt,
_FDT(fdt_property_string(fdt, "compatible", "virtio,mmio"));
_FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop)));
_FDT(fdt_property(fdt, "dma-coherent", NULL, 0));
- generate_irq_prop(fdt, vmmio->irq, IRQ_TYPE_EDGE_RISING);
+ generate_irq_prop(fdt, &vmmio->irq, &irq_type, 1);
_FDT(fdt_end_node(fdt));
}
#else
static void generate_virtio_mmio_fdt_node(void *fdt,
struct device_header *dev_hdr,
- void (*generate_irq_prop)(void *fdt,
- u8 irq))
+ fdt_irq_fn generate_irq_prop)
{
die("Unable to generate device tree nodes without libfdt\n");
}
--
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 ` [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 ` Mostafa Saleh [this message]
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-5-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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.