aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2010-05-06 04:45:46 -0400
committerH. Peter Anvin <hpa@zytor.com>2010-05-10 13:48:55 -0400
commit86603283326c9e95e5ad4e9fdddeec93cac5d9ad (patch)
tree1a26a37434e920f9519b547814a1a9af35022de8
parentc9ad488289144ae5ef53b012e15895ef1f5e4bb6 (diff)
x86: Introduce 'struct fpu' and related API
Currently all fpu state access is through tsk->thread.xstate. Since we wish to generalize fpu access to non-task contexts, wrap the state in a new 'struct fpu' and convert existing access to use an fpu API. Signal frame handlers are not converted to the API since they will remain task context only things. Signed-off-by: Avi Kivity <avi@redhat.com> Acked-by: Suresh Siddha <suresh.b.siddha@intel.com> LKML-Reference: <1273135546-29690-3-git-send-email-avi@redhat.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--arch/x86/include/asm/i387.h115
-rw-r--r--arch/x86/include/asm/processor.h6
-rw-r--r--arch/x86/include/asm/xsave.h7
-rw-r--r--arch/x86/kernel/i387.c102
-rw-r--r--arch/x86/kernel/process.c21
-rw-r--r--arch/x86/kernel/process_32.c2
-rw-r--r--arch/x86/kernel/process_64.c2
-rw-r--r--arch/x86/kernel/xsave.c2
-rw-r--r--arch/x86/math-emu/fpu_aux.c6
9 files changed, 160 insertions, 103 deletions
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h
index a301a6825c3a..1a8cca33b736 100644
--- a/arch/x86/include/asm/i387.h
+++ b/arch/x86/include/asm/i387.h
@@ -16,6 +16,7 @@
16#include <linux/kernel_stat.h> 16#include <linux/kernel_stat.h>
17#include <linux/regset.h> 17#include <linux/regset.h>
18#include <linux/hardirq.h> 18#include <linux/hardirq.h>
19#include <linux/slab.h>
19#include <asm/asm.h> 20#include <asm/asm.h>
20#include <asm/processor.h> 21#include <asm/processor.h>
21#include <asm/sigcontext.h> 22#include <asm/sigcontext.h>
@@ -103,10 +104,10 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
103 values. The kernel data segment can be sometimes 0 and sometimes 104 values. The kernel data segment can be sometimes 0 and sometimes
104 new user value. Both should be ok. 105 new user value. Both should be ok.
105 Use the PDA as safe address because it should be already in L1. */ 106 Use the PDA as safe address because it should be already in L1. */
106static inline void clear_fpu_state(struct task_struct *tsk) 107static inline void fpu_clear(struct fpu *fpu)
107{ 108{
108 struct xsave_struct *xstate = &tsk->thread.xstate->xsave; 109 struct xsave_struct *xstate = &fpu->state->xsave;
109 struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave; 110 struct i387_fxsave_struct *fx = &fpu->state->fxsave;
110 111
111 /* 112 /*
112 * xsave header may indicate the init state of the FP. 113 * xsave header may indicate the init state of the FP.
@@ -123,6 +124,11 @@ static inline void clear_fpu_state(struct task_struct *tsk)
123 X86_FEATURE_FXSAVE_LEAK); 124 X86_FEATURE_FXSAVE_LEAK);
124} 125}
125 126
127static inline void clear_fpu_state(struct task_struct *tsk)
128{
129 fpu_clear(&tsk->thread.fpu);
130}
131
126static inline int fxsave_user(struct i387_fxsave_struct __user *fx) 132static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
127{ 133{
128 int err; 134 int err;
@@ -147,7 +153,7 @@ static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
147 return err; 153 return err;
148} 154}
149 155
150static inline void fxsave(struct task_struct *tsk) 156static inline void fpu_fxsave(struct fpu *fpu)
151{ 157{
152 /* Using "rex64; fxsave %0" is broken because, if the memory operand 158 /* Using "rex64; fxsave %0" is broken because, if the memory operand
153 uses any extended registers for addressing, a second REX prefix 159 uses any extended registers for addressing, a second REX prefix
@@ -157,42 +163,45 @@ static inline void fxsave(struct task_struct *tsk)
157 /* Using "fxsaveq %0" would be the ideal choice, but is only supported 163 /* Using "fxsaveq %0" would be the ideal choice, but is only supported
158 starting with gas 2.16. */ 164 starting with gas 2.16. */
159 __asm__ __volatile__("fxsaveq %0" 165 __asm__ __volatile__("fxsaveq %0"
160 : "=m" (tsk->thread.xstate->fxsave)); 166 : "=m" (fpu->state->fxsave));
161#elif 0 167#elif 0
162 /* Using, as a workaround, the properly prefixed form below isn't 168 /* Using, as a workaround, the properly prefixed form below isn't
163 accepted by any binutils version so far released, complaining that 169 accepted by any binutils version so far released, complaining that
164 the same type of prefix is used twice if an extended register is 170 the same type of prefix is used twice if an extended register is
165 needed for addressing (fix submitted to mainline 2005-11-21). */ 171 needed for addressing (fix submitted to mainline 2005-11-21). */
166 __asm__ __volatile__("rex64/fxsave %0" 172 __asm__ __volatile__("rex64/fxsave %0"
167 : "=m" (tsk->thread.xstate->fxsave)); 173 : "=m" (fpu->state->fxsave));
168#else 174#else
169 /* This, however, we can work around by forcing the compiler to select 175 /* This, however, we can work around by forcing the compiler to select
170 an addressing mode that doesn't require extended registers. */ 176 an addressing mode that doesn't require extended registers. */
171 __asm__ __volatile__("rex64/fxsave (%1)" 177 __asm__ __volatile__("rex64/fxsave (%1)"
172 : "=m" (tsk->thread.xstate->fxsave) 178 : "=m" (fpu->state->fxsave)
173 : "cdaSDb" (&tsk->thread.xstate->fxsave)); 179 : "cdaSDb" (&fpu->state->fxsave));
174#endif 180#endif
175} 181}
176 182
177static inline void __save_init_fpu(struct task_struct *tsk) 183static inline void fpu_save_init(struct fpu *fpu)
178{ 184{
179 if (use_xsave()) 185 if (use_xsave())
180 xsave(tsk); 186 fpu_xsave(fpu);
181 else 187 else
182 fxsave(tsk); 188 fpu_fxsave(fpu);
183 189
184 clear_fpu_state(tsk); 190 fpu_clear(fpu);
191}
192
193static inline void __save_init_fpu(struct task_struct *tsk)
194{
195 fpu_save_init(&tsk->thread.fpu);
185 task_thread_info(tsk)->status &= ~TS_USEDFPU; 196 task_thread_info(tsk)->status &= ~TS_USEDFPU;
186} 197}
187 198
188#else /* CONFIG_X86_32 */ 199#else /* CONFIG_X86_32 */
189 200
190#ifdef CONFIG_MATH_EMULATION 201#ifdef CONFIG_MATH_EMULATION
191extern void finit_task(struct task_struct *tsk); 202extern void finit_soft_fpu(struct i387_soft_struct *soft);
192#else 203#else
193static inline void finit_task(struct task_struct *tsk) 204static inline void finit_soft_fpu(struct i387_soft_struct *soft) {}
194{
195}
196#endif 205#endif
197 206
198static inline void tolerant_fwait(void) 207static inline void tolerant_fwait(void)
@@ -228,13 +237,13 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
228/* 237/*
229 * These must be called with preempt disabled 238 * These must be called with preempt disabled
230 */ 239 */
231static inline void __save_init_fpu(struct task_struct *tsk) 240static inline void fpu_save_init(struct fpu *fpu)
232{ 241{
233 if (use_xsave()) { 242 if (use_xsave()) {
234 struct xsave_struct *xstate = &tsk->thread.xstate->xsave; 243 struct xsave_struct *xstate = &fpu->state->xsave;
235 struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave; 244 struct i387_fxsave_struct *fx = &fpu->state->fxsave;
236 245
237 xsave(tsk); 246 fpu_xsave(fpu);
238 247
239 /* 248 /*
240 * xsave header may indicate the init state of the FP. 249 * xsave header may indicate the init state of the FP.
@@ -258,8 +267,8 @@ static inline void __save_init_fpu(struct task_struct *tsk)
258 "fxsave %[fx]\n" 267 "fxsave %[fx]\n"
259 "bt $7,%[fsw] ; jnc 1f ; fnclex\n1:", 268 "bt $7,%[fsw] ; jnc 1f ; fnclex\n1:",
260 X86_FEATURE_FXSR, 269 X86_FEATURE_FXSR,
261 [fx] "m" (tsk->thread.xstate->fxsave), 270 [fx] "m" (fpu->state->fxsave),
262 [fsw] "m" (tsk->thread.xstate->fxsave.swd) : "memory"); 271 [fsw] "m" (fpu->state->fxsave.swd) : "memory");
263clear_state: 272clear_state:
264 /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception 273 /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
265 is pending. Clear the x87 state here by setting it to fixed 274 is pending. Clear the x87 state here by setting it to fixed
@@ -271,17 +280,34 @@ clear_state:
271 X86_FEATURE_FXSAVE_LEAK, 280 X86_FEATURE_FXSAVE_LEAK,
272 [addr] "m" (safe_address)); 281 [addr] "m" (safe_address));
273end: 282end:
283 ;
284}
285
286static inline void __save_init_fpu(struct task_struct *tsk)
287{
288 fpu_save_init(&tsk->thread.fpu);
274 task_thread_info(tsk)->status &= ~TS_USEDFPU; 289 task_thread_info(tsk)->status &= ~TS_USEDFPU;
275} 290}
276 291
292
277#endif /* CONFIG_X86_64 */ 293#endif /* CONFIG_X86_64 */
278 294
279static inline int restore_fpu_checking(struct task_struct *tsk) 295static inline int fpu_fxrstor_checking(struct fpu *fpu)
296{
297 return fxrstor_checking(&fpu->state->fxsave);
298}
299
300static inline int fpu_restore_checking(struct fpu *fpu)
280{ 301{
281 if (use_xsave()) 302 if (use_xsave())
282 return xrstor_checking(&tsk->thread.xstate->xsave); 303 return fpu_xrstor_checking(fpu);
283 else 304 else
284 return fxrstor_checking(&tsk->thread.xstate->fxsave); 305 return fpu_fxrstor_checking(fpu);
306}
307
308static inline int restore_fpu_checking(struct task_struct *tsk)
309{
310 return fpu_restore_checking(&tsk->thread.fpu);
285} 311}
286 312
287/* 313/*
@@ -409,30 +435,59 @@ static inline void clear_fpu(struct task_struct *tsk)
409static inline unsigned short get_fpu_cwd(struct task_struct *tsk) 435static inline unsigned short get_fpu_cwd(struct task_struct *tsk)
410{ 436{
411 if (cpu_has_fxsr) { 437 if (cpu_has_fxsr) {
412 return tsk->thread.xstate->fxsave.cwd; 438 return tsk->thread.fpu.state->fxsave.cwd;
413 } else { 439 } else {
414 return (unsigned short)tsk->thread.xstate->fsave.cwd; 440 return (unsigned short)tsk->thread.fpu.state->fsave.cwd;
415 } 441 }
416} 442}
417 443
418static inline unsigned short get_fpu_swd(struct task_struct *tsk) 444static inline unsigned short get_fpu_swd(struct task_struct *tsk)
419{ 445{
420 if (cpu_has_fxsr) { 446 if (cpu_has_fxsr) {
421 return tsk->thread.xstate->fxsave.swd; 447 return tsk->thread.fpu.state->fxsave.swd;
422 } else { 448 } else {
423 return (unsigned short)tsk->thread.xstate->fsave.swd; 449 return (unsigned short)tsk->thread.fpu.state->fsave.swd;
424 } 450 }
425} 451}
426 452
427static inline unsigned short get_fpu_mxcsr(struct task_struct *tsk) 453static inline unsigned short get_fpu_mxcsr(struct task_struct *tsk)
428{ 454{
429 if (cpu_has_xmm) { 455 if (cpu_has_xmm) {
430 return tsk->thread.xstate->fxsave.mxcsr; 456 return tsk->thread.fpu.state->fxsave.mxcsr;
431 } else { 457 } else {
432 return MXCSR_DEFAULT; 458 return MXCSR_DEFAULT;
433 } 459 }
434} 460}
435 461
462static bool fpu_allocated(struct fpu *fpu)
463{
464 return fpu->state != NULL;
465}
466
467static inline int fpu_alloc(struct fpu *fpu)
468{
469 if (fpu_allocated(fpu))
470 return 0;
471 fpu->state = kmem_cache_alloc(task_xstate_cachep, GFP_KERNEL);
472 if (!fpu->state)
473 return -ENOMEM;
474 WARN_ON((unsigned long)fpu->state & 15);
475 return 0;
476}
477
478static inline void fpu_free(struct fpu *fpu)
479{
480 if (fpu->state) {
481 kmem_cache_free(task_xstate_cachep, fpu->state);
482 fpu->state = NULL;
483 }
484}
485
486static inline void fpu_copy(struct fpu *dst, struct fpu *src)
487{
488 memcpy(dst->state, src->state, xstate_size);
489}
490
436#endif /* __ASSEMBLY__ */ 491#endif /* __ASSEMBLY__ */
437 492
438#define PSHUFB_XMM5_XMM0 .byte 0x66, 0x0f, 0x38, 0x00, 0xc5 493#define PSHUFB_XMM5_XMM0 .byte 0x66, 0x0f, 0x38, 0x00, 0xc5
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index b753ea59703a..b684f587647c 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -380,6 +380,10 @@ union thread_xstate {
380 struct xsave_struct xsave; 380 struct xsave_struct xsave;
381}; 381};
382 382
383struct fpu {
384 union thread_xstate *state;
385};
386
383#ifdef CONFIG_X86_64 387#ifdef CONFIG_X86_64
384DECLARE_PER_CPU(struct orig_ist, orig_ist); 388DECLARE_PER_CPU(struct orig_ist, orig_ist);
385 389
@@ -457,7 +461,7 @@ struct thread_struct {
457 unsigned long trap_no; 461 unsigned long trap_no;
458 unsigned long error_code; 462 unsigned long error_code;
459 /* floating point and extended processor state */ 463 /* floating point and extended processor state */
460 union thread_xstate *xstate; 464 struct fpu fpu;
461#ifdef CONFIG_X86_32 465#ifdef CONFIG_X86_32
462 /* Virtual 86 mode info */ 466 /* Virtual 86 mode info */
463 struct vm86_struct __user *vm86_info; 467 struct vm86_struct __user *vm86_info;
diff --git a/arch/x86/include/asm/xsave.h b/arch/x86/include/asm/xsave.h
index ddc04ccad03b..2c4390cae228 100644
--- a/arch/x86/include/asm/xsave.h
+++ b/arch/x86/include/asm/xsave.h
@@ -37,8 +37,9 @@ extern int check_for_xstate(struct i387_fxsave_struct __user *buf,
37 void __user *fpstate, 37 void __user *fpstate,
38 struct _fpx_sw_bytes *sw); 38 struct _fpx_sw_bytes *sw);
39 39
40static inline int xrstor_checking(struct xsave_struct *fx) 40static inline int fpu_xrstor_checking(struct fpu *fpu)
41{ 41{
42 struct xsave_struct *fx = &fpu->state->xsave;
42 int err; 43 int err;
43 44
44 asm volatile("1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n\t" 45 asm volatile("1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n\t"
@@ -110,12 +111,12 @@ static inline void xrstor_state(struct xsave_struct *fx, u64 mask)
110 : "memory"); 111 : "memory");
111} 112}
112 113
113static inline void xsave(struct task_struct *tsk) 114static inline void fpu_xsave(struct fpu *fpu)
114{ 115{
115 /* This, however, we can work around by forcing the compiler to select 116 /* This, however, we can work around by forcing the compiler to select
116 an addressing mode that doesn't require extended registers. */ 117 an addressing mode that doesn't require extended registers. */
117 __asm__ __volatile__(".byte " REX_PREFIX "0x0f,0xae,0x27" 118 __asm__ __volatile__(".byte " REX_PREFIX "0x0f,0xae,0x27"
118 : : "D" (&(tsk->thread.xstate->xsave)), 119 : : "D" (&(fpu->state->xsave)),
119 "a" (-1), "d"(-1) : "memory"); 120 "a" (-1), "d"(-1) : "memory");
120} 121}
121#endif 122#endif
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index 14ca1dc7a703..86cef6b32253 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -107,57 +107,57 @@ void __cpuinit fpu_init(void)
107} 107}
108#endif /* CONFIG_X86_64 */ 108#endif /* CONFIG_X86_64 */
109 109
110/* 110static void fpu_finit(struct fpu *fpu)
111 * The _current_ task is using the FPU for the first time
112 * so initialize it and set the mxcsr to its default
113 * value at reset if we support XMM instructions and then
114 * remeber the current task has used the FPU.
115 */
116int init_fpu(struct task_struct *tsk)
117{ 111{
118 if (tsk_used_math(tsk)) {
119 if (HAVE_HWFP && tsk == current)
120 unlazy_fpu(tsk);
121 return 0;
122 }
123
124 /*
125 * Memory allocation at the first usage of the FPU and other state.
126 */
127 if (!tsk->thread.xstate) {
128 tsk->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
129 GFP_KERNEL);
130 if (!tsk->thread.xstate)
131 return -ENOMEM;
132 }
133
134#ifdef CONFIG_X86_32 112#ifdef CONFIG_X86_32
135 if (!HAVE_HWFP) { 113 if (!HAVE_HWFP) {
136 memset(tsk->thread.xstate, 0, xstate_size); 114 finit_soft_fpu(&fpu->state->soft);
137 finit_task(tsk); 115 return;
138 set_stopped_child_used_math(tsk);
139 return 0;
140 } 116 }
141#endif 117#endif
142 118
143 if (cpu_has_fxsr) { 119 if (cpu_has_fxsr) {
144 struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave; 120 struct i387_fxsave_struct *fx = &fpu->state->fxsave;
145 121
146 memset(fx, 0, xstate_size); 122 memset(fx, 0, xstate_size);
147 fx->cwd = 0x37f; 123 fx->cwd = 0x37f;
148 if (cpu_has_xmm) 124 if (cpu_has_xmm)
149 fx->mxcsr = MXCSR_DEFAULT; 125 fx->mxcsr = MXCSR_DEFAULT;
150 } else { 126 } else {
151 struct i387_fsave_struct *fp = &tsk->thread.xstate->fsave; 127 struct i387_fsave_struct *fp = &fpu->state->fsave;
152 memset(fp, 0, xstate_size); 128 memset(fp, 0, xstate_size);
153 fp->cwd = 0xffff037fu; 129 fp->cwd = 0xffff037fu;
154 fp->swd = 0xffff0000u; 130 fp->swd = 0xffff0000u;
155 fp->twd = 0xffffffffu; 131 fp->twd = 0xffffffffu;
156 fp->fos = 0xffff0000u; 132 fp->fos = 0xffff0000u;
157 } 133 }
134}
135
136/*
137 * The _current_ task is using the FPU for the first time
138 * so initialize it and set the mxcsr to its default
139 * value at reset if we support XMM instructions and then
140 * remeber the current task has used the FPU.
141 */
142int init_fpu(struct task_struct *tsk)
143{
144 int ret;
145
146 if (tsk_used_math(tsk)) {
147 if (HAVE_HWFP && tsk == current)
148 unlazy_fpu(tsk);
149 return 0;
150 }
151
158 /* 152 /*
159 * Only the device not available exception or ptrace can call init_fpu. 153 * Memory allocation at the first usage of the FPU and other state.
160 */ 154 */
155 ret = fpu_alloc(&tsk->thread.fpu);
156 if (ret)
157 return ret;
158
159 fpu_finit(&tsk->thread.fpu);
160
161 set_stopped_child_used_math(tsk); 161 set_stopped_child_used_math(tsk);
162 return 0; 162 return 0;
163} 163}
@@ -191,7 +191,7 @@ int xfpregs_get(struct task_struct *target, const struct user_regset *regset,
191 return ret; 191 return ret;
192 192
193 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 193 return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
194 &target->thread.xstate->fxsave, 0, -1); 194 &target->thread.fpu.state->fxsave, 0, -1);
195} 195}
196 196
197int xfpregs_set(struct task_struct *target, const struct user_regset *regset, 197int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
@@ -208,19 +208,19 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset,
208 return ret; 208 return ret;
209 209
210 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 210 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
211 &target->thread.xstate->fxsave, 0, -1); 211 &target->thread.fpu.state->fxsave, 0, -1);
212 212
213 /* 213 /*
214 * mxcsr reserved bits must be masked to zero for security reasons. 214 * mxcsr reserved bits must be masked to zero for security reasons.
215 */ 215 */
216 target->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask; 216 target->thread.fpu.state->fxsave.mxcsr &= mxcsr_feature_mask;
217 217
218 /* 218 /*
219 * update the header bits in the xsave header, indicating the 219 * update the header bits in the xsave header, indicating the
220 * presence of FP and SSE state. 220 * presence of FP and SSE state.
221 */ 221 */
222 if (cpu_has_xsave) 222 if (cpu_has_xsave)
223 target->thread.xstate->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE; 223 target->thread.fpu.state->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE;
224 224
225 return ret; 225 return ret;
226} 226}
@@ -243,14 +243,14 @@ int xstateregs_get(struct task_struct *target, const struct user_regset *regset,
243 * memory layout in the thread struct, so that we can copy the entire 243 * memory layout in the thread struct, so that we can copy the entire
244 * xstateregs to the user using one user_regset_copyout(). 244 * xstateregs to the user using one user_regset_copyout().
245 */ 245 */
246 memcpy(&target->thread.xstate->fxsave.sw_reserved, 246 memcpy(&target->thread.fpu.state->fxsave.sw_reserved,
247 xstate_fx_sw_bytes, sizeof(xstate_fx_sw_bytes)); 247 xstate_fx_sw_bytes, sizeof(xstate_fx_sw_bytes));
248 248
249 /* 249 /*
250 * Copy the xstate memory layout. 250 * Copy the xstate memory layout.
251 */ 251 */
252 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 252 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
253 &target->thread.xstate->xsave, 0, -1); 253 &target->thread.fpu.state->xsave, 0, -1);
254 return ret; 254 return ret;
255} 255}
256 256
@@ -269,14 +269,14 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
269 return ret; 269 return ret;
270 270
271 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 271 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
272 &target->thread.xstate->xsave, 0, -1); 272 &target->thread.fpu.state->xsave, 0, -1);
273 273
274 /* 274 /*
275 * mxcsr reserved bits must be masked to zero for security reasons. 275 * mxcsr reserved bits must be masked to zero for security reasons.
276 */ 276 */
277 target->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask; 277 target->thread.fpu.state->fxsave.mxcsr &= mxcsr_feature_mask;
278 278
279 xsave_hdr = &target->thread.xstate->xsave.xsave_hdr; 279 xsave_hdr = &target->thread.fpu.state->xsave.xsave_hdr;
280 280
281 xsave_hdr->xstate_bv &= pcntxt_mask; 281 xsave_hdr->xstate_bv &= pcntxt_mask;
282 /* 282 /*
@@ -362,7 +362,7 @@ static inline u32 twd_fxsr_to_i387(struct i387_fxsave_struct *fxsave)
362static void 362static void
363convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk) 363convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk)
364{ 364{
365 struct i387_fxsave_struct *fxsave = &tsk->thread.xstate->fxsave; 365 struct i387_fxsave_struct *fxsave = &tsk->thread.fpu.state->fxsave;
366 struct _fpreg *to = (struct _fpreg *) &env->st_space[0]; 366 struct _fpreg *to = (struct _fpreg *) &env->st_space[0];
367 struct _fpxreg *from = (struct _fpxreg *) &fxsave->st_space[0]; 367 struct _fpxreg *from = (struct _fpxreg *) &fxsave->st_space[0];
368 int i; 368 int i;
@@ -402,7 +402,7 @@ static void convert_to_fxsr(struct task_struct *tsk,
402 const struct user_i387_ia32_struct *env) 402 const struct user_i387_ia32_struct *env)
403 403
404{ 404{
405 struct i387_fxsave_struct *fxsave = &tsk->thread.xstate->fxsave; 405 struct i387_fxsave_struct *fxsave = &tsk->thread.fpu.state->fxsave;
406 struct _fpreg *from = (struct _fpreg *) &env->st_space[0]; 406 struct _fpreg *from = (struct _fpreg *) &env->st_space[0];
407 struct _fpxreg *to = (struct _fpxreg *) &fxsave->st_space[0]; 407 struct _fpxreg *to = (struct _fpxreg *) &fxsave->st_space[0];
408 int i; 408 int i;
@@ -442,7 +442,7 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset,
442 442
443 if (!cpu_has_fxsr) { 443 if (!cpu_has_fxsr) {
444 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, 444 return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
445 &target->thread.xstate->fsave, 0, 445 &target->thread.fpu.state->fsave, 0,
446 -1); 446 -1);
447 } 447 }
448 448
@@ -472,7 +472,7 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
472 472
473 if (!cpu_has_fxsr) { 473 if (!cpu_has_fxsr) {
474 return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 474 return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
475 &target->thread.xstate->fsave, 0, -1); 475 &target->thread.fpu.state->fsave, 0, -1);
476 } 476 }
477 477
478 if (pos > 0 || count < sizeof(env)) 478 if (pos > 0 || count < sizeof(env))
@@ -487,7 +487,7 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
487 * presence of FP. 487 * presence of FP.
488 */ 488 */
489 if (cpu_has_xsave) 489 if (cpu_has_xsave)
490 target->thread.xstate->xsave.xsave_hdr.xstate_bv |= XSTATE_FP; 490 target->thread.fpu.state->xsave.xsave_hdr.xstate_bv |= XSTATE_FP;
491 return ret; 491 return ret;
492} 492}
493 493
@@ -498,7 +498,7 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
498static inline int save_i387_fsave(struct _fpstate_ia32 __user *buf) 498static inline int save_i387_fsave(struct _fpstate_ia32 __user *buf)
499{ 499{
500 struct task_struct *tsk = current; 500 struct task_struct *tsk = current;
501 struct i387_fsave_struct *fp = &tsk->thread.xstate->fsave; 501 struct i387_fsave_struct *fp = &tsk->thread.fpu.state->fsave;
502 502
503 fp->status = fp->swd; 503 fp->status = fp->swd;
504 if (__copy_to_user(buf, fp, sizeof(struct i387_fsave_struct))) 504 if (__copy_to_user(buf, fp, sizeof(struct i387_fsave_struct)))
@@ -509,7 +509,7 @@ static inline int save_i387_fsave(struct _fpstate_ia32 __user *buf)
509static int save_i387_fxsave(struct _fpstate_ia32 __user *buf) 509static int save_i387_fxsave(struct _fpstate_ia32 __user *buf)
510{ 510{
511 struct task_struct *tsk = current; 511 struct task_struct *tsk = current;
512 struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave; 512 struct i387_fxsave_struct *fx = &tsk->thread.fpu.state->fxsave;
513 struct user_i387_ia32_struct env; 513 struct user_i387_ia32_struct env;
514 int err = 0; 514 int err = 0;
515 515
@@ -544,7 +544,7 @@ static int save_i387_xsave(void __user *buf)
544 * header as well as change any contents in the memory layout. 544 * header as well as change any contents in the memory layout.
545 * xrestore as part of sigreturn will capture all the changes. 545 * xrestore as part of sigreturn will capture all the changes.
546 */ 546 */
547 tsk->thread.xstate->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE; 547 tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE;
548 548
549 if (save_i387_fxsave(fx) < 0) 549 if (save_i387_fxsave(fx) < 0)
550 return -1; 550 return -1;
@@ -596,7 +596,7 @@ static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf)
596{ 596{
597 struct task_struct *tsk = current; 597 struct task_struct *tsk = current;
598 598
599 return __copy_from_user(&tsk->thread.xstate->fsave, buf, 599 return __copy_from_user(&tsk->thread.fpu.state->fsave, buf,
600 sizeof(struct i387_fsave_struct)); 600 sizeof(struct i387_fsave_struct));
601} 601}
602 602
@@ -607,10 +607,10 @@ static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf,
607 struct user_i387_ia32_struct env; 607 struct user_i387_ia32_struct env;
608 int err; 608 int err;
609 609
610 err = __copy_from_user(&tsk->thread.xstate->fxsave, &buf->_fxsr_env[0], 610 err = __copy_from_user(&tsk->thread.fpu.state->fxsave, &buf->_fxsr_env[0],
611 size); 611 size);
612 /* mxcsr reserved bits must be masked to zero for security reasons */ 612 /* mxcsr reserved bits must be masked to zero for security reasons */
613 tsk->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask; 613 tsk->thread.fpu.state->fxsave.mxcsr &= mxcsr_feature_mask;
614 if (err || __copy_from_user(&env, buf, sizeof(env))) 614 if (err || __copy_from_user(&env, buf, sizeof(env)))
615 return 1; 615 return 1;
616 convert_to_fxsr(tsk, &env); 616 convert_to_fxsr(tsk, &env);
@@ -626,7 +626,7 @@ static int restore_i387_xsave(void __user *buf)
626 struct i387_fxsave_struct __user *fx = 626 struct i387_fxsave_struct __user *fx =
627 (struct i387_fxsave_struct __user *) &fx_user->_fxsr_env[0]; 627 (struct i387_fxsave_struct __user *) &fx_user->_fxsr_env[0];
628 struct xsave_hdr_struct *xsave_hdr = 628 struct xsave_hdr_struct *xsave_hdr =
629 &current->thread.xstate->xsave.xsave_hdr; 629 &current->thread.fpu.state->xsave.xsave_hdr;
630 u64 mask; 630 u64 mask;
631 int err; 631 int err;
632 632
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 28ad9f4d8b94..f18fd9c15247 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -32,25 +32,22 @@ struct kmem_cache *task_xstate_cachep;
32 32
33int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) 33int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
34{ 34{
35 int ret;
36
35 *dst = *src; 37 *dst = *src;
36 if (src->thread.xstate) { 38 if (fpu_allocated(&src->thread.fpu)) {
37 dst->thread.xstate = kmem_cache_alloc(task_xstate_cachep, 39 memset(&dst->thread.fpu, 0, sizeof(dst->thread.fpu));
38 GFP_KERNEL); 40 ret = fpu_alloc(&dst->thread.fpu);
39 if (!dst->thread.xstate) 41 if (ret)
40 return -ENOMEM; 42 return ret;
41 WARN_ON((unsigned long)dst->thread.xstate & 15); 43 fpu_copy(&dst->thread.fpu, &src->thread.fpu);
42 memcpy(dst->thread.xstate, src->thread.xstate, xstate_size);
43 } 44 }
44 return 0; 45 return 0;
45} 46}
46 47
47void free_thread_xstate(struct task_struct *tsk) 48void free_thread_xstate(struct task_struct *tsk)
48{ 49{
49 if (tsk->thread.xstate) { 50 fpu_free(&tsk->thread.fpu);
50 kmem_cache_free(task_xstate_cachep, tsk->thread.xstate);
51 tsk->thread.xstate = NULL;
52 }
53
54 WARN(tsk->thread.ds_ctx, "leaking DS context\n"); 51 WARN(tsk->thread.ds_ctx, "leaking DS context\n");
55} 52}
56 53
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index f6c62667e30c..0a7a4f5bbaa9 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -317,7 +317,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
317 317
318 /* we're going to use this soon, after a few expensive things */ 318 /* we're going to use this soon, after a few expensive things */
319 if (preload_fpu) 319 if (preload_fpu)
320 prefetch(next->xstate); 320 prefetch(next->fpu.state);
321 321
322 /* 322 /*
323 * Reload esp0. 323 * Reload esp0.
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 17cb3295cbf7..979215f51985 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -396,7 +396,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
396 396
397 /* we're going to use this soon, after a few expensive things */ 397 /* we're going to use this soon, after a few expensive things */
398 if (preload_fpu) 398 if (preload_fpu)
399 prefetch(next->xstate); 399 prefetch(next->fpu.state);
400 400
401 /* 401 /*
402 * Reload esp0, LDT and the page table pointer: 402 * Reload esp0, LDT and the page table pointer:
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index c1b0a11033a2..37e68fc5e24a 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -109,7 +109,7 @@ int save_i387_xstate(void __user *buf)
109 task_thread_info(tsk)->status &= ~TS_USEDFPU; 109 task_thread_info(tsk)->status &= ~TS_USEDFPU;
110 stts(); 110 stts();
111 } else { 111 } else {
112 if (__copy_to_user(buf, &tsk->thread.xstate->fxsave, 112 if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave,
113 xstate_size)) 113 xstate_size))
114 return -1; 114 return -1;
115 } 115 }
diff --git a/arch/x86/math-emu/fpu_aux.c b/arch/x86/math-emu/fpu_aux.c
index aa0987088774..62797f930511 100644
--- a/arch/x86/math-emu/fpu_aux.c
+++ b/arch/x86/math-emu/fpu_aux.c
@@ -30,10 +30,10 @@ static void fclex(void)
30} 30}
31 31
32/* Needs to be externally visible */ 32/* Needs to be externally visible */
33void finit_task(struct task_struct *tsk) 33void finit_soft_fpu(struct i387_soft_struct *soft)
34{ 34{
35 struct i387_soft_struct *soft = &tsk->thread.xstate->soft;
36 struct address *oaddr, *iaddr; 35 struct address *oaddr, *iaddr;
36 memset(soft, 0, sizeof(*soft));
37 soft->cwd = 0x037f; 37 soft->cwd = 0x037f;
38 soft->swd = 0; 38 soft->swd = 0;
39 soft->ftop = 0; /* We don't keep top in the status word internally. */ 39 soft->ftop = 0; /* We don't keep top in the status word internally. */
@@ -52,7 +52,7 @@ void finit_task(struct task_struct *tsk)
52 52
53void finit(void) 53void finit(void)
54{ 54{
55 finit_task(current); 55 finit_task(&current->thread.fpu);
56} 56}
57 57
58/* 58/*