diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h index 861049a6416f..5f16c6f800a6 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -121,6 +121,9 @@ void __noreturn __host_enter(struct kvm_cpu_context *host_ctxt); #ifdef __KVM_NVHE_HYPERVISOR__ struct user_fpsimd_state *get_host_fpsimd_state(struct kvm_vcpu *vcpu); struct kvm_host_sve_state *get_host_sve_state(struct kvm_vcpu *vcpu); +#else +#define get_host_fpsimd_state(vcpu) (vcpu)->arch.host_fpsimd_state +#define get_host_sve_state(vcpu) NULL #endif extern u64 kvm_nvhe_sym(id_aa64pfr0_el1_sys_val); diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index 3999a372078a..efcfd44e7012 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -167,7 +168,30 @@ static inline void __hyp_sve_restore_guest(struct kvm_vcpu *vcpu) write_sysreg_el1(__vcpu_sys_reg(vcpu, ZCR_EL1), SYS_ZCR); } -static void kvm_hyp_handle_fpsimd_host(struct kvm_vcpu *vcpu); +static void kvm_hyp_handle_fpsimd_host(struct kvm_vcpu *vcpu) +{ + /* + * Non-protected kvm relies on the host restoring its sve state. + * Protected kvm restores the host's sve state as not to reveal that + * fpsimd was used by a guest nor leak upper sve bits. + */ + if (unlikely(is_protected_kvm_enabled() && system_supports_sve())) { + struct kvm_host_sve_state *sve_state = get_host_sve_state(vcpu); + + sve_state->zcr_el1 = read_sysreg_el1(SYS_ZCR); + sve_cond_update_zcr_vq(sve_vq_from_vl(kvm_host_sve_max_vl) - 1, + SYS_ZCR_EL2); + __sve_save_state(sve_state->sve_regs + + sve_ffr_offset(kvm_host_sve_max_vl), + &sve_state->fpsr); + + /* Still trap SVE since it's handled by hyp in pKVM. */ + if (!vcpu_has_sve(vcpu)) + sysreg_clear_set(cptr_el2, 0, CPTR_EL2_TZ); + } else { + __fpsimd_save_state(get_host_fpsimd_state(vcpu)); + } +} static void __deactivate_fpsimd_traps(struct kvm_vcpu *vcpu); diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c index e75794c40e39..8240ae1ebeb3 100644 --- a/arch/arm64/kvm/hyp/nvhe/switch.c +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -190,31 +190,6 @@ static bool kvm_handle_pvm_sys64(struct kvm_vcpu *vcpu, u64 *exit_code) kvm_handle_pvm_sysreg(vcpu, exit_code)); } -static void kvm_hyp_handle_fpsimd_host(struct kvm_vcpu *vcpu) -{ - /* - * Non-protected kvm relies on the host restoring its sve state. - * Protected kvm restores the host's sve state as not to reveal that - * fpsimd was used by a guest nor leak upper sve bits. - */ - if (unlikely(is_protected_kvm_enabled() && system_supports_sve())) { - struct kvm_host_sve_state *sve_state = get_host_sve_state(vcpu); - - sve_state->zcr_el1 = read_sysreg_el1(SYS_ZCR); - sve_cond_update_zcr_vq(sve_vq_from_vl(kvm_host_sve_max_vl) - 1, - SYS_ZCR_EL2); - __sve_save_state(sve_state->sve_regs + - sve_ffr_offset(kvm_host_sve_max_vl), - &sve_state->fpsr); - - /* Still trap SVE since it's handled by hyp in pKVM. */ - if (!vcpu_has_sve(vcpu)) - sysreg_clear_set(cptr_el2, 0, CPTR_EL2_TZ); - } else { - __fpsimd_save_state(get_host_fpsimd_state(vcpu)); - } -} - static const exit_handler_fn hyp_exit_handlers[] = { [0 ... ESR_ELx_EC_MAX] = NULL, [ESR_ELx_EC_CP15_32] = kvm_hyp_handle_cp15_32, diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c index 747e4eeaab59..b9c8cd61ec7a 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -112,11 +112,6 @@ static void __deactivate_fpsimd_traps(struct kvm_vcpu *vcpu) sysreg_clear_set(cpacr_el1, 0, reg); } -static void kvm_hyp_handle_fpsimd_host(struct kvm_vcpu *vcpu) -{ - __fpsimd_save_state(vcpu->arch.host_fpsimd_state); -} - static const exit_handler_fn hyp_exit_handlers[] = { [0 ... ESR_ELx_EC_MAX] = NULL, [ESR_ELx_EC_CP15_32] = kvm_hyp_handle_cp15_32,