[PATCH v2 07/39] KVM: arm64: gic-v5: Extract host IRS caps from IRS config frame
Sascha Bischoff
Sascha.Bischoff at arm.com
Thu May 21 07:51:31 PDT 2026
The host irqchip driver provides KVM with a pointer to an IRS's config
frame, which allows KVM to directly interact with the host's IRS. The
MMIO registers in the config frame are used to configure VMs (in
addition to them being used by the host). The IRS's config frame also
includes a set of ID registers which describe the capabilities that
the IRS has.
Stash the pointer to the config frame, and extract the VM capabilities
(from IRS_IDR3 & IRS_IDR4), as well as the IST
capabilities/requirements (IRS_IDR2) from the IRS.
Signed-off-by: Sascha Bischoff <sascha.bischoff at arm.com>
---
arch/arm64/kvm/vgic/vgic-v5.c | 46 +++++++++++++++++++++++++++++++++--
include/kvm/arm_vgic.h | 26 ++++++++++++++++++++
2 files changed, 70 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-v5.c b/arch/arm64/kvm/vgic/vgic-v5.c
index d4789ff3e7402..3f7b132110114 100644
--- a/arch/arm64/kvm/vgic/vgic-v5.c
+++ b/arch/arm64/kvm/vgic/vgic-v5.c
@@ -11,6 +11,7 @@
#include "vgic.h"
#define ppi_caps kvm_vgic_global_state.vgic_v5_ppi_caps
+#define irs_caps kvm_vgic_global_state.vgic_v5_irs_caps
/*
* Not all PPIs are guaranteed to be implemented for GICv5. Deterermine which
@@ -34,6 +35,45 @@ static void vgic_v5_get_implemented_ppis(void)
__assign_bit(GICV5_ARCH_PPI_PMUIRQ, ppi_caps.impl_ppi_mask, system_supports_pmuv3());
}
+static u32 irs_readl_relaxed(const u32 reg_offset)
+{
+ return readl_relaxed(irs_caps.irs_base + reg_offset);
+}
+
+static void vgic_v5_irs_extract_vm_caps(const struct gic_kvm_info *info)
+{
+ u64 idr;
+
+ irs_caps.irs_base = info->gicv5_irs.base;
+ irs_caps.non_coherent = info->gicv5_irs.non_coherent;
+
+ idr = irs_readl_relaxed(GICV5_IRS_IDR2);
+
+ /* We skip the LPI field as it only applies to physical LPIs */
+ irs_caps.ist_id_bits = FIELD_GET(GICV5_IRS_IDR2_ID_BITS, idr);
+ irs_caps.min_lpi_id_bits = FIELD_GET(GICV5_IRS_IDR2_MIN_LPI_ID_BITS, idr);
+ irs_caps.ist_levels = (idr & GICV5_IRS_IDR2_IST_LEVELS);
+ irs_caps.ist_l2sz = FIELD_GET(GICV5_IRS_IDR2_IST_L2SZ, idr);
+ irs_caps.istmd = (idr & GICV5_IRS_IDR2_ISTMD);
+ irs_caps.istmd_sz = FIELD_GET(GICV5_IRS_IDR2_ISTMD_SZ, idr);
+
+ idr = irs_readl_relaxed(GICV5_IRS_IDR3);
+
+ irs_caps.max_vms = BIT(FIELD_GET(GICV5_IRS_IDR3_VM_ID_BITS, idr));
+ irs_caps.two_level_vmt_support = (idr & GICV5_IRS_IDR3_VMT_LEVELS);
+
+ if (idr & GICV5_IRS_IDR3_VMD)
+ irs_caps.vmd_size = BIT(FIELD_GET(GICV5_IRS_IDR3_VMD_SZ, idr));
+ else
+ irs_caps.vmd_size = 0;
+
+ idr = irs_readl_relaxed(GICV5_IRS_IDR4);
+
+ irs_caps.vped_size = BIT(FIELD_GET(GICV5_IRS_IDR4_VPED_SZ, idr));
+ /* Field stores VPE_ID_BITS - 1 */
+ irs_caps.max_vpes = BIT(FIELD_GET(GICV5_IRS_IDR4_VPE_ID_BITS, idr) + 1);
+}
+
/*
* Probe for a vGICv5 compatible interrupt controller, returning 0 on success.
*/
@@ -61,10 +101,12 @@ int vgic_v5_probe(const struct gic_kvm_info *info)
goto skip_v5;
}
- kvm_vgic_global_state.max_gic_vcpus = VGIC_V5_MAX_CPUS;
-
+ vgic_v5_irs_extract_vm_caps(info);
vgic_v5_get_implemented_ppis();
+ kvm_vgic_global_state.max_gic_vcpus = min(irs_caps.max_vpes,
+ VGIC_V5_MAX_CPUS);
+
ret = kvm_register_vgic_device(KVM_DEV_TYPE_ARM_VGIC_V5);
if (ret) {
kvm_err("Cannot register GICv5 KVM device.\n");
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index fe49fb56dc3c9..8d65a18fefb80 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -182,6 +182,32 @@ struct vgic_global {
struct {
DECLARE_BITMAP(impl_ppi_mask, VGIC_V5_NR_PRIVATE_IRQS);
} vgic_v5_ppi_caps;
+
+ /* GICv5 IRS capabilities */
+ struct {
+ /* Base address of the host IRS's CONFIG_FRAME */
+ void __iomem *irs_base;
+
+ /* IST Caps */
+ u8 ist_id_bits;
+ bool ist_levels;
+ u8 ist_l2sz;
+ bool istmd;
+ u8 istmd_sz;
+
+ /* LPI only */
+ u8 min_lpi_id_bits;
+
+ /* VM Table, VPE Table */
+ bool two_level_vmt_support;
+ u32 max_vms;
+ u32 max_vpes;
+ u16 vmd_size;
+ u16 vped_size;
+
+ /* Is the IRS coherent with us, or not? */
+ bool non_coherent;
+ } vgic_v5_irs_caps;
};
extern struct vgic_global kvm_vgic_global_state;
--
2.34.1
More information about the linux-arm-kernel
mailing list