diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2021-06-23 14:02:15 +0200 |
---|---|---|
committer | Borislav Petkov <bp@suse.de> | 2021-06-23 19:26:37 +0200 |
commit | 1d9bffab116fadfe1594f5fea2b50ab280d81d30 (patch) | |
tree | daeba06043cc6513a4472d81786ad606cf65bfc9 /arch/x86 | |
parent | 727d01100e15b18c67f05fb697779ad2a6c99b63 (diff) | |
download | linux-1d9bffab116fadfe1594f5fea2b50ab280d81d30.tar.gz linux-1d9bffab116fadfe1594f5fea2b50ab280d81d30.tar.bz2 linux-1d9bffab116fadfe1594f5fea2b50ab280d81d30.zip |
x86/fpu: Move FXSAVE_LEAK quirk info __copy_kernel_to_fpregs()
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
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/fpu/internal.h | 25 | ||||
-rw-r--r-- | arch/x86/kernel/fpu/core.c | 27 |
2 files changed, 28 insertions, 24 deletions
diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h index f7688f6e86bc..63d979656437 100644 --- a/arch/x86/include/asm/fpu/internal.h +++ b/arch/x86/include/asm/fpu/internal.h @@ -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); } diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index 6babf1876389..afd0deee8cfd 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -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(); |