]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
x86/fpu: Reset MXCSR to default in kernel_fpu_begin()
authorPetteri Aimonen <jpa@git.mail.kapsi.fi>
Tue, 16 Jun 2020 09:12:57 +0000 (11:12 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Jul 2020 07:32:51 +0000 (09:32 +0200)
[ Upstream commit 7ad816762f9bf89e940e618ea40c43138b479e10 ]

Previously, kernel floating point code would run with the MXCSR control
register value last set by userland code by the thread that was active
on the CPU core just before kernel call. This could affect calculation
results if rounding mode was changed, or a crash if a FPU/SIMD exception
was unmasked.

Restore MXCSR to the kernel's default value.

 [ bp: Carve out from a bigger patch by Petteri, add feature check, add
   FNINIT call too (amluto). ]

Signed-off-by: Petteri Aimonen <jpa@git.mail.kapsi.fi>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=207979
Link: https://lkml.kernel.org/r/20200624114646.28953-2-bp@alien8.de
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/x86/include/asm/fpu/internal.h
arch/x86/kernel/fpu/core.c

index 44c48e34d7994f885a12e67ae8d311f82fce7761..00eac7f1529b08db11d65830cfd14e38a495d75e 100644 (file)
@@ -619,6 +619,11 @@ static inline void switch_fpu_finish(struct fpu *new_fpu)
  * MXCSR and XCR definitions:
  */
 
+static inline void ldmxcsr(u32 mxcsr)
+{
+       asm volatile("ldmxcsr %0" :: "m" (mxcsr));
+}
+
 extern unsigned int mxcsr_feature_mask;
 
 #define XCR_XFEATURE_ENABLED_MASK      0x00000000
index 12c70840980e4b8aacf26541ff3814cbc4ebaf11..cd8839027f66d4b3e3c92aeb6f6f5e8f056acee1 100644 (file)
@@ -101,6 +101,12 @@ void kernel_fpu_begin(void)
                copy_fpregs_to_fpstate(&current->thread.fpu);
        }
        __cpu_invalidate_fpregs_state();
+
+       if (boot_cpu_has(X86_FEATURE_XMM))
+               ldmxcsr(MXCSR_DEFAULT);
+
+       if (boot_cpu_has(X86_FEATURE_FPU))
+               asm volatile ("fninit");
 }
 EXPORT_SYMBOL_GPL(kernel_fpu_begin);