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 | |
| 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>
| -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 */ |
