summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@imgtec.com>2015-01-30 13:09:37 +0100
committerRalf Baechle <ralf@linux-mips.org>2015-03-27 19:42:47 +0100
commit84ab45b33858a87632e1f5e207e302bf48eaf52e (patch)
treecb2816ad87e3917b4d400660d8cc3025be373f1d
parentMIPS: prevent FP context set via ptrace being discarded (diff)
downloadlinux-84ab45b33858a87632e1f5e207e302bf48eaf52e.tar.xz
linux-84ab45b33858a87632e1f5e207e302bf48eaf52e.zip
MIPS: disable FPU if the mode is unsupported
The expected semantics of __enable_fpu are for the FPU to be enabled in the given mode if possible, otherwise for the FPU to be left disabled and SIGFPE returned. The FPU was incorrectly being left enabled in cases where the desired value for FR was unavailable. Without ensuring the FPU is disabled in this case, it would be possible for userland to go on to execute further FP instructions natively in the incorrect mode, rather than those instructions being trapped & emulated as they need to be. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/9167/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/include/asm/fpu.h19
1 files changed, 12 insertions, 7 deletions
diff --git a/arch/mips/include/asm/fpu.h b/arch/mips/include/asm/fpu.h
index 9f26b079cc6a..b104ad9d655f 100644
--- a/arch/mips/include/asm/fpu.h
+++ b/arch/mips/include/asm/fpu.h
@@ -48,6 +48,12 @@ enum fpu_mode {
#define FPU_FR_MASK 0x1
};
+#define __disable_fpu() \
+do { \
+ clear_c0_status(ST0_CU1); \
+ disable_fpu_hazard(); \
+} while (0)
+
static inline int __enable_fpu(enum fpu_mode mode)
{
int fr;
@@ -86,7 +92,12 @@ fr_common:
enable_fpu_hazard();
/* check FR has the desired value */
- return (!!(read_c0_status() & ST0_FR) == !!fr) ? 0 : SIGFPE;
+ if (!!(read_c0_status() & ST0_FR) == !!fr)
+ return 0;
+
+ /* unsupported FR value */
+ __disable_fpu();
+ return SIGFPE;
default:
BUG();
@@ -95,12 +106,6 @@ fr_common:
return SIGFPE;
}
-#define __disable_fpu() \
-do { \
- clear_c0_status(ST0_CU1); \
- disable_fpu_hazard(); \
-} while (0)
-
#define clear_fpu_owner() clear_thread_flag(TIF_USEDFPU)
static inline int __is_fpu_owner(void)