@samitouri / QOSamiQemu / commits / b23a9cad31

hw/arm/virt: Use correct interrupt type for GICv5 SPIs in the DTB

The GICv5 devicetree binding specifies that the "interrupts" property for devices connected to it should use the architectural INTID.TYPE values to specify whether the interrupt is an SPI, LPI or PPI. This is different to the GICv2 and GICv3, so instead of hardcoding the GIC_FDT_IRQ_TYPE_SPI constant when we create "interrupts" bindings, create a new function gic_fdt_irq_type_spi() that returns the right value for the interrupt controller in use. For SPIs, the INTID.ID and the trigger-mode fields of the "interrupts" property remain the same for GICv5 and the older GIC versions. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Message-id: 20260327111700.795099-64-peter.maydell@linaro.org

Peter Maydell committed Mar 27, 2026 at 11:16 UTC b23a9cad3124d1da511116117a327f11311982e5
1 file changed +20 -9
hw/arm/virt.c
+20 -9
@@ -375,6 +375,16 @@ unsigned int virt_get_caches(const VirtMachineState *vms, CPUCoreCaches *caches)
375 return num_cache;
376 }
377
378 +/*
379 + * The correct value to use in a DTB "interrupts" property for an SPI
380 + * depends on the GIC version.
381 + */
382 +static int gic_fdt_irq_type_spi(const VirtMachineState *vms)
383 +{
384 + return vms->gic_version == VIRT_GIC_VERSION_5 ?
385 + GICV5_SPI : GIC_FDT_IRQ_TYPE_SPI;
386 +}
387 +
388 static void create_fdt(VirtMachineState *vms)
389 {
390 MachineState *ms = MACHINE(vms);
@@ -1510,7 +1520,7 @@ static void create_uart(const VirtMachineState *vms, int uart,
1520 qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
1521 2, base, 2, size);
1522 qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
1513 - GIC_FDT_IRQ_TYPE_SPI, irq,
1523 + gic_fdt_irq_type_spi(vms), irq,
1524 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
1525 qemu_fdt_setprop_cells(ms->fdt, nodename, "clocks",
1526 vms->clock_phandle, vms->clock_phandle);
@@ -1552,7 +1562,7 @@ static void create_rtc(const VirtMachineState *vms)
1562 qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
1563 2, base, 2, size);
1564 qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
1555 - GIC_FDT_IRQ_TYPE_SPI, irq,
1565 + gic_fdt_irq_type_spi(vms), irq,
1566 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
1567 qemu_fdt_setprop_cell(ms->fdt, nodename, "clocks", vms->clock_phandle);
1568 qemu_fdt_setprop_string(ms->fdt, nodename, "clock-names", "apb_pclk");
@@ -1671,7 +1681,7 @@ static void create_gpio_devices(const VirtMachineState *vms, int gpio,
1681 qemu_fdt_setprop_cell(ms->fdt, nodename, "#gpio-cells", 2);
1682 qemu_fdt_setprop(ms->fdt, nodename, "gpio-controller", NULL, 0);
1683 qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
1674 - GIC_FDT_IRQ_TYPE_SPI, irq,
1684 + gic_fdt_irq_type_spi(vms), irq,
1685 GIC_FDT_IRQ_FLAGS_LEVEL_HI);
1686 qemu_fdt_setprop_cell(ms->fdt, nodename, "clocks", vms->clock_phandle);
1687 qemu_fdt_setprop_string(ms->fdt, nodename, "clock-names", "apb_pclk");
@@ -1752,7 +1762,7 @@ static void create_virtio_devices(const VirtMachineState *vms)
1762 qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
1763 2, base, 2, size);
1764 qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
1755 - GIC_FDT_IRQ_TYPE_SPI, irq,
1765 + gic_fdt_irq_type_spi(vms), irq,
1766 GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
1767 qemu_fdt_setprop(ms->fdt, nodename, "dma-coherent", NULL, 0);
1768 g_free(nodename);
@@ -1952,10 +1962,11 @@ static void create_pcie_irq_map(const MachineState *ms,
1962 int devfn, pin;
1963 uint32_t full_irq_map[4 * 4 * 10] = { 0 };
1964 uint32_t *irq_map = full_irq_map;
1965 + const VirtMachineState *vms = VIRT_MACHINE(ms);
1966
1967 for (devfn = 0; devfn <= 0x18; devfn += 0x8) {
1968 for (pin = 0; pin < 4; pin++) {
1958 - int irq_type = GIC_FDT_IRQ_TYPE_SPI;
1969 + int irq_type = gic_fdt_irq_type_spi(vms);
1970 int irq_nr = first_irq + ((pin + PCI_SLOT(devfn)) % PCI_NUM_PINS);
1971 int irq_level = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
1972 int i;
@@ -1996,10 +2007,10 @@ static void create_smmuv3_dt_bindings(const VirtMachineState *vms, hwaddr base,
2007 qemu_fdt_setprop_sized_cells(ms->fdt, node, "reg", 2, base, 2, size);
2008
2009 qemu_fdt_setprop_cells(ms->fdt, node, "interrupts",
1999 - GIC_FDT_IRQ_TYPE_SPI, irq , GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
2000 - GIC_FDT_IRQ_TYPE_SPI, irq + 1, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
2001 - GIC_FDT_IRQ_TYPE_SPI, irq + 2, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
2002 - GIC_FDT_IRQ_TYPE_SPI, irq + 3, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
2010 + gic_fdt_irq_type_spi(vms), irq , GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
2011 + gic_fdt_irq_type_spi(vms), irq + 1, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
2012 + gic_fdt_irq_type_spi(vms), irq + 2, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI,
2013 + gic_fdt_irq_type_spi(vms), irq + 3, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
2014
2015 qemu_fdt_setprop(ms->fdt, node, "interrupt-names", irq_names,
2016 sizeof(irq_names));