Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2018-09-27 10:56:52 +0200
committerJiri Kosina <jkosina@suse.cz>2018-09-27 10:56:52 +0200
commite8d5f8ec481648a3f8bbab6f00a104dafc33c739 (patch)
treeca3ae9494cd87bffefd1fb111da788fd7b650ccb
parente163233dc47d2fdbd057ad02b4e126c18711723c (diff)
parentf1ab2601c4aa4707b0b2b6a19028b5ede91dd94d (diff)
Merge remote-tracking branch 'origin/users/nstange/SLE11-SP4/for-next' into SLE11-SP4rpm-3.0.101-108.74
Pull 32bit FPU handling fix from Nicolai Stange suse-commit: 453958e2dcf58ab4c2863c001089f656e089ddf6
-rw-r--r--arch/x86/kernel/i387.c38
1 files changed, 35 insertions, 3 deletions
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index 9f11ce8c5947..15cedba0043b 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -594,7 +594,8 @@ int save_i387_xstate_ia32(void __user *buf)
* This will cause a "finit" to be triggered by the next
* attempted FPU operation by the 'current' process.
*/
- drop_init_fpu(tsk);
+ if (!use_eager_fpu())
+ clear_used_math();
if (!HAVE_HWFP) {
return fpregs_soft_get(current, NULL,
@@ -611,6 +612,8 @@ int save_i387_xstate_ia32(void __user *buf)
__save_init_fpu(tsk);
if (!use_eager_fpu())
__thread_fpu_end(tsk);
+ else
+ drop_init_fpu(tsk);
} else
tsk->fpu_counter = 0;
@@ -698,8 +701,19 @@ int restore_i387_xstate_ia32(void __user *buf)
struct task_struct *tsk = current;
struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf;
- if (HAVE_HWFP)
- clear_fpu(tsk);
+ if (HAVE_HWFP) {
+ if (!use_eager_fpu()) {
+ clear_fpu(tsk);
+ } else {
+ /*
+ * Unlike clear_fpu(), keep FPU ownership, but
+ * clear any pending exceptions from user space.
+ */
+ asm volatile("1: fwait\n"
+ "2:\n"
+ _ASM_EXTABLE(1b, 2b));
+ }
+ }
if (!buf) {
drop_init_fpu(tsk);
@@ -723,6 +737,24 @@ int restore_i387_xstate_ia32(void __user *buf)
i387_fxsave_struct));
else
err = restore_i387_fsave(fp);
+
+ if (use_eager_fpu()) {
+ /*
+ * Should be the case already, but better be
+ * on the safe side: the init_fpu() from above
+ * should never get called in eager mode, but
+ * who knows?
+ */
+ if (WARN_ON_ONCE(!__thread_has_fpu(tsk)))
+ __thread_set_has_fpu(tsk);
+
+ /* copied from math_state_restore */
+ if(unlikely(restore_fpu_checking(tsk))) {
+ drop_init_fpu(tsk);
+ return -EACCES;
+ }
+ }
+
} else {
err = fpregs_soft_set(current, NULL,
0, sizeof(struct user_i387_ia32_struct),