i387.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * include/asm-x86_64/i387.h
  3. *
  4. * Copyright (C) 1994 Linus Torvalds
  5. *
  6. * Pentium III FXSR, SSE support
  7. * General FPU state handling cleanups
  8. * Gareth Hughes <gareth@valinux.com>, May 2000
  9. * x86-64 work by Andi Kleen 2002
  10. */
  11. #ifndef __ASM_X86_64_I387_H
  12. #define __ASM_X86_64_I387_H
  13. #include <linux/sched.h>
  14. #include <asm/processor.h>
  15. #include <asm/sigcontext.h>
  16. #include <asm/user.h>
  17. #include <asm/thread_info.h>
  18. #include <asm/uaccess.h>
  19. extern void fpu_init(void);
  20. extern unsigned int mxcsr_feature_mask;
  21. extern void mxcsr_feature_mask_init(void);
  22. extern void init_fpu(struct task_struct *child);
  23. extern int save_i387(struct _fpstate __user *buf);
  24. /*
  25. * FPU lazy state save handling...
  26. */
  27. #define unlazy_fpu(tsk) do { \
  28. if ((tsk)->thread_info->status & TS_USEDFPU) \
  29. save_init_fpu(tsk); \
  30. } while (0)
  31. /* Ignore delayed exceptions from user space */
  32. static inline void tolerant_fwait(void)
  33. {
  34. asm volatile("1: fwait\n"
  35. "2:\n"
  36. " .section __ex_table,\"a\"\n"
  37. " .align 8\n"
  38. " .quad 1b,2b\n"
  39. " .previous\n");
  40. }
  41. #define clear_fpu(tsk) do { \
  42. if ((tsk)->thread_info->status & TS_USEDFPU) { \
  43. tolerant_fwait(); \
  44. (tsk)->thread_info->status &= ~TS_USEDFPU; \
  45. stts(); \
  46. } \
  47. } while (0)
  48. /*
  49. * ptrace request handers...
  50. */
  51. extern int get_fpregs(struct user_i387_struct __user *buf,
  52. struct task_struct *tsk);
  53. extern int set_fpregs(struct task_struct *tsk,
  54. struct user_i387_struct __user *buf);
  55. /*
  56. * i387 state interaction
  57. */
  58. #define get_fpu_mxcsr(t) ((t)->thread.i387.fxsave.mxcsr)
  59. #define get_fpu_cwd(t) ((t)->thread.i387.fxsave.cwd)
  60. #define get_fpu_fxsr_twd(t) ((t)->thread.i387.fxsave.twd)
  61. #define get_fpu_swd(t) ((t)->thread.i387.fxsave.swd)
  62. #define set_fpu_cwd(t,val) ((t)->thread.i387.fxsave.cwd = (val))
  63. #define set_fpu_swd(t,val) ((t)->thread.i387.fxsave.swd = (val))
  64. #define set_fpu_fxsr_twd(t,val) ((t)->thread.i387.fxsave.twd = (val))
  65. static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
  66. {
  67. int err;
  68. asm volatile("1: rex64 ; fxrstor (%[fx])\n\t"
  69. "2:\n"
  70. ".section .fixup,\"ax\"\n"
  71. "3: movl $-1,%[err]\n"
  72. " jmp 2b\n"
  73. ".previous\n"
  74. ".section __ex_table,\"a\"\n"
  75. " .align 8\n"
  76. " .quad 1b,3b\n"
  77. ".previous"
  78. : [err] "=r" (err)
  79. : [fx] "r" (fx), "0" (0));
  80. if (unlikely(err))
  81. init_fpu(current);
  82. return err;
  83. }
  84. static inline int save_i387_checking(struct i387_fxsave_struct __user *fx)
  85. {
  86. int err;
  87. asm volatile("1: rex64 ; fxsave (%[fx])\n\t"
  88. "2:\n"
  89. ".section .fixup,\"ax\"\n"
  90. "3: movl $-1,%[err]\n"
  91. " jmp 2b\n"
  92. ".previous\n"
  93. ".section __ex_table,\"a\"\n"
  94. " .align 8\n"
  95. " .quad 1b,3b\n"
  96. ".previous"
  97. : [err] "=r" (err)
  98. : [fx] "r" (fx), "0" (0));
  99. if (unlikely(err))
  100. __clear_user(fx, sizeof(struct i387_fxsave_struct));
  101. return err;
  102. }
  103. static inline void kernel_fpu_begin(void)
  104. {
  105. struct thread_info *me = current_thread_info();
  106. preempt_disable();
  107. if (me->status & TS_USEDFPU) {
  108. asm volatile("rex64 ; fxsave %0 ; fnclex"
  109. : "=m" (me->task->thread.i387.fxsave));
  110. me->status &= ~TS_USEDFPU;
  111. return;
  112. }
  113. clts();
  114. }
  115. static inline void kernel_fpu_end(void)
  116. {
  117. stts();
  118. preempt_enable();
  119. }
  120. static inline void save_init_fpu( struct task_struct *tsk )
  121. {
  122. asm volatile( "rex64 ; fxsave %0 ; fnclex"
  123. : "=m" (tsk->thread.i387.fxsave));
  124. tsk->thread_info->status &= ~TS_USEDFPU;
  125. stts();
  126. }
  127. /*
  128. * This restores directly out of user space. Exceptions are handled.
  129. */
  130. static inline int restore_i387(struct _fpstate __user *buf)
  131. {
  132. return restore_fpu_checking((__force struct i387_fxsave_struct *)buf);
  133. }
  134. #endif /* __ASM_X86_64_I387_H */