From: Ingo Molnar <mingo@kernel.org>
To: linux-kernel@vger.kernel.org
Cc: Andy Lutomirski <luto@amacapital.net>,
Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
Fenghua Yu <fenghua.yu@intel.com>,
"H. Peter Anvin" <hpa@zytor.com>,
Linus Torvalds <torvalds@linux-foundation.org>,
Oleg Nesterov <oleg@redhat.com>,
Thomas Gleixner <tglx@linutronix.de>
Subject: [PATCH 188/208] x86/fpu: Factor out the exception error code handling code
Date: Tue, 5 May 2015 19:58:12 +0200 [thread overview]
Message-ID: <1430848712-28064-28-git-send-email-mingo@kernel.org> (raw)
In-Reply-To: <1430848712-28064-1-git-send-email-mingo@kernel.org>
Factor out the FPU error code handling code from traps.c and fpu/internal.h
and move them close to each other.
Also convert the helper functions to 'struct fpu *', which further simplifies
them.
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: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
arch/x86/include/asm/fpu/internal.h | 33 ++--------------------
arch/x86/kernel/fpu/core.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
arch/x86/kernel/traps.c | 67 ++++++++-----------------------------------
3 files changed, 102 insertions(+), 86 deletions(-)
diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h
index 7b62d9032623..dfdafea6e56f 100644
--- a/arch/x86/include/asm/fpu/internal.h
+++ b/arch/x86/include/asm/fpu/internal.h
@@ -30,7 +30,8 @@ extern void fpu__init_system(struct cpuinfo_x86 *c);
extern void fpu__activate_curr(struct fpu *fpu);
extern void fpstate_init(struct fpu *fpu);
-extern int dump_fpu(struct pt_regs *, struct user_i387_struct *);
+extern int dump_fpu(struct pt_regs *, struct user_i387_struct *);
+extern int fpu__exception_code(struct fpu *fpu, int trap_nr);
/*
* High level FPU state handling functions:
@@ -467,34 +468,4 @@ static inline void user_fpu_begin(void)
preempt_enable();
}
-/*
- * i387 state interaction
- */
-static inline unsigned short get_fpu_cwd(struct task_struct *tsk)
-{
- if (cpu_has_fxsr) {
- return tsk->thread.fpu.state.fxsave.cwd;
- } else {
- return (unsigned short)tsk->thread.fpu.state.fsave.cwd;
- }
-}
-
-static inline unsigned short get_fpu_swd(struct task_struct *tsk)
-{
- if (cpu_has_fxsr) {
- return tsk->thread.fpu.state.fxsave.swd;
- } else {
- return (unsigned short)tsk->thread.fpu.state.fsave.swd;
- }
-}
-
-static inline unsigned short get_fpu_mxcsr(struct task_struct *tsk)
-{
- if (cpu_has_xmm) {
- return tsk->thread.fpu.state.fxsave.mxcsr;
- } else {
- return MXCSR_DEFAULT;
- }
-}
-
#endif /* _ASM_X86_FPU_INTERNAL_H */
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index b34c1a72d838..38274909e193 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -8,6 +8,7 @@
#include <asm/fpu/internal.h>
#include <asm/fpu/regset.h>
#include <asm/fpu/signal.h>
+#include <asm/traps.h>
#include <linux/hardirq.h>
@@ -749,3 +750,90 @@ int dump_fpu(struct pt_regs *regs, struct user_i387_struct *ufpu)
EXPORT_SYMBOL(dump_fpu);
#endif /* CONFIG_X86_32 || CONFIG_IA32_EMULATION */
+
+/*
+ * x87 math exception handling:
+ */
+
+static inline unsigned short get_fpu_cwd(struct fpu *fpu)
+{
+ if (cpu_has_fxsr) {
+ return fpu->state.fxsave.cwd;
+ } else {
+ return (unsigned short)fpu->state.fsave.cwd;
+ }
+}
+
+static inline unsigned short get_fpu_swd(struct fpu *fpu)
+{
+ if (cpu_has_fxsr) {
+ return fpu->state.fxsave.swd;
+ } else {
+ return (unsigned short)fpu->state.fsave.swd;
+ }
+}
+
+static inline unsigned short get_fpu_mxcsr(struct fpu *fpu)
+{
+ if (cpu_has_xmm) {
+ return fpu->state.fxsave.mxcsr;
+ } else {
+ return MXCSR_DEFAULT;
+ }
+}
+
+int fpu__exception_code(struct fpu *fpu, int trap_nr)
+{
+ int err;
+
+ if (trap_nr == X86_TRAP_MF) {
+ unsigned short cwd, swd;
+ /*
+ * (~cwd & swd) will mask out exceptions that are not set to unmasked
+ * status. 0x3f is the exception bits in these regs, 0x200 is the
+ * C1 reg you need in case of a stack fault, 0x040 is the stack
+ * fault bit. We should only be taking one exception at a time,
+ * so if this combination doesn't produce any single exception,
+ * then we have a bad program that isn't synchronizing its FPU usage
+ * and it will suffer the consequences since we won't be able to
+ * fully reproduce the context of the exception
+ */
+ cwd = get_fpu_cwd(fpu);
+ swd = get_fpu_swd(fpu);
+
+ err = swd & ~cwd;
+ } else {
+ /*
+ * The SIMD FPU exceptions are handled a little differently, as there
+ * is only a single status/control register. Thus, to determine which
+ * unmasked exception was caught we must mask the exception mask bits
+ * at 0x1f80, and then use these to mask the exception bits at 0x3f.
+ */
+ unsigned short mxcsr = get_fpu_mxcsr(fpu);
+ err = ~(mxcsr >> 7) & mxcsr;
+ }
+
+ if (err & 0x001) { /* Invalid op */
+ /*
+ * swd & 0x240 == 0x040: Stack Underflow
+ * swd & 0x240 == 0x240: Stack Overflow
+ * User must clear the SF bit (0x40) if set
+ */
+ return FPE_FLTINV;
+ } else if (err & 0x004) { /* Divide by Zero */
+ return FPE_FLTDIV;
+ } else if (err & 0x008) { /* Overflow */
+ return FPE_FLTOVF;
+ } else if (err & 0x012) { /* Denormal, Underflow */
+ return FPE_FLTUND;
+ } else if (err & 0x020) { /* Precision */
+ return FPE_FLTRES;
+ }
+
+ /*
+ * If we're using IRQ 13, or supposedly even some trap
+ * X86_TRAP_MF implementations, it's possible
+ * we get a spurious trap, which is not an error.
+ */
+ return 0;
+}
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 48dfcd9ed351..cab397d0085f 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -708,8 +708,8 @@ NOKPROBE_SYMBOL(do_debug);
static void math_error(struct pt_regs *regs, int error_code, int trapnr)
{
struct task_struct *task = current;
+ struct fpu *fpu = &task->thread.fpu;
siginfo_t info;
- unsigned short err;
char *str = (trapnr == X86_TRAP_MF) ? "fpu exception" :
"simd exception";
@@ -717,8 +717,7 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr)
return;
conditional_sti(regs);
- if (!user_mode(regs))
- {
+ if (!user_mode(regs)) {
if (!fixup_exception(regs)) {
task->thread.error_code = error_code;
task->thread.trap_nr = trapnr;
@@ -730,62 +729,20 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr)
/*
* Save the info for the exception handler and clear the error.
*/
- fpu__save(&task->thread.fpu);
- task->thread.trap_nr = trapnr;
+ fpu__save(fpu);
+
+ task->thread.trap_nr = trapnr;
task->thread.error_code = error_code;
- info.si_signo = SIGFPE;
- info.si_errno = 0;
- info.si_addr = (void __user *)uprobe_get_trap_addr(regs);
- if (trapnr == X86_TRAP_MF) {
- unsigned short cwd, swd;
- /*
- * (~cwd & swd) will mask out exceptions that are not set to unmasked
- * status. 0x3f is the exception bits in these regs, 0x200 is the
- * C1 reg you need in case of a stack fault, 0x040 is the stack
- * fault bit. We should only be taking one exception at a time,
- * so if this combination doesn't produce any single exception,
- * then we have a bad program that isn't synchronizing its FPU usage
- * and it will suffer the consequences since we won't be able to
- * fully reproduce the context of the exception
- */
- cwd = get_fpu_cwd(task);
- swd = get_fpu_swd(task);
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_addr = (void __user *)uprobe_get_trap_addr(regs);
- err = swd & ~cwd;
- } else {
- /*
- * The SIMD FPU exceptions are handled a little differently, as there
- * is only a single status/control register. Thus, to determine which
- * unmasked exception was caught we must mask the exception mask bits
- * at 0x1f80, and then use these to mask the exception bits at 0x3f.
- */
- unsigned short mxcsr = get_fpu_mxcsr(task);
- err = ~(mxcsr >> 7) & mxcsr;
- }
+ info.si_code = fpu__exception_code(fpu, trapnr);
- if (err & 0x001) { /* Invalid op */
- /*
- * swd & 0x240 == 0x040: Stack Underflow
- * swd & 0x240 == 0x240: Stack Overflow
- * User must clear the SF bit (0x40) if set
- */
- info.si_code = FPE_FLTINV;
- } else if (err & 0x004) { /* Divide by Zero */
- info.si_code = FPE_FLTDIV;
- } else if (err & 0x008) { /* Overflow */
- info.si_code = FPE_FLTOVF;
- } else if (err & 0x012) { /* Denormal, Underflow */
- info.si_code = FPE_FLTUND;
- } else if (err & 0x020) { /* Precision */
- info.si_code = FPE_FLTRES;
- } else {
- /*
- * If we're using IRQ 13, or supposedly even some trap
- * X86_TRAP_MF implementations, it's possible
- * we get a spurious trap, which is not an error.
- */
+ /* Retry when we get spurious exceptions: */
+ if (!info.si_code)
return;
- }
+
force_sig_info(SIGFPE, &info, task);
}
--
2.1.0
next prev parent reply other threads:[~2015-05-05 18:06 UTC|newest]
Thread overview: 76+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-05-05 17:57 [PATCH 000/208] big x86 FPU code rewrite Ingo Molnar
2015-05-05 17:57 ` [PATCH 162/208] x86/fpu, crypto x86/cast6_avx: Simplify the cast6_init() xfeature checks Ingo Molnar
2015-05-05 17:57 ` [PATCH 163/208] x86/fpu, crypto x86/sha1_ssse3: Simplify the sha1_ssse3_mod_init() " Ingo Molnar
2015-05-05 17:57 ` [PATCH 164/208] x86/fpu, crypto x86/serpent_avx2: Simplify the init() " Ingo Molnar
2015-05-05 17:57 ` [PATCH 165/208] x86/fpu, crypto x86/sha1_mb: Remove FPU internal headers from sha1_mb.c Ingo Molnar
2015-05-05 17:57 ` [PATCH 166/208] x86/fpu: Move asm/xcr.h to asm/fpu/internal.h Ingo Molnar
2015-05-05 17:57 ` [PATCH 167/208] x86/fpu: Rename sanitize_i387_state() to fpstate_sanitize_xstate() Ingo Molnar
2015-05-05 17:57 ` [PATCH 168/208] x86/fpu: Simplify fpstate_sanitize_xstate() calls Ingo Molnar
2015-05-05 17:57 ` [PATCH 169/208] x86/fpu: Pass 'struct fpu' to fpstate_sanitize_xstate() Ingo Molnar
2015-05-05 17:57 ` [PATCH 170/208] x86/fpu: Rename save_xstate_sig() to copy_fpstate_to_sigframe() Ingo Molnar
2015-05-05 17:57 ` [PATCH 171/208] x86/fpu: Rename save_user_xstate() to copy_fpregs_to_sigframe() Ingo Molnar
2015-05-05 17:57 ` [PATCH 172/208] x86/fpu: Clarify ancient comments in fpu__restore() Ingo Molnar
2015-05-05 17:57 ` [PATCH 173/208] x86/fpu: Rename user_has_fpu() to fpregs_active() Ingo Molnar
2015-05-05 17:57 ` [PATCH 174/208] x86/fpu: Initialize fpregs in fpu__init_cpu_generic() Ingo Molnar
2015-05-05 17:57 ` [PATCH 175/208] x86/fpu: Clean up fpu__clear() state handling Ingo Molnar
2015-05-05 17:58 ` [PATCH 176/208] x86/alternatives, x86/fpu: Add 'alternatives_patched' debug flag and use it in xsave_state() Ingo Molnar
2015-05-05 22:47 ` Borislav Petkov
2015-05-06 2:57 ` Ingo Molnar
2015-05-05 17:58 ` [PATCH 177/208] x86/fpu: Synchronize the naming of drop_fpu() and fpu_reset_state() Ingo Molnar
2015-05-05 17:58 ` [PATCH 178/208] x86/fpu: Rename restore_fpu_checking() to copy_fpstate_to_fpregs() Ingo Molnar
2015-05-05 17:58 ` [PATCH 179/208] x86/fpu: Move all the fpu__*() high level methods closer to each other Ingo Molnar
2015-05-05 17:58 ` [PATCH 180/208] x86/fpu: Move fpu__clear() to 'struct fpu *' parameter passing Ingo Molnar
2015-05-05 17:58 ` [PATCH 181/208] x86/fpu: Rename restore_xstate_sig() to fpu__restore_sig() Ingo Molnar
2015-05-05 17:58 ` [PATCH 182/208] x86/fpu: Move the signal frame handling code closer to each other Ingo Molnar
2015-05-05 17:58 ` [PATCH 183/208] x86/fpu: Merge fpu__reset() and fpu__clear() Ingo Molnar
2015-05-05 17:58 ` [PATCH 184/208] x86/fpu: Move is_ia32*frame() helpers out of fpu/internal.h Ingo Molnar
2015-05-05 17:58 ` [PATCH 185/208] x86/fpu: Split out fpu/signal.h from fpu/internal.h for signal frame handling functions Ingo Molnar
2015-05-05 17:58 ` [PATCH 186/208] x86/fpu: Factor out fpu/regset.h from fpu/internal.h Ingo Molnar
2015-05-05 17:58 ` [PATCH 187/208] x86/fpu: Remove run-once init quirks Ingo Molnar
2015-05-05 17:58 ` Ingo Molnar [this message]
2015-05-05 17:58 ` [PATCH 189/208] x86/fpu: Harmonize the names of the fpstate_init() helper functions Ingo Molnar
2015-05-05 17:58 ` [PATCH 190/208] x86/fpu: Create 'union thread_xstate' helper for fpstate_init() Ingo Molnar
2015-05-05 17:58 ` [PATCH 191/208] x86/fpu: Generalize 'init_xstate_ctx' Ingo Molnar
2015-05-05 17:58 ` [PATCH 192/208] x86/fpu: Move restore_init_xstate() out of fpu/internal.h Ingo Molnar
2015-05-05 17:58 ` [PATCH 193/208] x86/fpu: Rename all the fpregs, xregs, fxregs and fregs handling functions Ingo Molnar
2015-05-12 21:54 ` Dave Hansen
2015-05-05 17:58 ` [PATCH 194/208] x86/fpu: Factor out fpu/signal.c Ingo Molnar
2015-05-05 17:58 ` [PATCH 195/208] x86/fpu: Factor out the FPU regset code into fpu/regset.c Ingo Molnar
2015-05-05 17:58 ` [PATCH 196/208] x86/fpu: Harmonize FPU register state types Ingo Molnar
2015-05-05 17:58 ` [PATCH 197/208] x86/fpu: Change fpu->fpregs_active from 'int' to 'char', add lazy switching comments Ingo Molnar
2015-05-05 17:58 ` [PATCH 198/208] x86/fpu: Document the various fpregs state formats Ingo Molnar
2015-05-05 19:52 ` Dave Hansen
2015-05-05 22:55 ` Yu, Fenghua
2015-05-06 4:20 ` Ingo Molnar
2015-05-05 17:58 ` [PATCH 199/208] x86/fpu: Move debugging check from kernel_fpu_begin() to __kernel_fpu_begin() Ingo Molnar
2015-05-05 17:58 ` [PATCH 200/208] x86/fpu/xstate: Don't assume the first zero xfeatures zero bit means the end Ingo Molnar
2015-05-05 20:10 ` Dave Hansen
2015-05-05 23:04 ` Yu, Fenghua
2015-05-06 4:13 ` Ingo Molnar
2015-05-05 17:58 ` [PATCH 201/208] x86/fpu: Clean up xstate feature reservation Ingo Molnar
2015-05-05 20:12 ` Dave Hansen
2015-05-06 4:54 ` Ingo Molnar
2015-05-05 17:58 ` [PATCH 202/208] x86/fpu/xstate: Clean up setup_xstate_comp() call Ingo Molnar
2015-05-05 17:58 ` [PATCH 203/208] x86/fpu/init: Propagate __init annotations Ingo Molnar
2015-05-05 17:58 ` [PATCH 204/208] x86/fpu: Pass 'struct fpu' to fpu__restore() Ingo Molnar
2015-05-05 17:58 ` [PATCH 205/208] x86/fpu: Fix the 'nofxsr' boot parameter to also clear X86_FEATURE_FXSR_OPT Ingo Molnar
2015-05-05 17:58 ` [PATCH 206/208] x86/fpu: Add CONFIG_X86_DEBUG_FPU=y FPU debugging code Ingo Molnar
2015-05-05 19:41 ` Borislav Petkov
2015-05-06 3:35 ` Ingo Molnar
2024-06-18 22:02 ` Mateusz Guzik
2025-02-25 13:43 ` Mateusz Guzik
2015-05-05 17:58 ` [PATCH 207/208] x86/fpu: Add FPU performance measurement subsystem Ingo Molnar
2015-05-05 19:15 ` Dave Hansen
2015-05-05 19:22 ` Borislav Petkov
2015-05-06 4:11 ` Ingo Molnar
2015-05-06 0:52 ` Andy Lutomirski
2015-05-06 4:52 ` Ingo Molnar
2015-05-06 15:53 ` Borislav Petkov
2015-05-07 2:52 ` Andy Lutomirski
2015-05-05 17:58 ` [PATCH 208/208] x86/fpu: Reorganize fpu/internal.h Ingo Molnar
2015-05-12 17:46 ` [PATCH 000/208] big x86 FPU code rewrite Dave Hansen
2015-05-29 18:53 ` Ingo Molnar
2015-05-19 21:41 ` Ingo Molnar
2015-05-27 1:22 ` Bobby Powers
2015-05-27 10:42 ` [PATCH] x86/fpu: Fix FPU register read access to the current task Ingo Molnar
2015-05-29 13:12 ` Bobby Powers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1430848712-28064-28-git-send-email-mingo@kernel.org \
--to=mingo@kernel.org \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=fenghua.yu@intel.com \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@amacapital.net \
--cc=oleg@redhat.com \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome