Skip to content

Commit 186b58b

Browse files
mrutland-armMarc Zyngier
authored andcommitted
KVM: arm64: Remove ad-hoc CPTR manipulation from kvm_hyp_handle_fpsimd()
The hyp code FPSIMD/SVE/SME trap handling logic has some rather messy open-coded manipulation of CPTR/CPACR. This is benign for non-nested guests, but broken for nested guests, as the guest hypervisor's CPTR configuration is not taken into account. Consider the case where L0 provides FPSIMD+SVE to an L1 guest hypervisor, and the L1 guest hypervisor only provides FPSIMD to an L2 guest (with L1 configuring CPTR/CPACR to trap SVE usage from L2). If the L2 guest triggers an FPSIMD trap to the L0 hypervisor, kvm_hyp_handle_fpsimd() will see that the vCPU supports FPSIMD+SVE, and will configure CPTR/CPACR to NOT trap FPSIMD+SVE before returning to the L2 guest. Consequently the L2 guest would be able to manipulate SVE state even though the L1 hypervisor had configured CPTR/CPACR to forbid this. Clean this up, and fix the nested virt issue by always using __deactivate_cptr_traps() and __activate_cptr_traps() to manage the CPTR traps. This removes the need for the ad-hoc fixup in kvm_hyp_save_fpsimd_host(), and ensures that any guest hypervisor configuration of CPTR/CPACR is taken into account. Signed-off-by: Mark Rutland <[email protected]> Cc: Catalin Marinas <[email protected]> Cc: Fuad Tabba <[email protected]> Cc: Marc Zyngier <[email protected]> Cc: Mark Brown <[email protected]> Cc: Oliver Upton <[email protected]> Cc: Will Deacon <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Marc Zyngier <[email protected]>
1 parent 59e6e10 commit 186b58b

File tree

1 file changed

+8
-9
lines changed

1 file changed

+8
-9
lines changed

arch/arm64/kvm/hyp/include/hyp/switch.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -616,11 +616,6 @@ static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu)
616616
*/
617617
if (system_supports_sve()) {
618618
__hyp_sve_save_host();
619-
620-
/* Re-enable SVE traps if not supported for the guest vcpu. */
621-
if (!vcpu_has_sve(vcpu))
622-
cpacr_clear_set(CPACR_EL1_ZEN, 0);
623-
624619
} else {
625620
__fpsimd_save_state(host_data_ptr(host_ctxt.fp_regs));
626621
}
@@ -671,10 +666,7 @@ static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
671666
/* Valid trap. Switch the context: */
672667

673668
/* First disable enough traps to allow us to update the registers */
674-
if (sve_guest || (is_protected_kvm_enabled() && system_supports_sve()))
675-
cpacr_clear_set(0, CPACR_EL1_FPEN | CPACR_EL1_ZEN);
676-
else
677-
cpacr_clear_set(0, CPACR_EL1_FPEN);
669+
__deactivate_cptr_traps(vcpu);
678670
isb();
679671

680672
/* Write out the host state if it's in the registers */
@@ -696,6 +688,13 @@ static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code)
696688

697689
*host_data_ptr(fp_owner) = FP_STATE_GUEST_OWNED;
698690

691+
/*
692+
* Re-enable traps necessary for the current state of the guest, e.g.
693+
* those enabled by a guest hypervisor. The ERET to the guest will
694+
* provide the necessary context synchronization.
695+
*/
696+
__activate_cptr_traps(vcpu);
697+
699698
return true;
700699
}
701700

0 commit comments

Comments
 (0)