x86/fpu: Move FXSAVE_LEAK quirk info __copy_kernel_to_fpregs()
authorThomas Gleixner <tglx@linutronix.de>
Wed, 23 Jun 2021 12:02:15 +0000 (14:02 +0200)
committerBorislav Petkov <bp@suse.de>
Wed, 23 Jun 2021 17:26:37 +0000 (19:26 +0200)
copy_kernel_to_fpregs() restores all xfeatures but it is also the place
where the AMD FXSAVE_LEAK bug is handled.

That prevents fpregs_restore_userregs() to limit the restored features,
which is required to untangle PKRU and XSTATE handling and also for the
upcoming supervisor state management.

Move the FXSAVE_LEAK quirk into __copy_kernel_to_fpregs() and deinline that
function which has become rather fat.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20210623121456.114271278@linutronix.de
arch/x86/include/asm/fpu/internal.h
arch/x86/kernel/fpu/core.c

index f7688f6..63d9796 100644 (file)
@@ -379,33 +379,10 @@ static inline int os_xrstor_safe(struct xregs_state *xstate, u64 mask)
        return err;
 }
 
-static inline void __restore_fpregs_from_fpstate(union fpregs_state *fpstate, u64 mask)
-{
-       if (use_xsave()) {
-               os_xrstor(&fpstate->xsave, mask);
-       } else {
-               if (use_fxsr())
-                       fxrstor(&fpstate->fxsave);
-               else
-                       frstor(&fpstate->fsave);
-       }
-}
+extern void __restore_fpregs_from_fpstate(union fpregs_state *fpstate, u64 mask);
 
 static inline void restore_fpregs_from_fpstate(union fpregs_state *fpstate)
 {
-       /*
-        * AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception is
-        * pending. Clear the x87 state here by setting it to fixed values.
-        * "m" is a random variable that should be in L1.
-        */
-       if (unlikely(static_cpu_has_bug(X86_BUG_FXSAVE_LEAK))) {
-               asm volatile(
-                       "fnclex\n\t"
-                       "emms\n\t"
-                       "fildl %P[addr]"        /* set F?P to defined value */
-                       : : [addr] "m" (fpstate));
-       }
-
        __restore_fpregs_from_fpstate(fpstate, -1);
 }
 
index 6babf18..afd0dee 100644 (file)
@@ -124,6 +124,33 @@ void save_fpregs_to_fpstate(struct fpu *fpu)
 }
 EXPORT_SYMBOL(save_fpregs_to_fpstate);
 
+void __restore_fpregs_from_fpstate(union fpregs_state *fpstate, u64 mask)
+{
+       /*
+        * AMD K7/K8 and later CPUs up to Zen don't save/restore
+        * FDP/FIP/FOP unless an exception is pending. Clear the x87 state
+        * here by setting it to fixed values.  "m" is a random variable
+        * that should be in L1.
+        */
+       if (unlikely(static_cpu_has_bug(X86_BUG_FXSAVE_LEAK))) {
+               asm volatile(
+                       "fnclex\n\t"
+                       "emms\n\t"
+                       "fildl %P[addr]"        /* set F?P to defined value */
+                       : : [addr] "m" (fpstate));
+       }
+
+       if (use_xsave()) {
+               os_xrstor(&fpstate->xsave, mask);
+       } else {
+               if (use_fxsr())
+                       fxrstor(&fpstate->fxsave);
+               else
+                       frstor(&fpstate->fsave);
+       }
+}
+EXPORT_SYMBOL_GPL(__restore_fpregs_from_fpstate);
+
 void kernel_fpu_begin_mask(unsigned int kfpu_mask)
 {
        preempt_disable();