]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
x86/fpu/math-emu: Fix math-emu boot crash
authorIngo Molnar <mingo@kernel.org>
Sat, 22 Aug 2015 07:52:06 +0000 (09:52 +0200)
committerIngo Molnar <mingo@kernel.org>
Sat, 22 Aug 2015 08:02:04 +0000 (10:02 +0200)
On a math-emu bootup the following crash occurs:

Initializing CPU#0
------------[ cut here ]------------
kernel BUG at arch/x86/kernel/traps.c:779!
invalid opcode: 0000 [#1] SMP
[...]
EIP is at do_device_not_available+0xe/0x70
[...]
Call Trace:
 [<c18238e6>] error_code+0x5a/0x60
 [<c1002bd0>] ? math_error+0x140/0x140
 [<c100bbd9>] ? fpu__init_cpu+0x59/0xa0
 [<c1012322>] cpu_init+0x202/0x330
 [<c104509f>] ? __native_set_fixmap+0x1f/0x30
 [<c1b56ab0>] trap_init+0x305/0x346
 [<c1b548af>] start_kernel+0x1a5/0x35d
 [<c1b542b4>] i386_start_kernel+0x82/0x86

The reason is that in the following commit:

  b1276c48e91b ("x86/fpu: Initialize fpregs in fpu__init_cpu_generic()")

I failed to consider math-emu's limitation that it cannot execute the
FNINIT instruction in kernel mode.

The long term fix might be to allow math-emu to execute (certain) kernel
mode FPU instructions, but for now apply the safe (albeit somewhat ugly)
fix: initialize the emulation state explicitly without trapping out to
the FPU emulator.

Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.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: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/kernel/fpu/init.c

index 1e173f6285c73b76b2e6ab41daed7681406c5d15..d14e9ac3235a1ac73174ffb95b2990d5163d2933 100644 (file)
@@ -40,7 +40,12 @@ static void fpu__init_cpu_generic(void)
        write_cr0(cr0);
 
        /* Flush out any pending x87 state: */
-       asm volatile ("fninit");
+#ifdef CONFIG_MATH_EMULATION
+       if (!cpu_has_fpu)
+               fpstate_init_soft(&current->thread.fpu.state.soft);
+       else
+#endif
+               asm volatile ("fninit");
 }
 
 /*