diff options
author | Maciej W. Rozycki <macro@linux-mips.org> | 2015-04-04 00:27:06 +0200 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2015-04-08 01:10:15 +0200 |
commit | ed2d72c1eb3643b7c109bdf387563d9b9a30c279 (patch) | |
tree | cd0cc0203cef78f94b60770889f0e996a60387c6 /arch | |
parent | MIPS: math-emu: Move long fixed-point support into an `ar' library (diff) | |
download | linux-ed2d72c1eb3643b7c109bdf387563d9b9a30c279.tar.xz linux-ed2d72c1eb3643b7c109bdf387563d9b9a30c279.zip |
MIPS: Respect the FCSR exception mask for `si_code'
Respect the FCSR exception mask when interpreting the IEEE 754 exception
condition to report with SIGFPE in `si_code', so as not to use one that
has been masked where a different one set in parallel caused the FPE
hardware exception to trigger. As per the IEEE Std 754 the Inexact
exception can happen together with Overflow or Underflow.
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/9703/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/kernel/traps.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 88f04f0d2d21..dbfa47cdc8c1 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -12,6 +12,7 @@ * Copyright (C) 2000, 2001, 2012 MIPS Technologies, Inc. All rights reserved. * Copyright (C) 2014, Imagination Technologies Ltd. */ +#include <linux/bitops.h> #include <linux/bug.h> #include <linux/compiler.h> #include <linux/context_tracking.h> @@ -817,7 +818,15 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) process_fpemu_return(sig, fault_addr); goto out; - } else if (fcr31 & FPU_CSR_INV_X) + } + + /* + * Inexact can happen together with Overflow or Underflow. + * Respect the mask to deliver the correct exception. + */ + fcr31 &= (fcr31 & FPU_CSR_ALL_E) << + (ffs(FPU_CSR_ALL_X) - ffs(FPU_CSR_ALL_E)); + if (fcr31 & FPU_CSR_INV_X) info.si_code = FPE_FLTINV; else if (fcr31 & FPU_CSR_DIV_X) info.si_code = FPE_FLTDIV; |