diff options
Diffstat (limited to 'arch/x86/include/asm/i387.h')
-rw-r--r-- | arch/x86/include/asm/i387.h | 43 |
1 files changed, 21 insertions, 22 deletions
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index 71c9e5183982..175adf58dd4f 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 | */ |
@@ -305,18 +304,18 @@ static inline void kernel_fpu_end(void) | |||
305 | /* | 304 | /* |
306 | * Some instructions like VIA's padlock instructions generate a spurious | 305 | * Some instructions like VIA's padlock instructions generate a spurious |
307 | * DNA fault but don't modify SSE registers. And these instructions | 306 | * DNA fault but don't modify SSE registers. And these instructions |
308 | * get used from interrupt context aswell. To prevent these kernel instructions | 307 | * get used from interrupt context as well. To prevent these kernel instructions |
309 | * in interrupt context interact wrongly with other user/kernel fpu usage, we | 308 | * in interrupt context interacting wrongly with other user/kernel fpu usage, we |
310 | * should use them only in the context of irq_ts_save/restore() | 309 | * should use them only in the context of irq_ts_save/restore() |
311 | */ | 310 | */ |
312 | static inline int irq_ts_save(void) | 311 | static inline int irq_ts_save(void) |
313 | { | 312 | { |
314 | /* | 313 | /* |
315 | * If we are in process context, we are ok to take a spurious DNA fault. | 314 | * If in process context and not atomic, we can take a spurious DNA fault. |
316 | * Otherwise, doing clts() in process context require pre-emption to | 315 | * Otherwise, doing clts() in process context requires disabling preemption |
317 | * be disabled or some heavy lifting like kernel_fpu_begin() | 316 | * or some heavy lifting like kernel_fpu_begin() |
318 | */ | 317 | */ |
319 | if (!in_interrupt()) | 318 | if (!in_atomic()) |
320 | return 0; | 319 | return 0; |
321 | 320 | ||
322 | if (read_cr0() & X86_CR0_TS) { | 321 | if (read_cr0() & X86_CR0_TS) { |