Subject: Re: [PATCH v5 12/36] KVM: arm64: gic-v5: Add emulation for ICC_IAFFIDR_EL1 accesses

From: Marc Zyngier <[email-masked]>
Date: Tue, 03 Mar 2026 16:02:36 +0000

On Thu, 26 Feb 2026 15:58:31 +0000,
Sascha Bischoff <[email-masked]> wrote:
> 
> GICv5 doesn't provide an ICV_IAFFIDR_EL1 or ICH_IAFFIDR_EL2 for
> providing the IAFFID to the guest. A guest access to the
> ICC_IAFFIDR_EL1 must therefore be trapped and emulated to avoid the
> guest accessing the host's ICC_IAFFIDR_EL1.
> 
> The virtual IAFFID is provided to the guest when it reads
> ICC_IAFFIDR_EL1 (which always traps back to the hypervisor). Writes are
> rightly ignored. KVM treats the GICv5 VPEID, the virtual IAFFID, and
> the vcpu_id as the same, and so the vcpu_id is returned.
> 
> The trapping for the ICC_IAFFIDR_EL1 is always enabled when in a guest
> context.
> 
> Co-authored-by: Timothy Hayes <[email-masked]>
> Signed-off-by: Timothy Hayes <[email-masked]>
> Signed-off-by: Sascha Bischoff <[email-masked]>
> ---
>  arch/arm64/kvm/config.c    | 10 +++++++++-
>  arch/arm64/kvm/sys_regs.c  | 19 +++++++++++++++++++
>  arch/arm64/kvm/vgic/vgic.h |  5 +++++
>  3 files changed, 33 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
> index e4ec1bda8dfcb..bac5f49fdbdef 100644
> --- a/arch/arm64/kvm/config.c
> +++ b/arch/arm64/kvm/config.c
> @@ -1684,6 +1684,14 @@ static void __compute_hdfgwtr(struct kvm_vcpu *vcpu)
>  		*vcpu_fgt(vcpu, HDFGWTR_EL2) |= HDFGWTR_EL2_MDSCR_EL1;
>  }
>  
> +static void __compute_ich_hfgrtr(struct kvm_vcpu *vcpu)
> +{
> +	__compute_fgt(vcpu, ICH_HFGRTR_EL2);
> +
> +	/* ICC_IAFFIDR_EL1 *always* needs to be trapped when running a guest */
> +	*vcpu_fgt(vcpu, ICH_HFGRTR_EL2) &= ~ICH_HFGRTR_EL2_ICC_IAFFIDR_EL1;
> +}
> +
>  void kvm_vcpu_load_fgt(struct kvm_vcpu *vcpu)
>  {
>  	if (!cpus_have_final_cap(ARM64_HAS_FGT))
> @@ -1705,7 +1713,7 @@ void kvm_vcpu_load_fgt(struct kvm_vcpu *vcpu)
>  	}
>  
>  	if (cpus_have_final_cap(ARM64_HAS_GICV5_CPUIF)) {
> -		__compute_fgt(vcpu, ICH_HFGRTR_EL2);
> +		__compute_ich_hfgrtr(vcpu);
>  		__compute_fgt(vcpu, ICH_HFGWTR_EL2);
>  		__compute_fgt(vcpu, ICH_HFGITR_EL2);
>  	}
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index b8b86f5e1adc1..384824e875603 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -681,6 +681,24 @@ static bool access_gic_dir(struct kvm_vcpu *vcpu,
>  	return true;
>  }
>  
> +static bool access_gicv5_iaffid(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> +				const struct sys_reg_desc *r)
> +{
> +	if (!kvm_has_gicv5(vcpu->kvm))
> +		return undef_access(vcpu, p, r);

Do we really need this? If the guest doesn't have FEAT_GCIE, then we
should have an FGU bit set for any FGT bit that control a GCIE
register, and that register should UNDEF at the point of triaging the
trap, and never reach this handler.

If it doesn't, we have bigger problems, and we should address them.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.