Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/fpu: Fix math emulation in eager fpu mode

Systems without an FPU are generally old and therefore use lazy FPU
switching. Unsurprisingly, math emulation in eager FPU mode is a
bit buggy. Fix it.

There were two bugs involving kernel code trying to use the FPU
registers in eager mode even if they didn't exist and one BUG_ON()
that was incorrect.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Quentin Casasnovas <quentin.casasnovas@oracle.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: yu-cheng yu <yu-cheng.yu@intel.com>
Link: http://lkml.kernel.org/r/b4b8d112436bd6fab866e1b4011131507e8d7fbe.1453675014.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by

Andy Lutomirski and committed by
Ingo Molnar
4ecd16ec 765bdb40

+3 -3
+2 -1
arch/x86/include/asm/fpu/internal.h
··· 589 589 * If the task has used the math, pre-load the FPU on xsave processors 590 590 * or if the past 5 consecutive context-switches used math. 591 591 */ 592 - fpu.preload = new_fpu->fpstate_active && 592 + fpu.preload = static_cpu_has(X86_FEATURE_FPU) && 593 + new_fpu->fpstate_active && 593 594 (use_eager_fpu() || new_fpu->counter > 5); 594 595 595 596 if (old_fpu->fpregs_active) {
+1 -1
arch/x86/kernel/fpu/core.c
··· 423 423 { 424 424 WARN_ON_FPU(fpu != &current->thread.fpu); /* Almost certainly an anomaly */ 425 425 426 - if (!use_eager_fpu()) { 426 + if (!use_eager_fpu() || !static_cpu_has(X86_FEATURE_FPU)) { 427 427 /* FPU state will be reallocated lazily at the first use. */ 428 428 fpu__drop(fpu); 429 429 } else {
-1
arch/x86/kernel/traps.c
··· 750 750 do_device_not_available(struct pt_regs *regs, long error_code) 751 751 { 752 752 RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU"); 753 - BUG_ON(use_eager_fpu()); 754 753 755 754 #ifdef CONFIG_MATH_EMULATION 756 755 if (read_cr0() & X86_CR0_EM) {