summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/i387.c12
-rw-r--r--include/asm-x86/i387.h10
2 files changed, 19 insertions, 3 deletions
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index db6839b53195..e03cc952f233 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -450,7 +450,6 @@ static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf)
{
struct task_struct *tsk = current;
- clear_fpu(tsk);
return __copy_from_user(&tsk->thread.xstate->fsave, buf,
sizeof(struct i387_fsave_struct));
}
@@ -461,7 +460,6 @@ static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf)
struct user_i387_ia32_struct env;
int err;
- clear_fpu(tsk);
err = __copy_from_user(&tsk->thread.xstate->fxsave, &buf->_fxsr_env[0],
sizeof(struct i387_fxsave_struct));
/* mxcsr reserved bits must be masked to zero for security reasons */
@@ -478,6 +476,16 @@ int restore_i387_ia32(struct _fpstate_ia32 __user *buf)
int err;
if (HAVE_HWFP) {
+ struct task_struct *tsk = current;
+
+ clear_fpu(tsk);
+
+ if (!used_math()) {
+ err = init_fpu(tsk);
+ if (err)
+ return err;
+ }
+
if (cpu_has_fxsr)
err = restore_i387_fxsave(buf);
else
diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h
index da2adb45f6e3..6b722d315936 100644
--- a/include/asm-x86/i387.h
+++ b/include/asm-x86/i387.h
@@ -175,7 +175,15 @@ static inline int save_i387(struct _fpstate __user *buf)
*/
static inline int restore_i387(struct _fpstate __user *buf)
{
- set_used_math();
+ struct task_struct *tsk = current;
+ int err;
+
+ if (!used_math()) {
+ err = init_fpu(tsk);
+ if (err)
+ return err;
+ }
+
if (!(task_thread_info(current)->status & TS_USEDFPU)) {
clts();
task_thread_info(current)->status |= TS_USEDFPU;