@samitouri / QOSamiQemu / commits / c41215f1a9

hw/arm/virt: Handle GICv5 in interrupt bindings for PPIs

The GICv5 devicetree binding specifies the "interrupts" property differently to GICv2 and GICv3 for PPIs: the first field is the architectural INTID.TYPE, and the second is the architectural INTID.ID. (The third field defining the level/edge trigger mode has the same values for GICv5 as it did for the older GICs.) In the places in the virt board where we wire up PPIs (the timer and the PMU), handle the GICv5: * use the architectural constant GICV5_PPI for the type * use the architected GICv5 PPI numbers for the interrupt sources (which differ from the old ones and don't need to be adjusted via INTID_TO_PPI()) * leave the irqflags as-is Add some commentary in our include/hw/arm/fdt.h file about what the the constants defined there are valid for. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Message-id: 20260327111700.795099-63-peter.maydell@linaro.org

Peter Maydell committed Mar 27, 2026 at 11:16 UTC c41215f1a957ee2ef941eeb8303295688ded378a
2 files changed +29 -4
hw/arm/virt.c
+19 -4
@@ -500,7 +500,15 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
500 "arm,armv7-timer");
501 }
502 qemu_fdt_setprop(ms->fdt, "/timer", "always-on", NULL, 0);
503 - if (vms->ns_el2_virt_timer_irq) {
503 + if (vms->gic_version == VIRT_GIC_VERSION_5) {
504 + /* The GICv5 architects the PPI numbers differently */
505 + qemu_fdt_setprop_cells(ms->fdt, "/timer", "interrupts",
506 + GICV5_PPI, GICV5_PPI_CNTPS, irqflags,
507 + GICV5_PPI, GICV5_PPI_CNTP, irqflags,
508 + GICV5_PPI, GICV5_PPI_CNTV, irqflags,
509 + GICV5_PPI, GICV5_PPI_CNTHP, irqflags,
510 + GICV5_PPI, GICV5_PPI_CNTHV, irqflags);
511 + } else if (vms->ns_el2_virt_timer_irq) {
512 qemu_fdt_setprop_cells(ms->fdt, "/timer", "interrupts",
513 GIC_FDT_IRQ_TYPE_PPI,
514 INTID_TO_PPI(ARCH_TIMER_S_EL1_IRQ), irqflags,
@@ -1025,11 +1033,18 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
1033 qemu_fdt_add_subnode(ms->fdt, "/pmu");
1034 if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) {
1035 const char compat[] = "arm,armv8-pmuv3";
1036 +
1037 qemu_fdt_setprop(ms->fdt, "/pmu", "compatible",
1038 compat, sizeof(compat));
1030 - qemu_fdt_setprop_cells(ms->fdt, "/pmu", "interrupts",
1031 - GIC_FDT_IRQ_TYPE_PPI,
1032 - INTID_TO_PPI(VIRTUAL_PMU_IRQ), irqflags);
1039 + if (vms->gic_version == VIRT_GIC_VERSION_5) {
1040 + qemu_fdt_setprop_cells(ms->fdt, "/pmu", "interrupts",
1041 + GICV5_PPI, GICV5_PPI_PMUIRQ, irqflags);
1042 + } else {
1043 + qemu_fdt_setprop_cells(ms->fdt, "/pmu", "interrupts",
1044 + GIC_FDT_IRQ_TYPE_PPI,
1045 + INTID_TO_PPI(VIRTUAL_PMU_IRQ),
1046 + irqflags);
1047 + }
1048 }
1049 }
1050
include/hw/arm/fdt.h
+10
@@ -20,9 +20,19 @@
20 #ifndef QEMU_ARM_FDT_H
21 #define QEMU_ARM_FDT_H
22
23 +/*
24 + * These are for GICv2/v3/v4 only; GICv5 encodes the interrupt type in
25 + * the DTB "interrupts" properties differently, using constants that
26 + * match the architectural INTID.Type. In QEMU those are available as
27 + * the GICV5_PPI and GICV5_SPI enum values in arm_gicv5_types.h.
28 + */
29 #define GIC_FDT_IRQ_TYPE_SPI 0
30 #define GIC_FDT_IRQ_TYPE_PPI 1
31
32 +/*
33 + * The trigger type/level field in the DTB "interrupts" property has
34 + * the same encoding for GICv2/v3/v4 and v5.
35 + */
36 #define GIC_FDT_IRQ_FLAGS_EDGE_LO_HI 1
37 #define GIC_FDT_IRQ_FLAGS_EDGE_HI_LO 2
38 #define GIC_FDT_IRQ_FLAGS_LEVEL_HI 4