]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: arm64: gic-v5: Detect implemented PPIs on boot
authorSascha Bischoff <Sascha.Bischoff@arm.com>
Thu, 19 Mar 2026 15:52:34 +0000 (15:52 +0000)
committerMarc Zyngier <maz@kernel.org>
Thu, 19 Mar 2026 18:21:27 +0000 (18:21 +0000)
As part of booting the system and initialising KVM, create and
populate a mask of the implemented PPIs. This mask allows future PPI
operations (such as save/restore or state, or syncing back into the
shadow state) to only consider PPIs that are actually implemented on
the host.

The set of implemented virtual PPIs matches the set of implemented
physical PPIs for a GICv5 host. Therefore, this mask represents all
PPIs that could ever by used by a GICv5-based guest on a specific
host, albeit pre-filtered by what we support in KVM (see next
paragraph).

Only architected PPIs are currently supported in KVM with
GICv5. Moreover, as KVM only supports a subset of all possible PPIS
(Timers, PMU, GICv5 SW_PPI) the PPI mask only includes these PPIs, if
present. The timers are always assumed to be present; if we have KVM
we have EL2, which means that we have the EL1 & EL2 Timer PPIs. If we
have a PMU (v3), then the PMUIRQ is present. The GICv5 SW_PPI is
always assumed to be present.

Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Link: https://patch.msgid.link/20260319154937.3619520-12-sascha.bischoff@arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/vgic/vgic-v5.c
include/kvm/arm_vgic.h
include/linux/irqchip/arm-gic-v5.h

index 9d9aa5774e6344865da706f306bfea2af1e8e07d..cf8382a954bbcf9bc4c2f2d3e3a552595b6374dd 100644 (file)
@@ -4,10 +4,39 @@
  */
 
 #include <kvm/arm_vgic.h>
+
+#include <linux/bitops.h>
 #include <linux/irqchip/arm-vgic-info.h>
 
 #include "vgic.h"
 
+static struct vgic_v5_ppi_caps ppi_caps;
+
+/*
+ * Not all PPIs are guaranteed to be implemented for GICv5. Deterermine which
+ * ones are, and generate a mask.
+ */
+static void vgic_v5_get_implemented_ppis(void)
+{
+       if (!cpus_have_final_cap(ARM64_HAS_GICV5_CPUIF))
+               return;
+
+       /*
+        * If we have KVM, we have EL2, which means that we have support for the
+        * EL1 and EL2 Physical & Virtual timers.
+        */
+       __assign_bit(GICV5_ARCH_PPI_CNTHP, ppi_caps.impl_ppi_mask, 1);
+       __assign_bit(GICV5_ARCH_PPI_CNTV, ppi_caps.impl_ppi_mask, 1);
+       __assign_bit(GICV5_ARCH_PPI_CNTHV, ppi_caps.impl_ppi_mask, 1);
+       __assign_bit(GICV5_ARCH_PPI_CNTP, ppi_caps.impl_ppi_mask, 1);
+
+       /* The SW_PPI should be available */
+       __assign_bit(GICV5_ARCH_PPI_SW_PPI, ppi_caps.impl_ppi_mask, 1);
+
+       /* The PMUIRQ is available if we have the PMU */
+       __assign_bit(GICV5_ARCH_PPI_PMUIRQ, ppi_caps.impl_ppi_mask, system_supports_pmuv3());
+}
+
 /*
  * Probe for a vGICv5 compatible interrupt controller, returning 0 on success.
  * Currently only supports GICv3-based VMs on a GICv5 host, and hence only
@@ -18,6 +47,8 @@ int vgic_v5_probe(const struct gic_kvm_info *info)
        u64 ich_vtr_el2;
        int ret;
 
+       vgic_v5_get_implemented_ppis();
+
        if (!cpus_have_final_cap(ARM64_HAS_GICV5_LEGACY))
                return -ENODEV;
 
index b8011b395796d2af65cd42254d58b17a097adfda..0fabeabedd6d7f6c4210e0dd9e74950e521e441b 100644 (file)
 #define VGIC_MIN_LPI           8192
 #define KVM_IRQCHIP_NUM_PINS   (1020 - 32)
 
+/*
+ * GICv5 supports 128 PPIs, but only the first 64 are architected. We only
+ * support the timers and PMU in KVM, both of which are architected. Rather than
+ * handling twice the state, we instead opt to only support the architected set
+ * in KVM for now. At a future stage, this can be bumped up to 128, if required.
+ */
+#define VGIC_V5_NR_PRIVATE_IRQS        64
+
 #define is_v5_type(t, i)       (FIELD_GET(GICV5_HWIRQ_TYPE, (i)) == (t))
 
 #define __irq_is_sgi(t, i)                                             \
@@ -420,6 +428,11 @@ struct vgic_v3_cpu_if {
        unsigned int used_lrs;
 };
 
+/* What PPI capabilities does a GICv5 host have */
+struct vgic_v5_ppi_caps {
+       DECLARE_BITMAP(impl_ppi_mask, VGIC_V5_NR_PRIVATE_IRQS);
+};
+
 struct vgic_cpu {
        /* CPU vif control registers for world switch */
        union {
index b78488df6c989d6f3dcffce58fc170e0951fbc55..b1566a7c93ecb4294732da9380718014f48a79e2 100644 (file)
 #define GICV5_HWIRQ_TYPE_LPI           UL(0x2)
 #define GICV5_HWIRQ_TYPE_SPI           UL(0x3)
 
+/*
+ * Architected PPIs
+ */
+#define GICV5_ARCH_PPI_S_DB_PPI                0x0
+#define GICV5_ARCH_PPI_RL_DB_PPI       0x1
+#define GICV5_ARCH_PPI_NS_DB_PPI       0x2
+#define GICV5_ARCH_PPI_SW_PPI          0x3
+#define GICV5_ARCH_PPI_HACDBSIRQ       0xf
+#define GICV5_ARCH_PPI_CNTHVS          0x13
+#define GICV5_ARCH_PPI_CNTHPS          0x14
+#define GICV5_ARCH_PPI_PMBIRQ          0x15
+#define GICV5_ARCH_PPI_COMMIRQ         0x16
+#define GICV5_ARCH_PPI_PMUIRQ          0x17
+#define GICV5_ARCH_PPI_CTIIRQ          0x18
+#define GICV5_ARCH_PPI_GICMNT          0x19
+#define GICV5_ARCH_PPI_CNTHP           0x1a
+#define GICV5_ARCH_PPI_CNTV            0x1b
+#define GICV5_ARCH_PPI_CNTHV           0x1c
+#define GICV5_ARCH_PPI_CNTPS           0x1d
+#define GICV5_ARCH_PPI_CNTP            0x1e
+#define GICV5_ARCH_PPI_TRBIRQ          0x1f
+
 /*
  * Tables attributes
  */