summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeonid Yegoshin <Leonid.Yegoshin@imgtec.com>2013-12-12 20:57:19 +0400
committerRalf Baechle <ralf@linux-mips.org>2014-03-27 02:09:17 +0400
commitca750649e08ce37bd3873e1026dc245811adf7a8 (patch)
tree20da25ff255abacaf73da7c9009063fd5a316027
parentc2d85bc1041c38bebf982a0d16242c3189ca1152 (diff)
downloadlinux-ca750649e08ce37bd3873e1026dc245811adf7a8.tar.xz
MIPS: kernel: signal: Prevent save/restore FPU context in user memory
EVA does not have FPU specific instructions for reading or writing FPU registers from userspace memory. Signed-off-by: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
-rw-r--r--arch/mips/kernel/signal.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index fd61700409bc..33133d3df3e5 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -6,6 +6,7 @@
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1994 - 2000 Ralf Baechle
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2014, Imagination Technologies Ltd.
*/
#include <linux/cache.h>
#include <linux/context_tracking.h>
@@ -140,6 +141,7 @@ static int protected_save_fp_context(struct sigcontext __user *sc,
{
int err;
bool save_msa = cpu_has_msa && (used_math & USEDMATH_MSA);
+#ifndef CONFIG_EVA
while (1) {
lock_fpu_owner();
if (is_fpu_owner()) {
@@ -162,6 +164,17 @@ static int protected_save_fp_context(struct sigcontext __user *sc,
if (err)
break; /* really bad sigcontext */
}
+#else
+ /*
+ * EVA does not have FPU EVA instructions so saving fpu context directly
+ * does not work.
+ */
+ disable_msa();
+ lose_fpu(1);
+ err = save_fp_context(sc); /* this might fail */
+ if (save_msa && !err)
+ err = copy_msa_to_sigcontext(sc);
+#endif
return err;
}
@@ -170,6 +183,7 @@ static int protected_restore_fp_context(struct sigcontext __user *sc,
{
int err, tmp __maybe_unused;
bool restore_msa = cpu_has_msa && (used_math & USEDMATH_MSA);
+#ifndef CONFIG_EVA
while (1) {
lock_fpu_owner();
if (is_fpu_owner()) {
@@ -197,6 +211,17 @@ static int protected_restore_fp_context(struct sigcontext __user *sc,
if (err)
break; /* really bad sigcontext */
}
+#else
+ /*
+ * EVA does not have FPU EVA instructions so restoring fpu context
+ * directly does not work.
+ */
+ enable_msa();
+ lose_fpu(0);
+ err = restore_fp_context(sc); /* this might fail */
+ if (restore_msa && !err)
+ err = copy_msa_from_sigcontext(sc);
+#endif
return err;
}
@@ -685,6 +710,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
}
#ifdef CONFIG_SMP
+#ifndef CONFIG_EVA
static int smp_save_fp_context(struct sigcontext __user *sc)
{
return raw_cpu_has_fpu
@@ -698,10 +724,12 @@ static int smp_restore_fp_context(struct sigcontext __user *sc)
? _restore_fp_context(sc)
: copy_fp_from_sigcontext(sc);
}
+#endif /* CONFIG_EVA */
#endif
static int signal_setup(void)
{
+#ifndef CONFIG_EVA
#ifdef CONFIG_SMP
/* For now just do the cpu_has_fpu check when the functions are invoked */
save_fp_context = smp_save_fp_context;
@@ -714,6 +742,10 @@ static int signal_setup(void)
save_fp_context = copy_fp_from_sigcontext;
restore_fp_context = copy_fp_to_sigcontext;
}
+#endif /* CONFIG_SMP */
+#else
+ save_fp_context = copy_fp_from_sigcontext;;
+ restore_fp_context = copy_fp_to_sigcontext;
#endif
return 0;