Update the PMU code to interact correctly with the GICV5 support in KVM and the guest. This change comprises two parts: The first is to update the interrupt specifier used for the FDT to generate a GICv5-compatible description of the PMU overflow interrupt. The second is to correctly convey the PPI used for the overflow interrupt to KVM itself. This needs to be in the correct GICv5 interrupt ID format (type + ID), which requires the interrupt type in the top bits. Moreover, it must match the architecturally defined PMUIRQ for GICv5, or else KVM will reject it for a GICv5-based guest. Signed-off-by: Sascha Bischoff --- arm64/pmu.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/arm64/pmu.c b/arm64/pmu.c index 5f31d6b6..f6316425 100644 --- a/arm64/pmu.c +++ b/arm64/pmu.c @@ -197,13 +197,8 @@ void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm) struct kvm_cpu *vcpu; int pmu_id = -ENXIO; int i; - + u32 irq_prop[3]; u32 cpu_mask = gic__get_fdt_irq_cpumask(kvm); - u32 irq_prop[] = { - cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI), - cpu_to_fdt32(irq - 16), - cpu_to_fdt32(cpu_mask | IRQ_TYPE_LEVEL_HIGH), - }; if (!kvm->cfg.arch.has_pmuv3) return; @@ -216,6 +211,22 @@ void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm) } } + if (gic__is_v5()) { + irq_prop[0] = cpu_to_fdt32(GICV5_FDT_IRQ_TYPE_PPI); + irq_prop[1] = cpu_to_fdt32(irq); + } else { + irq_prop[0] = cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI); + irq_prop[1] = cpu_to_fdt32(irq - 16); + } + irq_prop[2] = cpu_to_fdt32(cpu_mask | IRQ_TYPE_LEVEL_HIGH); + + /* + * For GICv5, we must encode the full IntID by adding the type (PPI) + * when setting the PMUIRQ. + */ + if (gic__is_v5()) + irq |= GICV5_FDT_IRQ_TYPE_PPI << GICV5_FDT_IRQ_TYPE_SHIFT; + for (i = 0; i < kvm->nrcpus; i++) { vcpu = kvm->cpus[i]; set_pmu_attr(vcpu, &irq, KVM_ARM_VCPU_PMU_V3_IRQ); -- 2.34.1