[PATCH] KVM: arm64: VHE: Compute fgt traps before activating them

Alexandru Elisei alexandru.elisei at arm.com
Wed Nov 12 02:28:53 PST 2025


On VHE, the Fine Grain Traps registers are written to hardware in
kvm_arch_vcpu_load()->..->__activate_traps_hfgxtr(), but the fgt array is
computed later, in kvm_vcpu_load_fgt(). This can lead to zero being written
to the FGT registers the first time a VCPU is loaded. Also, any changes to
the fgt array will be visible only after the VCPU is scheduled out, and
then back in, which is not the intended behaviour.

Fix it by computing the fgt array just before the fgt traps are written
to hardware.

Fixes: fb10ddf35c1c ("KVM: arm64: Compute per-vCPU FGTs at vcpu_load()")
Signed-off-by: Alexandru Elisei <alexandru.elisei at arm.com>
---

Stumbled upon this when running a Linux guest on FVP with FEAT_S1PIE
enabled.  Linux touches PIRE0_EL1 very early during boot, in __cpu_setup().
HFGWTR_EL2 was 0 the first time the VCPU was run, KVM would then trap
the access to PIR0_EL1 (PIRE0_EL1 is an inverted trap) and trigger the
BUG_ON(!r->access) from perform_access().

I hacked __activate_traps_hfgxtr() to print the register value for
HFGWTR_EL2. Before this patch, during the first vcpu_load(),
HFGWTR_EL2 is 0, then it has the correct value. After this patch, it
always has the correct value.

If I were to venture a shot in the dark, it might be that the name is a bit
misleading - it's kvm_vpcu_load_fgt(), but it doesn't load anything onto
hardware, it just computes values. Might be worth renaming to avoid
similar ordering issues in the future.

 arch/arm64/kvm/arm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 870953b4a8a7..052bf0d4d0b0 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -624,6 +624,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 	kvm_timer_vcpu_load(vcpu);
 	kvm_vgic_load(vcpu);
 	kvm_vcpu_load_debug(vcpu);
+	kvm_vcpu_load_fgt(vcpu);
 	if (has_vhe())
 		kvm_vcpu_load_vhe(vcpu);
 	kvm_arch_vcpu_load_fp(vcpu);
@@ -642,7 +643,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 		vcpu->arch.hcr_el2 |= HCR_TWI;
 
 	vcpu_set_pauth_traps(vcpu);
-	kvm_vcpu_load_fgt(vcpu);
 
 	if (is_protected_kvm_enabled()) {
 		kvm_call_hyp_nvhe(__pkvm_vcpu_load,

base-commit: e9a6fb0bcdd7609be6969112f3fbfcce3b1d4a7c
-- 
2.51.2




More information about the linux-arm-kernel mailing list