aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/include/asm/i387.h
diff options
context:
space:
mode:
authorBrian Gerst <brgerst@gmail.com>2010-09-03 21:17:18 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2010-09-09 17:17:31 -0400
commit58a992b9cbaf449aeebd3575c3695a9eb5d95b5e (patch)
treee4a1a020fd8db9fda6b71fcdd723098d3c82cf20 /arch/x86/include/asm/i387.h
parenteec73f813ab0954253e5e2168119c4555f83f07d (diff)
x86-32, fpu: Rewrite fpu_save_init()
Rewrite fpu_save_init() to prepare for merging with 64-bit. Signed-off-by: Brian Gerst <brgerst@gmail.com> Acked-by: Pekka Enberg <penberg@kernel.org> Cc: Suresh Siddha <suresh.b.siddha@intel.com> LKML-Reference: <1283563039-3466-12-git-send-email-brgerst@gmail.com> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86/include/asm/i387.h')
-rw-r--r--arch/x86/include/asm/i387.h47
1 files changed, 22 insertions, 25 deletions
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h
index 907967e4fa8d..b45abefb89f2 100644
--- a/arch/x86/include/asm/i387.h
+++ b/arch/x86/include/asm/i387.h
@@ -73,6 +73,11 @@ static __always_inline __pure bool use_xsave(void)
73 return static_cpu_has(X86_FEATURE_XSAVE); 73 return static_cpu_has(X86_FEATURE_XSAVE);
74} 74}
75 75
76static __always_inline __pure bool use_fxsr(void)
77{
78 return static_cpu_has(X86_FEATURE_FXSR);
79}
80
76extern void __sanitize_i387_state(struct task_struct *); 81extern void __sanitize_i387_state(struct task_struct *);
77 82
78static inline void sanitize_i387_state(struct task_struct *tsk) 83static inline void sanitize_i387_state(struct task_struct *tsk)
@@ -211,6 +216,12 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
211 return 0; 216 return 0;
212} 217}
213 218
219static inline void fpu_fxsave(struct fpu *fpu)
220{
221 asm volatile("fxsave %[fx]"
222 : [fx] "=m" (fpu->state->fxsave));
223}
224
214/* We need a safe address that is cheap to find and that is already 225/* We need a safe address that is cheap to find and that is already
215 in L1 during context switch. The best choices are unfortunately 226 in L1 during context switch. The best choices are unfortunately
216 different for UP and SMP */ 227 different for UP and SMP */
@@ -226,36 +237,24 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
226static inline void fpu_save_init(struct fpu *fpu) 237static inline void fpu_save_init(struct fpu *fpu)
227{ 238{
228 if (use_xsave()) { 239 if (use_xsave()) {
229 struct xsave_struct *xstate = &fpu->state->xsave;
230 struct i387_fxsave_struct *fx = &fpu->state->fxsave;
231
232 fpu_xsave(fpu); 240 fpu_xsave(fpu);
233 241
234 /* 242 /*
235 * xsave header may indicate the init state of the FP. 243 * xsave header may indicate the init state of the FP.
236 */ 244 */
237 if (!(xstate->xsave_hdr.xstate_bv & XSTATE_FP)) 245 if (!(fpu->state->xsave.xsave_hdr.xstate_bv & XSTATE_FP))
238 goto end; 246 return;
239 247 } else if (use_fxsr()) {
240 if (unlikely(fx->swd & X87_FSW_ES)) 248 fpu_fxsave(fpu);
241 asm volatile("fnclex"); 249 } else {
242 250 asm volatile("fsave %[fx]; fwait"
243 /* 251 : [fx] "=m" (fpu->state->fsave));
244 * we can do a simple return here or be paranoid :) 252 return;
245 */
246 goto clear_state;
247 } 253 }
248 254
249 /* Use more nops than strictly needed in case the compiler 255 if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES))
250 varies code */ 256 asm volatile("fnclex");
251 alternative_input( 257
252 "fnsave %[fx] ;fwait;" GENERIC_NOP8 GENERIC_NOP4,
253 "fxsave %[fx]\n"
254 "bt $7,%[fsw] ; jnc 1f ; fnclex\n1:",
255 X86_FEATURE_FXSR,
256 [fx] "m" (fpu->state->fxsave),
257 [fsw] "m" (fpu->state->fxsave.swd) : "memory");
258clear_state:
259 /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception 258 /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
260 is pending. Clear the x87 state here by setting it to fixed 259 is pending. Clear the x87 state here by setting it to fixed
261 values. safe_address is a random variable that should be in L1 */ 260 values. safe_address is a random variable that should be in L1 */
@@ -265,8 +264,6 @@ clear_state:
265 "fildl %[addr]", /* set F?P to defined value */ 264 "fildl %[addr]", /* set F?P to defined value */
266 X86_FEATURE_FXSAVE_LEAK, 265 X86_FEATURE_FXSAVE_LEAK,
267 [addr] "m" (safe_address)); 266 [addr] "m" (safe_address));
268end:
269 ;
270} 267}
271 268
272#endif /* CONFIG_X86_64 */ 269#endif /* CONFIG_X86_64 */