diff options
author | Siarhei Liakh <Siarhei.Liakh@concurrent-rt.com> | 2018-06-14 15:36:07 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2018-06-20 05:44:56 -0400 |
commit | 3ae6295ccb7cf6d344908209701badbbbb503e40 (patch) | |
tree | 8c78733ff8b5fc228c089deb4002e90b70e6f781 | |
parent | 1d9f3e20a56d33e55748552aeec597f58542f92d (diff) |
x86: Call fixup_exception() before notify_die() in math_error()
fpu__drop() has an explicit fwait which under some conditions can trigger a
fixable FPU exception while in kernel. Thus, we should attempt to fixup the
exception first, and only call notify_die() if the fixup failed just like
in do_general_protection(). The original call sequence incorrectly triggers
KDB entry on debug kernels under particular FPU-intensive workloads.
Andy noted, that this makes the whole conditional irq enable thing even
more inconsistent, but fixing that it outside the scope of this.
Signed-off-by: Siarhei Liakh <siarhei.liakh@concurrent-rt.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Andy Lutomirski <luto@kernel.org>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: "Borislav Petkov" <bpetkov@suse.de>
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/DM5PR11MB201156F1CAB2592B07C79A03B17D0@DM5PR11MB2011.namprd11.prod.outlook.com
-rw-r--r-- | arch/x86/kernel/traps.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 03f3d7695dac..162a31d80ad5 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -834,16 +834,18 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr) | |||
834 | char *str = (trapnr == X86_TRAP_MF) ? "fpu exception" : | 834 | char *str = (trapnr == X86_TRAP_MF) ? "fpu exception" : |
835 | "simd exception"; | 835 | "simd exception"; |
836 | 836 | ||
837 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, SIGFPE) == NOTIFY_STOP) | ||
838 | return; | ||
839 | cond_local_irq_enable(regs); | 837 | cond_local_irq_enable(regs); |
840 | 838 | ||
841 | if (!user_mode(regs)) { | 839 | if (!user_mode(regs)) { |
842 | if (!fixup_exception(regs, trapnr)) { | 840 | if (fixup_exception(regs, trapnr)) |
843 | task->thread.error_code = error_code; | 841 | return; |
844 | task->thread.trap_nr = trapnr; | 842 | |
843 | task->thread.error_code = error_code; | ||
844 | task->thread.trap_nr = trapnr; | ||
845 | |||
846 | if (notify_die(DIE_TRAP, str, regs, error_code, | ||
847 | trapnr, SIGFPE) != NOTIFY_STOP) | ||
845 | die(str, regs, error_code); | 848 | die(str, regs, error_code); |
846 | } | ||
847 | return; | 849 | return; |
848 | } | 850 | } |
849 | 851 | ||