diff options
author | Brian Gerst <brgerst@gmail.com> | 2010-09-03 21:17:18 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2010-09-09 17:17:31 -0400 |
commit | 58a992b9cbaf449aeebd3575c3695a9eb5d95b5e (patch) | |
tree | e4a1a020fd8db9fda6b71fcdd723098d3c82cf20 /arch/x86/include/asm/i387.h | |
parent | eec73f813ab0954253e5e2168119c4555f83f07d (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.h | 47 |
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 | ||
76 | static __always_inline __pure bool use_fxsr(void) | ||
77 | { | ||
78 | return static_cpu_has(X86_FEATURE_FXSR); | ||
79 | } | ||
80 | |||
76 | extern void __sanitize_i387_state(struct task_struct *); | 81 | extern void __sanitize_i387_state(struct task_struct *); |
77 | 82 | ||
78 | static inline void sanitize_i387_state(struct task_struct *tsk) | 83 | static 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 | ||
219 | static 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) | |||
226 | static inline void fpu_save_init(struct fpu *fpu) | 237 | static 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"); | ||
258 | clear_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)); |
268 | end: | ||
269 | ; | ||
270 | } | 267 | } |
271 | 268 | ||
272 | #endif /* CONFIG_X86_64 */ | 269 | #endif /* CONFIG_X86_64 */ |