aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-x86/i387.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-x86/i387.h')
-rw-r--r--include/asm-x86/i387.h60
1 files changed, 31 insertions, 29 deletions
diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h
index f377b76b2f34..da2adb45f6e3 100644
--- a/include/asm-x86/i387.h
+++ b/include/asm-x86/i387.h
@@ -21,8 +21,9 @@
21 21
22extern void fpu_init(void); 22extern void fpu_init(void);
23extern void mxcsr_feature_mask_init(void); 23extern void mxcsr_feature_mask_init(void);
24extern void init_fpu(struct task_struct *child); 24extern int init_fpu(struct task_struct *child);
25extern asmlinkage void math_state_restore(void); 25extern asmlinkage void math_state_restore(void);
26extern void init_thread_xstate(void);
26 27
27extern user_regset_active_fn fpregs_active, xfpregs_active; 28extern user_regset_active_fn fpregs_active, xfpregs_active;
28extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get; 29extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get;
@@ -41,7 +42,7 @@ static inline void tolerant_fwait(void)
41{ 42{
42 asm volatile("1: fwait\n" 43 asm volatile("1: fwait\n"
43 "2:\n" 44 "2:\n"
44 _ASM_EXTABLE(1b,2b)); 45 _ASM_EXTABLE(1b, 2b));
45} 46}
46 47
47static inline int restore_fpu_checking(struct i387_fxsave_struct *fx) 48static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
@@ -54,7 +55,7 @@ static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
54 "3: movl $-1,%[err]\n" 55 "3: movl $-1,%[err]\n"
55 " jmp 2b\n" 56 " jmp 2b\n"
56 ".previous\n" 57 ".previous\n"
57 _ASM_EXTABLE(1b,3b) 58 _ASM_EXTABLE(1b, 3b)
58 : [err] "=r" (err) 59 : [err] "=r" (err)
59#if 0 /* See comment in __save_init_fpu() below. */ 60#if 0 /* See comment in __save_init_fpu() below. */
60 : [fx] "r" (fx), "m" (*fx), "0" (0)); 61 : [fx] "r" (fx), "m" (*fx), "0" (0));
@@ -76,11 +77,11 @@ static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
76static inline void clear_fpu_state(struct i387_fxsave_struct *fx) 77static inline void clear_fpu_state(struct i387_fxsave_struct *fx)
77{ 78{
78 if (unlikely(fx->swd & X87_FSW_ES)) 79 if (unlikely(fx->swd & X87_FSW_ES))
79 asm volatile("fnclex"); 80 asm volatile("fnclex");
80 alternative_input(ASM_NOP8 ASM_NOP2, 81 alternative_input(ASM_NOP8 ASM_NOP2,
81 " emms\n" /* clear stack tags */ 82 " emms\n" /* clear stack tags */
82 " fildl %%gs:0", /* load to clear state */ 83 " fildl %%gs:0", /* load to clear state */
83 X86_FEATURE_FXSAVE_LEAK); 84 X86_FEATURE_FXSAVE_LEAK);
84} 85}
85 86
86static inline int save_i387_checking(struct i387_fxsave_struct __user *fx) 87static inline int save_i387_checking(struct i387_fxsave_struct __user *fx)
@@ -93,14 +94,15 @@ static inline int save_i387_checking(struct i387_fxsave_struct __user *fx)
93 "3: movl $-1,%[err]\n" 94 "3: movl $-1,%[err]\n"
94 " jmp 2b\n" 95 " jmp 2b\n"
95 ".previous\n" 96 ".previous\n"
96 _ASM_EXTABLE(1b,3b) 97 _ASM_EXTABLE(1b, 3b)
97 : [err] "=r" (err), "=m" (*fx) 98 : [err] "=r" (err), "=m" (*fx)
98#if 0 /* See comment in __fxsave_clear() below. */ 99#if 0 /* See comment in __fxsave_clear() below. */
99 : [fx] "r" (fx), "0" (0)); 100 : [fx] "r" (fx), "0" (0));
100#else 101#else
101 : [fx] "cdaSDb" (fx), "0" (0)); 102 : [fx] "cdaSDb" (fx), "0" (0));
102#endif 103#endif
103 if (unlikely(err) && __clear_user(fx, sizeof(struct i387_fxsave_struct))) 104 if (unlikely(err) &&
105 __clear_user(fx, sizeof(struct i387_fxsave_struct)))
104 err = -EFAULT; 106 err = -EFAULT;
105 /* No need to clear here because the caller clears USED_MATH */ 107 /* No need to clear here because the caller clears USED_MATH */
106 return err; 108 return err;
@@ -116,24 +118,22 @@ static inline void __save_init_fpu(struct task_struct *tsk)
116 /* Using "fxsaveq %0" would be the ideal choice, but is only supported 118 /* Using "fxsaveq %0" would be the ideal choice, but is only supported
117 starting with gas 2.16. */ 119 starting with gas 2.16. */
118 __asm__ __volatile__("fxsaveq %0" 120 __asm__ __volatile__("fxsaveq %0"
119 : "=m" (tsk->thread.i387.fxsave)); 121 : "=m" (tsk->thread.xstate->fxsave));
120#elif 0 122#elif 0
121 /* Using, as a workaround, the properly prefixed form below isn't 123 /* Using, as a workaround, the properly prefixed form below isn't
122 accepted by any binutils version so far released, complaining that 124 accepted by any binutils version so far released, complaining that
123 the same type of prefix is used twice if an extended register is 125 the same type of prefix is used twice if an extended register is
124 needed for addressing (fix submitted to mainline 2005-11-21). */ 126 needed for addressing (fix submitted to mainline 2005-11-21). */
125 __asm__ __volatile__("rex64/fxsave %0" 127 __asm__ __volatile__("rex64/fxsave %0"
126 : "=m" (tsk->thread.i387.fxsave)); 128 : "=m" (tsk->thread.xstate->fxsave));
127#else 129#else
128 /* This, however, we can work around by forcing the compiler to select 130 /* This, however, we can work around by forcing the compiler to select
129 an addressing mode that doesn't require extended registers. */ 131 an addressing mode that doesn't require extended registers. */
130 __asm__ __volatile__("rex64/fxsave %P2(%1)" 132 __asm__ __volatile__("rex64/fxsave (%1)"
131 : "=m" (tsk->thread.i387.fxsave) 133 : "=m" (tsk->thread.xstate->fxsave)
132 : "cdaSDb" (tsk), 134 : "cdaSDb" (&tsk->thread.xstate->fxsave));
133 "i" (offsetof(__typeof__(*tsk),
134 thread.i387.fxsave)));
135#endif 135#endif
136 clear_fpu_state(&tsk->thread.i387.fxsave); 136 clear_fpu_state(&tsk->thread.xstate->fxsave);
137 task_thread_info(tsk)->status &= ~TS_USEDFPU; 137 task_thread_info(tsk)->status &= ~TS_USEDFPU;
138} 138}
139 139
@@ -147,7 +147,7 @@ static inline int save_i387(struct _fpstate __user *buf)
147 int err = 0; 147 int err = 0;
148 148
149 BUILD_BUG_ON(sizeof(struct user_i387_struct) != 149 BUILD_BUG_ON(sizeof(struct user_i387_struct) !=
150 sizeof(tsk->thread.i387.fxsave)); 150 sizeof(tsk->thread.xstate->fxsave));
151 151
152 if ((unsigned long)buf % 16) 152 if ((unsigned long)buf % 16)
153 printk("save_i387: bad fpstate %p\n", buf); 153 printk("save_i387: bad fpstate %p\n", buf);
@@ -156,12 +156,14 @@ static inline int save_i387(struct _fpstate __user *buf)
156 return 0; 156 return 0;
157 clear_used_math(); /* trigger finit */ 157 clear_used_math(); /* trigger finit */
158 if (task_thread_info(tsk)->status & TS_USEDFPU) { 158 if (task_thread_info(tsk)->status & TS_USEDFPU) {
159 err = save_i387_checking((struct i387_fxsave_struct __user *)buf); 159 err = save_i387_checking((struct i387_fxsave_struct __user *)
160 if (err) return err; 160 buf);
161 if (err)
162 return err;
161 task_thread_info(tsk)->status &= ~TS_USEDFPU; 163 task_thread_info(tsk)->status &= ~TS_USEDFPU;
162 stts(); 164 stts();
163 } else { 165 } else {
164 if (__copy_to_user(buf, &tsk->thread.i387.fxsave, 166 if (__copy_to_user(buf, &tsk->thread.xstate->fxsave,
165 sizeof(struct i387_fxsave_struct))) 167 sizeof(struct i387_fxsave_struct)))
166 return -1; 168 return -1;
167 } 169 }
@@ -198,7 +200,7 @@ static inline void restore_fpu(struct task_struct *tsk)
198 "nop ; frstor %1", 200 "nop ; frstor %1",
199 "fxrstor %1", 201 "fxrstor %1",
200 X86_FEATURE_FXSR, 202 X86_FEATURE_FXSR,
201 "m" ((tsk)->thread.i387.fxsave)); 203 "m" (tsk->thread.xstate->fxsave));
202} 204}
203 205
204/* We need a safe address that is cheap to find and that is already 206/* We need a safe address that is cheap to find and that is already
@@ -222,8 +224,8 @@ static inline void __save_init_fpu(struct task_struct *tsk)
222 "fxsave %[fx]\n" 224 "fxsave %[fx]\n"
223 "bt $7,%[fsw] ; jnc 1f ; fnclex\n1:", 225 "bt $7,%[fsw] ; jnc 1f ; fnclex\n1:",
224 X86_FEATURE_FXSR, 226 X86_FEATURE_FXSR,
225 [fx] "m" (tsk->thread.i387.fxsave), 227 [fx] "m" (tsk->thread.xstate->fxsave),
226 [fsw] "m" (tsk->thread.i387.fxsave.swd) : "memory"); 228 [fsw] "m" (tsk->thread.xstate->fxsave.swd) : "memory");
227 /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception 229 /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
228 is pending. Clear the x87 state here by setting it to fixed 230 is pending. Clear the x87 state here by setting it to fixed
229 values. safe_address is a random variable that should be in L1 */ 231 values. safe_address is a random variable that should be in L1 */
@@ -324,25 +326,25 @@ static inline void clear_fpu(struct task_struct *tsk)
324static inline unsigned short get_fpu_cwd(struct task_struct *tsk) 326static inline unsigned short get_fpu_cwd(struct task_struct *tsk)
325{ 327{
326 if (cpu_has_fxsr) { 328 if (cpu_has_fxsr) {
327 return tsk->thread.i387.fxsave.cwd; 329 return tsk->thread.xstate->fxsave.cwd;
328 } else { 330 } else {
329 return (unsigned short)tsk->thread.i387.fsave.cwd; 331 return (unsigned short)tsk->thread.xstate->fsave.cwd;
330 } 332 }
331} 333}
332 334
333static inline unsigned short get_fpu_swd(struct task_struct *tsk) 335static inline unsigned short get_fpu_swd(struct task_struct *tsk)
334{ 336{
335 if (cpu_has_fxsr) { 337 if (cpu_has_fxsr) {
336 return tsk->thread.i387.fxsave.swd; 338 return tsk->thread.xstate->fxsave.swd;
337 } else { 339 } else {
338 return (unsigned short)tsk->thread.i387.fsave.swd; 340 return (unsigned short)tsk->thread.xstate->fsave.swd;
339 } 341 }
340} 342}
341 343
342static inline unsigned short get_fpu_mxcsr(struct task_struct *tsk) 344static inline unsigned short get_fpu_mxcsr(struct task_struct *tsk)
343{ 345{
344 if (cpu_has_xmm) { 346 if (cpu_has_xmm) {
345 return tsk->thread.i387.fxsave.mxcsr; 347 return tsk->thread.xstate->fxsave.mxcsr;
346 } else { 348 } else {
347 return MXCSR_DEFAULT; 349 return MXCSR_DEFAULT;
348 } 350 }