[tip: x86/fpu] x86/fpu: Reset MXCSR to default in kernel_fpu_begin()

From: tip-bot2 for Petteri Aimonen
Date: Mon Jun 29 2020 - 16:53:53 EST


The following commit has been merged into the x86/fpu branch of tip:

Commit-ID: 7ad816762f9bf89e940e618ea40c43138b479e10
Gitweb: https://git.kernel.org/tip/7ad816762f9bf89e940e618ea40c43138b479e10
Author: Petteri Aimonen <jpa@xxxxxxxxxxxxxxxxx>
AuthorDate: Tue, 16 Jun 2020 11:12:57 +02:00
Committer: Borislav Petkov <bp@xxxxxxx>
CommitterDate: Mon, 29 Jun 2020 10:02:00 +02:00

x86/fpu: Reset MXCSR to default in kernel_fpu_begin()

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@xxxxxxxxxxxxxxxxx>
Signed-off-by: Borislav Petkov <bp@xxxxxxx>
Link: https://bugzilla.kernel.org/show_bug.cgi?id=207979
Link: https://lkml.kernel.org/r/20200624114646.28953-2-bp@xxxxxxxxx
---
arch/x86/include/asm/fpu/internal.h | 5 +++++
arch/x86/kernel/fpu/core.c | 6 ++++++
2 files changed, 11 insertions(+)

diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h
index 42159f4..845e748 100644
--- a/arch/x86/include/asm/fpu/internal.h
+++ b/arch/x86/include/asm/fpu/internal.h
@@ -623,6 +623,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
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index 06c8189..15247b9 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -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);