Commit ca750649 authored by Leonid Yegoshin's avatar Leonid Yegoshin Committed by Ralf Baechle

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: default avatarLeonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: default avatarMarkos Chandras <markos.chandras@imgtec.com>
parent c2d85bc1
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1994 - 2000 Ralf Baechle * Copyright (C) 1994 - 2000 Ralf Baechle
* Copyright (C) 1999, 2000 Silicon Graphics, Inc. * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
* Copyright (C) 2014, Imagination Technologies Ltd.
*/ */
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/context_tracking.h> #include <linux/context_tracking.h>
...@@ -140,6 +141,7 @@ static int protected_save_fp_context(struct sigcontext __user *sc, ...@@ -140,6 +141,7 @@ static int protected_save_fp_context(struct sigcontext __user *sc,
{ {
int err; int err;
bool save_msa = cpu_has_msa && (used_math & USEDMATH_MSA); bool save_msa = cpu_has_msa && (used_math & USEDMATH_MSA);
#ifndef CONFIG_EVA
while (1) { while (1) {
lock_fpu_owner(); lock_fpu_owner();
if (is_fpu_owner()) { if (is_fpu_owner()) {
...@@ -162,6 +164,17 @@ static int protected_save_fp_context(struct sigcontext __user *sc, ...@@ -162,6 +164,17 @@ static int protected_save_fp_context(struct sigcontext __user *sc,
if (err) if (err)
break; /* really bad sigcontext */ 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; return err;
} }
...@@ -170,6 +183,7 @@ static int protected_restore_fp_context(struct sigcontext __user *sc, ...@@ -170,6 +183,7 @@ static int protected_restore_fp_context(struct sigcontext __user *sc,
{ {
int err, tmp __maybe_unused; int err, tmp __maybe_unused;
bool restore_msa = cpu_has_msa && (used_math & USEDMATH_MSA); bool restore_msa = cpu_has_msa && (used_math & USEDMATH_MSA);
#ifndef CONFIG_EVA
while (1) { while (1) {
lock_fpu_owner(); lock_fpu_owner();
if (is_fpu_owner()) { if (is_fpu_owner()) {
...@@ -197,6 +211,17 @@ static int protected_restore_fp_context(struct sigcontext __user *sc, ...@@ -197,6 +211,17 @@ static int protected_restore_fp_context(struct sigcontext __user *sc,
if (err) if (err)
break; /* really bad sigcontext */ 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; return err;
} }
...@@ -685,6 +710,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, ...@@ -685,6 +710,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#ifndef CONFIG_EVA
static int smp_save_fp_context(struct sigcontext __user *sc) static int smp_save_fp_context(struct sigcontext __user *sc)
{ {
return raw_cpu_has_fpu return raw_cpu_has_fpu
...@@ -698,10 +724,12 @@ static int smp_restore_fp_context(struct sigcontext __user *sc) ...@@ -698,10 +724,12 @@ static int smp_restore_fp_context(struct sigcontext __user *sc)
? _restore_fp_context(sc) ? _restore_fp_context(sc)
: copy_fp_from_sigcontext(sc); : copy_fp_from_sigcontext(sc);
} }
#endif /* CONFIG_EVA */
#endif #endif
static int signal_setup(void) static int signal_setup(void)
{ {
#ifndef CONFIG_EVA
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* For now just do the cpu_has_fpu check when the functions are invoked */ /* For now just do the cpu_has_fpu check when the functions are invoked */
save_fp_context = smp_save_fp_context; save_fp_context = smp_save_fp_context;
...@@ -714,6 +742,10 @@ static int signal_setup(void) ...@@ -714,6 +742,10 @@ static int signal_setup(void)
save_fp_context = copy_fp_from_sigcontext; save_fp_context = copy_fp_from_sigcontext;
restore_fp_context = copy_fp_to_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 #endif
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment