Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: arm64: gic-v5: Add emulation for ICC_IAFFIDR_EL1 accesses

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 <timothy.hayes@arm.com>
Signed-off-by: Timothy Hayes <timothy.hayes@arm.com>
Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Link: https://patch.msgid.link/20260319154937.3619520-15-sascha.bischoff@arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>

authored by

Sascha Bischoff
Timothy Hayes
and committed by
Marc Zyngier
607871ce 9d6d9514

+30 -1
+9 -1
arch/arm64/kvm/config.c
··· 1684 1684 *vcpu_fgt(vcpu, HDFGWTR_EL2) |= HDFGWTR_EL2_MDSCR_EL1; 1685 1685 } 1686 1686 1687 + static void __compute_ich_hfgrtr(struct kvm_vcpu *vcpu) 1688 + { 1689 + __compute_fgt(vcpu, ICH_HFGRTR_EL2); 1690 + 1691 + /* ICC_IAFFIDR_EL1 *always* needs to be trapped when running a guest */ 1692 + *vcpu_fgt(vcpu, ICH_HFGRTR_EL2) &= ~ICH_HFGRTR_EL2_ICC_IAFFIDR_EL1; 1693 + } 1694 + 1687 1695 void kvm_vcpu_load_fgt(struct kvm_vcpu *vcpu) 1688 1696 { 1689 1697 if (!cpus_have_final_cap(ARM64_HAS_FGT)) ··· 1713 1705 } 1714 1706 1715 1707 if (cpus_have_final_cap(ARM64_HAS_GICV5_CPUIF)) { 1716 - __compute_fgt(vcpu, ICH_HFGRTR_EL2); 1708 + __compute_ich_hfgrtr(vcpu); 1717 1709 __compute_fgt(vcpu, ICH_HFGWTR_EL2); 1718 1710 __compute_fgt(vcpu, ICH_HFGITR_EL2); 1719 1711 }
+16
arch/arm64/kvm/sys_regs.c
··· 681 681 return true; 682 682 } 683 683 684 + static bool access_gicv5_iaffid(struct kvm_vcpu *vcpu, struct sys_reg_params *p, 685 + const struct sys_reg_desc *r) 686 + { 687 + if (p->is_write) 688 + return undef_access(vcpu, p, r); 689 + 690 + /* 691 + * For GICv5 VMs, the IAFFID value is the same as the VPE ID. The VPE ID 692 + * is the same as the VCPU's ID. 693 + */ 694 + p->regval = FIELD_PREP(ICC_IAFFIDR_EL1_IAFFID, vcpu->vcpu_id); 695 + 696 + return true; 697 + } 698 + 684 699 static bool trap_raz_wi(struct kvm_vcpu *vcpu, 685 700 struct sys_reg_params *p, 686 701 const struct sys_reg_desc *r) ··· 3420 3405 { SYS_DESC(SYS_ICC_AP1R1_EL1), undef_access }, 3421 3406 { SYS_DESC(SYS_ICC_AP1R2_EL1), undef_access }, 3422 3407 { SYS_DESC(SYS_ICC_AP1R3_EL1), undef_access }, 3408 + { SYS_DESC(SYS_ICC_IAFFIDR_EL1), access_gicv5_iaffid }, 3423 3409 { SYS_DESC(SYS_ICC_DIR_EL1), access_gic_dir }, 3424 3410 { SYS_DESC(SYS_ICC_RPR_EL1), undef_access }, 3425 3411 { SYS_DESC(SYS_ICC_SGI1R_EL1), access_gic_sgi },
+5
arch/arm64/kvm/vgic/vgic.h
··· 447 447 return kvm_has_feat(kvm, ID_AA64PFR0_EL1, GIC, IMP); 448 448 } 449 449 450 + static inline bool kvm_has_gicv5(struct kvm *kvm) 451 + { 452 + return kvm_has_feat(kvm, ID_AA64PFR2_EL1, GCIE, IMP); 453 + } 454 + 450 455 void vgic_v3_flush_nested(struct kvm_vcpu *vcpu); 451 456 void vgic_v3_sync_nested(struct kvm_vcpu *vcpu); 452 457 void vgic_v3_load_nested(struct kvm_vcpu *vcpu);