From: Marc Zyngier <maz@kernel.org> mainline inclusion from mainline-6.12 commit ef3be86021c3bdf384c36d9d4aa1ee9fe65b95af category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/8904 CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... ---------------------------------------------------------------------- Just like the rest of the FP/SIMD state, FPMR needs to be context switched. The only interesting thing here is that we need to treat the pKVM part a bit differently, as the host FP state is never written back to the vcpu thread, but instead stored locally and eagerly restored. Reviewed-by: Mark Brown <broonie@kernel.org> Tested-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20240820131802.3547589-5-maz@kernel.org Signed-off-by: Marc Zyngier <maz@kernel.org> Conflicts: arch/arm64/include/asm/kvm_host.h arch/arm64/kvm/fpsimd.c arch/arm64/kvm/hyp/include/hyp/switch.h [Modifications adapt to kaki breakage.] Signed-off-by: Qinxin Xia <xiaqinxin@huawei.com> Signed-off-by: Hongye Lin <linhongye@h-partners.com> --- arch/arm64/include/asm/kvm_host.h | 4 ++++ arch/arm64/kvm/fpsimd.c | 3 +++ arch/arm64/kvm/hyp/include/hyp/switch.h | 12 +++++++++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index da553b005182..07e8144d55f7 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -502,6 +502,10 @@ struct kvm_host_data { struct kvm_cpu_context host_ctxt; struct user_fpsimd_state *fpsimd_state; /* hyp VA */ +#ifdef CONFIG_ENABLE_KVM_FPMR + u64 fpmr; +#endif + /* Ownership of the FP regs */ enum { FP_STATE_FREE, diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 9c444a277a17..90fb893e47ba 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -137,6 +137,9 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu) fp_state.sve_vl = vcpu->arch.sve_max_vl; fp_state.sme_state = NULL; fp_state.svcr = &vcpu->arch.svcr; +#ifdef CONFIG_ENABLE_KVM_FPMR + fp_state.fpmr = &__vcpu_sys_reg(vcpu, FPMR); +#endif fp_state.fp_type = &vcpu->arch.fp_type; if (vcpu_has_sve(vcpu)) diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index a28d79608d06..0a1e613fcab6 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -369,8 +369,13 @@ static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code) isb(); /* Write out the host state if it's in the registers */ - if (*host_data_ptr(fp_owner) == FP_STATE_HOST_OWNED) + if (*host_data_ptr(fp_owner) == FP_STATE_HOST_OWNED) { __fpsimd_save_state(*host_data_ptr(fpsimd_state)); +#ifdef CONFIG_ENABLE_KVM_FPMR + if (system_supports_fpmr()) + *host_data_ptr(fpmr) = read_sysreg_s(SYS_FPMR); +#endif + } /* Restore the guest state */ if (sve_guest) @@ -378,6 +383,11 @@ static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code) else __fpsimd_restore_state(&vcpu->arch.ctxt.fp_regs); +#ifdef CONFIG_ENABLE_KVM_FPMR + if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm))) + write_sysreg_s(__vcpu_sys_reg(vcpu, FPMR), SYS_FPMR); +#endif + /* Skip restoring fpexc32 for AArch64 guests */ if (!(read_sysreg(hcr_el2) & HCR_RW)) write_sysreg(__vcpu_sys_reg(vcpu, FPEXC32_EL2), fpexc32_el2); -- 2.25.1