| From a4b22c68e37d494d9cd58e43c65f386e7c645bbd Mon Sep 17 00:00:00 2001 |
| From: Sean Christopherson <sean.j.christopherson@intel.com> |
| Date: Fri, 17 Jan 2020 11:30:49 -0800 |
| Subject: [PATCH] KVM: x86: Handle TIF_NEED_FPU_LOAD in |
| kvm_{load,put}_guest_fpu() |
| |
| commit c9aef3b85f425d1f6635382ec210ee5a7ef55d7d upstream. |
| |
| Handle TIF_NEED_FPU_LOAD similar to how fpu__copy() handles the flag |
| when duplicating FPU state to a new task struct. TIF_NEED_FPU_LOAD can |
| be set any time control is transferred out of KVM, be it voluntarily, |
| e.g. if I/O is triggered during a KVM call to get_user_pages, or |
| involuntarily, e.g. if softirq runs after an IRQ occurs. Therefore, |
| KVM must account for TIF_NEED_FPU_LOAD whenever it is (potentially) |
| accessing CPU FPU state. |
| |
| Fixes: 5f409e20b7945 ("x86/fpu: Defer FPU state load until return to userspace") |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c |
| index 1913ffa97d1b..f95ff4940a0d 100644 |
| --- a/arch/x86/kvm/x86.c |
| +++ b/arch/x86/kvm/x86.c |
| @@ -8330,12 +8330,26 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu) |
| return 0; |
| } |
| |
| +static void kvm_save_current_fpu(struct fpu *fpu) |
| +{ |
| + /* |
| + * If the target FPU state is not resident in the CPU registers, just |
| + * memcpy() from current, else save CPU state directly to the target. |
| + */ |
| + if (test_thread_flag(TIF_NEED_FPU_LOAD)) |
| + memcpy(&fpu->state, ¤t->thread.fpu.state, |
| + fpu_kernel_xstate_size); |
| + else |
| + copy_fpregs_to_fpstate(fpu); |
| +} |
| + |
| /* Swap (qemu) user FPU context for the guest FPU context. */ |
| static void kvm_load_guest_fpu(struct kvm_vcpu *vcpu) |
| { |
| fpregs_lock(); |
| |
| - copy_fpregs_to_fpstate(vcpu->arch.user_fpu); |
| + kvm_save_current_fpu(vcpu->arch.user_fpu); |
| + |
| /* PKRU is separately restored in kvm_x86_ops->run. */ |
| __copy_kernel_to_fpregs(&vcpu->arch.guest_fpu->state, |
| ~XFEATURE_MASK_PKRU); |
| @@ -8351,7 +8365,8 @@ static void kvm_put_guest_fpu(struct kvm_vcpu *vcpu) |
| { |
| fpregs_lock(); |
| |
| - copy_fpregs_to_fpstate(vcpu->arch.guest_fpu); |
| + kvm_save_current_fpu(vcpu->arch.guest_fpu); |
| + |
| copy_kernel_to_fpregs(&vcpu->arch.user_fpu->state); |
| |
| fpregs_mark_activate(); |
| -- |
| 2.7.4 |
| |