diff options
| -rw-r--r-- | arch/x86/include/asm/i387.h | 31 | ||||
| -rw-r--r-- | arch/x86/kernel/traps.c | 5 |
2 files changed, 16 insertions, 20 deletions
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index 71c9e5183982..63d185087d91 100644 --- a/arch/x86/include/asm/i387.h +++ b/arch/x86/include/asm/i387.h | |||
| @@ -67,7 +67,7 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx) | |||
| 67 | ".previous\n" | 67 | ".previous\n" |
| 68 | _ASM_EXTABLE(1b, 3b) | 68 | _ASM_EXTABLE(1b, 3b) |
| 69 | : [err] "=r" (err) | 69 | : [err] "=r" (err) |
| 70 | #if 0 /* See comment in __save_init_fpu() below. */ | 70 | #if 0 /* See comment in fxsave() below. */ |
| 71 | : [fx] "r" (fx), "m" (*fx), "0" (0)); | 71 | : [fx] "r" (fx), "m" (*fx), "0" (0)); |
| 72 | #else | 72 | #else |
| 73 | : [fx] "cdaSDb" (fx), "m" (*fx), "0" (0)); | 73 | : [fx] "cdaSDb" (fx), "m" (*fx), "0" (0)); |
| @@ -75,14 +75,6 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx) | |||
| 75 | return err; | 75 | return err; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | static inline int restore_fpu_checking(struct task_struct *tsk) | ||
| 79 | { | ||
| 80 | if (task_thread_info(tsk)->status & TS_XSAVE) | ||
| 81 | return xrstor_checking(&tsk->thread.xstate->xsave); | ||
| 82 | else | ||
| 83 | return fxrstor_checking(&tsk->thread.xstate->fxsave); | ||
| 84 | } | ||
| 85 | |||
| 86 | /* AMD CPUs don't save/restore FDP/FIP/FOP unless an exception | 78 | /* AMD CPUs don't save/restore FDP/FIP/FOP unless an exception |
| 87 | is pending. Clear the x87 state here by setting it to fixed | 79 | is pending. Clear the x87 state here by setting it to fixed |
| 88 | values. The kernel data segment can be sometimes 0 and sometimes | 80 | values. The kernel data segment can be sometimes 0 and sometimes |
| @@ -120,7 +112,7 @@ static inline int fxsave_user(struct i387_fxsave_struct __user *fx) | |||
| 120 | ".previous\n" | 112 | ".previous\n" |
| 121 | _ASM_EXTABLE(1b, 3b) | 113 | _ASM_EXTABLE(1b, 3b) |
| 122 | : [err] "=r" (err), "=m" (*fx) | 114 | : [err] "=r" (err), "=m" (*fx) |
| 123 | #if 0 /* See comment in __fxsave_clear() below. */ | 115 | #if 0 /* See comment in fxsave() below. */ |
| 124 | : [fx] "r" (fx), "0" (0)); | 116 | : [fx] "r" (fx), "0" (0)); |
| 125 | #else | 117 | #else |
| 126 | : [fx] "cdaSDb" (fx), "0" (0)); | 118 | : [fx] "cdaSDb" (fx), "0" (0)); |
| @@ -185,12 +177,9 @@ static inline void tolerant_fwait(void) | |||
| 185 | asm volatile("fnclex ; fwait"); | 177 | asm volatile("fnclex ; fwait"); |
| 186 | } | 178 | } |
| 187 | 179 | ||
| 188 | static inline void restore_fpu(struct task_struct *tsk) | 180 | /* perform fxrstor iff the processor has extended states, otherwise frstor */ |
| 181 | static inline int fxrstor_checking(struct i387_fxsave_struct *fx) | ||
| 189 | { | 182 | { |
| 190 | if (task_thread_info(tsk)->status & TS_XSAVE) { | ||
| 191 | xrstor_checking(&tsk->thread.xstate->xsave); | ||
| 192 | return; | ||
| 193 | } | ||
| 194 | /* | 183 | /* |
| 195 | * The "nop" is needed to make the instructions the same | 184 | * The "nop" is needed to make the instructions the same |
| 196 | * length. | 185 | * length. |
| @@ -199,7 +188,9 @@ static inline void restore_fpu(struct task_struct *tsk) | |||
| 199 | "nop ; frstor %1", | 188 | "nop ; frstor %1", |
| 200 | "fxrstor %1", | 189 | "fxrstor %1", |
| 201 | X86_FEATURE_FXSR, | 190 | X86_FEATURE_FXSR, |
| 202 | "m" (tsk->thread.xstate->fxsave)); | 191 | "m" (*fx)); |
| 192 | |||
| 193 | return 0; | ||
| 203 | } | 194 | } |
| 204 | 195 | ||
| 205 | /* We need a safe address that is cheap to find and that is already | 196 | /* We need a safe address that is cheap to find and that is already |
| @@ -262,6 +253,14 @@ end: | |||
| 262 | 253 | ||
| 263 | #endif /* CONFIG_X86_64 */ | 254 | #endif /* CONFIG_X86_64 */ |
| 264 | 255 | ||
| 256 | static inline int restore_fpu_checking(struct task_struct *tsk) | ||
| 257 | { | ||
| 258 | if (task_thread_info(tsk)->status & TS_XSAVE) | ||
| 259 | return xrstor_checking(&tsk->thread.xstate->xsave); | ||
| 260 | else | ||
| 261 | return fxrstor_checking(&tsk->thread.xstate->fxsave); | ||
| 262 | } | ||
| 263 | |||
| 265 | /* | 264 | /* |
| 266 | * Signal frame handlers... | 265 | * Signal frame handlers... |
| 267 | */ | 266 | */ |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 2310700faca5..ede024531f8f 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
| @@ -839,9 +839,6 @@ asmlinkage void math_state_restore(void) | |||
| 839 | } | 839 | } |
| 840 | 840 | ||
| 841 | clts(); /* Allow maths ops (or we recurse) */ | 841 | clts(); /* Allow maths ops (or we recurse) */ |
| 842 | #ifdef CONFIG_X86_32 | ||
| 843 | restore_fpu(tsk); | ||
| 844 | #else | ||
| 845 | /* | 842 | /* |
| 846 | * Paranoid restore. send a SIGSEGV if we fail to restore the state. | 843 | * Paranoid restore. send a SIGSEGV if we fail to restore the state. |
| 847 | */ | 844 | */ |
| @@ -850,7 +847,7 @@ asmlinkage void math_state_restore(void) | |||
| 850 | force_sig(SIGSEGV, tsk); | 847 | force_sig(SIGSEGV, tsk); |
| 851 | return; | 848 | return; |
| 852 | } | 849 | } |
| 853 | #endif | 850 | |
| 854 | thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ | 851 | thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ |
| 855 | tsk->fpu_counter++; | 852 | tsk->fpu_counter++; |
| 856 | } | 853 | } |
