[PATCH 10/32] KVM: arm64: gic-v5: Add emulation for ICC_IAFFID_EL1 accesses
Sascha Bischoff
Sascha.Bischoff at arm.com
Fri Dec 12 07:22:38 PST 2025
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
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.
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.
Co-authored-by: Timothy Hayes <timothy.hayes at arm.com>
Signed-off-by: Timothy Hayes <timothy.hayes at arm.com>
Signed-off-by: Sascha Bischoff <sascha.bischoff at arm.com>
---
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;
+}
+
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);
+
+ 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->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 },
--
2.34.1
More information about the linux-arm-kernel
mailing list