4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Andy Lutomirski <[email protected]>

commit 5ed73f40735c68d8a656b46d09b1885d3b8740ae upstream.

In eager fpu mode, having deactivated FPU without immediately
reloading some other context is illegal.  Therefore, to recover from
FNSAVE, we can't just deactivate the state -- we need to reload it
if we're not actively context switching.

We had this wrong in fpu__save() and fpu__copy().  Fix both.
__kernel_fpu_begin() was fine -- add a comment.

This fixes a warning triggerable with nofxsr eagerfpu=on.

Signed-off-by: Andy Lutomirski <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Dave Hansen <[email protected]>
Cc: Fenghua Yu <[email protected]>
Cc: H. Peter Anvin <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Oleg Nesterov <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Quentin Casasnovas <[email protected]>
Cc: Rik van Riel <[email protected]>
Cc: Sai Praneeth Prakhya <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: yu-cheng yu <[email protected]>
Link: 
http://lkml.kernel.org/r/60662444e13c76f06e23c15c5dcdba31b4ac3d67.1453675014.git.l...@kernel.org
Signed-off-by: Ingo Molnar <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
 arch/x86/kernel/fpu/core.c |   18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -114,6 +114,10 @@ void __kernel_fpu_begin(void)
        kernel_fpu_disable();
 
        if (fpu->fpregs_active) {
+               /*
+                * Ignore return value -- we don't care if reg state
+                * is clobbered.
+                */
                copy_fpregs_to_fpstate(fpu);
        } else {
                this_cpu_write(fpu_fpregs_owner_ctx, NULL);
@@ -189,8 +193,12 @@ void fpu__save(struct fpu *fpu)
 
        preempt_disable();
        if (fpu->fpregs_active) {
-               if (!copy_fpregs_to_fpstate(fpu))
-                       fpregs_deactivate(fpu);
+               if (!copy_fpregs_to_fpstate(fpu)) {
+                       if (use_eager_fpu())
+                               copy_kernel_to_fpregs(&fpu->state);
+                       else
+                               fpregs_deactivate(fpu);
+               }
        }
        preempt_enable();
 }
@@ -259,7 +267,11 @@ static void fpu_copy(struct fpu *dst_fpu
        preempt_disable();
        if (!copy_fpregs_to_fpstate(dst_fpu)) {
                memcpy(&src_fpu->state, &dst_fpu->state, xstate_size);
-               fpregs_deactivate(src_fpu);
+
+               if (use_eager_fpu())
+                       copy_kernel_to_fpregs(&src_fpu->state);
+               else
+                       fpregs_deactivate(src_fpu);
        }
        preempt_enable();
 }


Reply via email to