| From 2224d616528194b02424c91c2ee254b3d29942c3 Mon Sep 17 00:00:00 2001 |
| From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
| Date: Tue, 16 Oct 2018 22:25:25 +0200 |
| Subject: x86/fpu: Fix i486 + no387 boot crash by only saving FPU registers on context switch if there is an FPU |
| |
| From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
| |
| commit 2224d616528194b02424c91c2ee254b3d29942c3 upstream. |
| |
| Booting an i486 with "no387 nofxsr" ends with with the following crash: |
| |
| math_emulate: 0060:c101987d |
| Kernel panic - not syncing: Math emulation needed in kernel |
| |
| on the first context switch in user land. |
| |
| The reason is that copy_fpregs_to_fpstate() tries FNSAVE which does not work |
| as the FPU is turned off. |
| |
| This bug was introduced in: |
| |
| f1c8cd0176078 ("x86/fpu: Change fpu->fpregs_active users to fpu->fpstate_active") |
| |
| Add a check for X86_FEATURE_FPU before trying to save FPU registers (we |
| have such a check in switch_fpu_finish() already). |
| |
| Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
| Reviewed-by: Andy Lutomirski <luto@kernel.org> |
| Cc: Borislav Petkov <bp@alien8.de> |
| Cc: Dave Hansen <dave.hansen@linux.intel.com> |
| Cc: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Cc: stable@vger.kernel.org |
| Fixes: f1c8cd0176078 ("x86/fpu: Change fpu->fpregs_active users to fpu->fpstate_active") |
| Link: http://lkml.kernel.org/r/20181016202525.29437-4-bigeasy@linutronix.de |
| Signed-off-by: Ingo Molnar <mingo@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/x86/include/asm/fpu/internal.h | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/arch/x86/include/asm/fpu/internal.h |
| +++ b/arch/x86/include/asm/fpu/internal.h |
| @@ -528,7 +528,7 @@ static inline void fpregs_activate(struc |
| static inline void |
| switch_fpu_prepare(struct fpu *old_fpu, int cpu) |
| { |
| - if (old_fpu->initialized) { |
| + if (static_cpu_has(X86_FEATURE_FPU) && old_fpu->initialized) { |
| if (!copy_fpregs_to_fpstate(old_fpu)) |
| old_fpu->last_cpu = -1; |
| else |