8 #include <linux/module.h>
10 #include <linux/sched.h>
11 #include <linux/slab.h>
13 #include <asm/sigcontext.h>
14 #include <asm/processor.h>
16 #include <asm/uaccess.h>
17 #include <asm/ptrace.h>
38 static inline bool interrupted_kernel_fpu_idle(
void)
43 return !__thread_has_fpu(
current) &&
55 static inline bool interrupted_user_mode(
void)
58 return regs && user_mode_vm(regs);
71 interrupted_user_mode() ||
72 interrupted_kernel_fpu_idle();
80 if (__thread_has_fpu(me)) {
82 __thread_clear_has_fpu(me);
84 }
else if (!use_eager_fpu()) {
103 if (__thread_has_fpu(tsk)) {
104 __save_init_fpu(tsk);
105 __thread_fpu_end(tsk);
117 static void __cpuinit mxcsr_feature_mask_init(
void)
119 unsigned long mask = 0;
123 asm volatile(
"fxsave %0" : :
"m" (fx_scratch));
124 mask = fx_scratch.mxcsr_mask;
163 unsigned long cr4_mask = 0;
170 set_in_cr4(cr4_mask);
181 mxcsr_feature_mask_init();
197 memset(fp, 0, xstate_size);
198 fp->
cwd = 0xffff037f
u;
199 fp->
swd = 0xffff0000
u;
200 fp->
twd = 0xffffffff
u;
201 fp->
fos = 0xffff0000
u;
219 tsk->
thread.fpu.last_cpu = ~0;
226 ret = fpu_alloc(&tsk->
thread.fpu);
253 unsigned int pos,
unsigned int count,
254 void *kbuf,
void __user *ubuf)
265 sanitize_i387_state(target);
267 return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
268 &target->
thread.fpu.state->fxsave, 0, -1);
272 unsigned int pos,
unsigned int count,
273 const void *kbuf,
const void __user *ubuf)
284 sanitize_i387_state(target);
286 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
287 &target->
thread.fpu.state->fxsave, 0, -1);
305 unsigned int pos,
unsigned int count,
306 void *kbuf,
void __user *ubuf)
328 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
329 &target->
thread.fpu.state->xsave, 0, -1);
334 unsigned int pos,
unsigned int count,
335 const void *kbuf,
const void __user *ubuf)
347 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
348 &target->
thread.fpu.state->xsave, 0, -1);
355 xsave_hdr = &target->
thread.fpu.state->xsave.xsave_hdr;
366 #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
372 static inline unsigned short twd_i387_to_fxsr(
unsigned short twd)
378 tmp = (tmp | (tmp>>1)) & 0x5555;
380 tmp = (tmp | (tmp >> 1)) & 0x3333;
381 tmp = (tmp | (tmp >> 2)) & 0x0f0f;
382 tmp = (tmp | (tmp >> 4)) & 0x00ff;
387 #define FPREG_ADDR(f, n) ((void *)&(f)->st_space + (n) * 16)
388 #define FP_EXP_TAG_VALID 0
389 #define FP_EXP_TAG_ZERO 1
390 #define FP_EXP_TAG_SPECIAL 2
391 #define FP_EXP_TAG_EMPTY 3
396 u32 tos = (fxsave->
swd >> 11) & 7;
402 for (
i = 0; i < 8; i++, twd >>= 1) {
404 st = FPREG_ADDR(fxsave, (
i - tos) & 7);
408 tag = FP_EXP_TAG_SPECIAL;
415 tag = FP_EXP_TAG_ZERO;
417 tag = FP_EXP_TAG_SPECIAL;
421 tag = FP_EXP_TAG_VALID;
423 tag = FP_EXP_TAG_SPECIAL;
427 tag = FP_EXP_TAG_EMPTY;
446 env->
cwd = fxsave->
cwd | 0xffff0000
u;
447 env->
swd = fxsave->
swd | 0xffff0000
u;
448 env->
twd = twd_fxsr_to_i387(fxsave);
459 savesegment(
ds, env->
fos);
463 env->
fos |= 0xffff0000;
471 for (i = 0; i < 8; ++
i)
486 fxsave->
twd = twd_i387_to_fxsr(env->
twd);
494 fxsave->
fcs = (env->
fcs & 0xffff);
499 for (i = 0; i < 8; ++
i)
500 memcpy(&to[i], &from[i],
sizeof(from[0]));
504 unsigned int pos,
unsigned int count,
505 void *kbuf,
void __user *ubuf)
518 return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
519 &target->
thread.fpu.state->fsave, 0,
523 sanitize_i387_state(target);
525 if (kbuf && pos == 0 && count ==
sizeof(env)) {
532 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &env, 0, -1);
536 unsigned int pos,
unsigned int count,
537 const void *kbuf,
const void __user *ubuf)
546 sanitize_i387_state(target);
552 return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
553 &target->
thread.fpu.state->fsave, 0, -1);
556 if (pos > 0 || count <
sizeof(env))
559 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &env, 0, -1);