Thread (73 messages) 73 messages, 6 authors, 2026-01-07

Re: [PATCH 10/32] KVM: arm64: gic-v5: Add emulation for ICC_IAFFID_EL1 accesses

From: Sascha Bischoff <hidden>
Date: 2025-12-16 10:58:55
Also in: kvm, kvmarm

On Mon, 2025-12-15 at 17:31 +0000, Marc Zyngier wrote:
On Fri, 12 Dec 2025 15:22:38 +0000,
Sascha Bischoff [off-list ref] wrote:
quoted
GICv5 doesn't include an ICV_IAFFIDR_EL1 or ICH_IAFFIDR_EL2 for
providing the IAFFID to the guest. A guest access to the
ICH_IAFFIDR_EL1 must therefore be trapped and emulated to avoid the
nit: ICC_IAFFIDR_EL1. There is no ICH_*_EL1 register.
quoted
guest accessing the host's ICC_IAFFIDR_EL1.

For GICv5, the VPE ID corresponds to the virtual IAFFID for the
purposes of specifying the affinity of virtual interrupts. The VPE
ID
is the index into the VPE Table, which will be the same as the
vcpu->vcpu_id once the various GICv5 VM tables are introduced. At
this
stage, said VM tables have yet to be introduced as they are not
required for PPI support. Moreover, the IAFFID should go largely
unused by any guest using just PPIs as they are not routable to a
different PE. That said, we still need to trap and emulate the
guest's
accesses to avoid leaking host state into the guest.
I think you can trim some of this. Just state that KVM makes the
IAFFIDR, VPEID and vcpu_id the same thing, and that'll be good
enough.
quoted
The virtual IAFFID is provided to the guest when it reads
ICC_IAFFID_EL1 (which always traps back to the hypervisor). Writes
are
rightly ignored.

The trapping for the ICC_IAFFIDR_EL2 is always enabled when in a
guest
context.
This register doesn't exist either.
Yikes. I really wasn't having a good day with my register names. I've
addressed these now and have compacted down that paragraph.
quoted
Co-authored-by: Timothy Hayes [off-list ref]
Signed-off-by: Timothy Hayes <redacted>
Signed-off-by: Sascha Bischoff <redacted>
---
 arch/arm64/kvm/config.c   | 10 +++++++++-
 arch/arm64/kvm/sys_regs.c | 19 +++++++++++++++++++
 2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/config.c b/arch/arm64/kvm/config.c
index 57ef67f718113..cbdd8ac90f4d0 100644
--- a/arch/arm64/kvm/config.c
+++ b/arch/arm64/kvm/config.c
@@ -1582,6 +1582,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;
Slightly redundant when !GICv5 in the guest, but that's not really a
problem.
quoted
+}
+
 void kvm_vcpu_load_fgt(struct kvm_vcpu *vcpu)
 {
 	if (!cpus_have_final_cap(ARM64_HAS_FGT))
@@ -1607,7 +1615,7 @@ void kvm_vcpu_load_fgt(struct kvm_vcpu *vcpu)
 	if (!cpus_have_final_cap(ARM64_HAS_GICV5_CPUIF))
 		return;
 
-	__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 fbbd7b6ff6507..31c08fd591d08 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 (!vgic_is_v5(vcpu->kvm))
+		return undef_access(vcpu, p, r);
Shouldn't this be readily handled by the FGU configuration in the
absence of GICv5 in the guest?
Yeah, it should be. This was written before GICv5 was plumbed into the
FGUs. I've just tested it, and it undefs correctly without the explicit
check, so I've dropped this.

Thanks,
Sascha
quoted
+
+	if (p->is_write)
+		return ignore_write(vcpu, p);
+
+	/*
+	 * For GICv5 VMs, the IAFFID value is the same as the VPE
ID. The VPE ID
+	 * is the same as the VCPU's ID.
+	 */
+	p->regval = FIELD_PREP(ICC_IAFFIDR_EL1_IAFFID, vcpu-
quoted
vcpu_id);
+
+	return true;
+}
+
 static bool trap_raz_wi(struct kvm_vcpu *vcpu,
 			struct sys_reg_params *p,
 			const struct sys_reg_desc *r)
@@ -3411,6 +3429,7 @@ static const struct sys_reg_desc
sys_reg_descs[] = {
 	{ SYS_DESC(SYS_ICC_AP1R1_EL1), undef_access },
 	{ SYS_DESC(SYS_ICC_AP1R2_EL1), undef_access },
 	{ SYS_DESC(SYS_ICC_AP1R3_EL1), undef_access },
+	{ SYS_DESC(SYS_ICC_IAFFIDR_EL1), access_gicv5_iaffid },
 	{ SYS_DESC(SYS_ICC_DIR_EL1), access_gic_dir },
 	{ SYS_DESC(SYS_ICC_RPR_EL1), undef_access },
 	{ SYS_DESC(SYS_ICC_SGI1R_EL1), access_gic_sgi },
Thanks,

	M.
  
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help