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/kernel/fpu/core.c | |
parent | 727d01100e15b18c67f05fb697779ad2a6c99b63 (diff) |
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/kernel/fpu/core.c')
-rw-r--r-- | arch/x86/kernel/fpu/core.c | 27 |
1 files changed, 27 insertions, 0 deletions
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(); |