[PATCH v4 07/48] KVM: arm64: gic-v5: Extract host IRS caps from IRS config frame
Marc Zyngier
maz at kernel.org
Sat Jul 25 03:40:04 PDT 2026
On Fri, 24 Jul 2026 11:50:13 +0100,
Sascha Bischoff <Sascha.Bischoff at arm.com> wrote:
>
> 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);
Not a big deal, but I'm a bit over this split of ID regs in individual
fields. It looks appealing at first, but ends-up being problematic.
The reason for this is that EL2 doesn't map kvm_vgic_global_state,
which will eventually force pKVM to either duplicate the structure, or
access the ID reg directly (the latter resulting in traps under NV).
My preference would be to only cache the raw ID reg values, and have
inline accessors for the individual fields. Once this is in place, we
can patch the ID reg values in the code directly, ICH_VTR_EL2-style.
Anyway, something to think about.
Thanks,
M.
--
Jazz isn't dead. It just smells funny.
More information about the linux-arm-kernel
mailing list