diff options
author | Suresh Siddha <suresh.b.siddha@intel.com> | 2008-05-07 15:09:52 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2008-05-10 13:31:45 -0400 |
commit | fd3c3ed5d1e3ceb37635cbe6d220ab94aae0781d (patch) | |
tree | 67cc2a950e670e5362173efd88ea6ded708b7e6c /arch/x86 | |
parent | 0646153921892cc7a81320a6920beaca06b3e9f0 (diff) |
x86: fix fpu restore from sig return
If the task never used fpu, initialize the fpu before restoring the FP
state from the signal handler context. This will allocate the fpu
state, if the task never needed it before.
Reported-and-bisected-by: Eric Sesterhenn <snakebyte@gmx.de>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Tested-by: Eric Sesterhenn <snakebyte@gmx.de>
Cc: Frederik Deweerdt <deweerdt@free.fr>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kernel/i387.c | 12 |
1 files changed, 10 insertions, 2 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) | |||
450 | { | 450 | { |
451 | struct task_struct *tsk = current; | 451 | struct task_struct *tsk = current; |
452 | 452 | ||
453 | clear_fpu(tsk); | ||
454 | return __copy_from_user(&tsk->thread.xstate->fsave, buf, | 453 | return __copy_from_user(&tsk->thread.xstate->fsave, buf, |
455 | sizeof(struct i387_fsave_struct)); | 454 | sizeof(struct i387_fsave_struct)); |
456 | } | 455 | } |
@@ -461,7 +460,6 @@ static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf) | |||
461 | struct user_i387_ia32_struct env; | 460 | struct user_i387_ia32_struct env; |
462 | int err; | 461 | int err; |
463 | 462 | ||
464 | clear_fpu(tsk); | ||
465 | err = __copy_from_user(&tsk->thread.xstate->fxsave, &buf->_fxsr_env[0], | 463 | err = __copy_from_user(&tsk->thread.xstate->fxsave, &buf->_fxsr_env[0], |
466 | sizeof(struct i387_fxsave_struct)); | 464 | sizeof(struct i387_fxsave_struct)); |
467 | /* mxcsr reserved bits must be masked to zero for security reasons */ | 465 | /* mxcsr reserved bits must be masked to zero for security reasons */ |
@@ -478,6 +476,16 @@ int restore_i387_ia32(struct _fpstate_ia32 __user *buf) | |||
478 | int err; | 476 | int err; |
479 | 477 | ||
480 | if (HAVE_HWFP) { | 478 | if (HAVE_HWFP) { |
479 | struct task_struct *tsk = current; | ||
480 | |||
481 | clear_fpu(tsk); | ||
482 | |||
483 | if (!used_math()) { | ||
484 | err = init_fpu(tsk); | ||
485 | if (err) | ||
486 | return err; | ||
487 | } | ||
488 | |||
481 | if (cpu_has_fxsr) | 489 | if (cpu_has_fxsr) |
482 | err = restore_i387_fxsave(buf); | 490 | err = restore_i387_fxsave(buf); |
483 | else | 491 | else |