i387_32.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. * include/asm-i386/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. */
  10. #ifndef __ASM_I386_I387_H
  11. #define __ASM_I386_I387_H
  12. #include <linux/sched.h>
  13. #include <linux/init.h>
  14. #include <linux/kernel_stat.h>
  15. #include <asm/processor.h>
  16. #include <asm/sigcontext.h>
  17. #include <asm/user.h>
  18. extern void mxcsr_feature_mask_init(void);
  19. extern void init_fpu(struct task_struct *);
  20. /*
  21. * FPU lazy state save handling...
  22. */
  23. /*
  24. * The "nop" is needed to make the instructions the same
  25. * length.
  26. */
  27. #define restore_fpu(tsk) \
  28. alternative_input( \
  29. "nop ; frstor %1", \
  30. "fxrstor %1", \
  31. X86_FEATURE_FXSR, \
  32. "m" ((tsk)->thread.i387.fxsave))
  33. extern void kernel_fpu_begin(void);
  34. #define kernel_fpu_end() do { stts(); preempt_enable(); } while(0)
  35. /* We need a safe address that is cheap to find and that is already
  36. in L1 during context switch. The best choices are unfortunately
  37. different for UP and SMP */
  38. #ifdef CONFIG_SMP
  39. #define safe_address (__per_cpu_offset[0])
  40. #else
  41. #define safe_address (kstat_cpu(0).cpustat.user)
  42. #endif
  43. /*
  44. * These must be called with preempt disabled
  45. */
  46. static inline void __save_init_fpu( struct task_struct *tsk )
  47. {
  48. /* Use more nops than strictly needed in case the compiler
  49. varies code */
  50. alternative_input(
  51. "fnsave %[fx] ;fwait;" GENERIC_NOP8 GENERIC_NOP4,
  52. "fxsave %[fx]\n"
  53. "bt $7,%[fsw] ; jnc 1f ; fnclex\n1:",
  54. X86_FEATURE_FXSR,
  55. [fx] "m" (tsk->thread.i387.fxsave),
  56. [fsw] "m" (tsk->thread.i387.fxsave.swd) : "memory");
  57. /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
  58. is pending. Clear the x87 state here by setting it to fixed
  59. values. safe_address is a random variable that should be in L1 */
  60. alternative_input(
  61. GENERIC_NOP8 GENERIC_NOP2,
  62. "emms\n\t" /* clear stack tags */
  63. "fildl %[addr]", /* set F?P to defined value */
  64. X86_FEATURE_FXSAVE_LEAK,
  65. [addr] "m" (safe_address));
  66. task_thread_info(tsk)->status &= ~TS_USEDFPU;
  67. }
  68. #define __unlazy_fpu( tsk ) do { \
  69. if (task_thread_info(tsk)->status & TS_USEDFPU) { \
  70. __save_init_fpu(tsk); \
  71. stts(); \
  72. } else \
  73. tsk->fpu_counter = 0; \
  74. } while (0)
  75. #define __clear_fpu( tsk ) \
  76. do { \
  77. if (task_thread_info(tsk)->status & TS_USEDFPU) { \
  78. asm volatile("fnclex ; fwait"); \
  79. task_thread_info(tsk)->status &= ~TS_USEDFPU; \
  80. stts(); \
  81. } \
  82. } while (0)
  83. /*
  84. * These disable preemption on their own and are safe
  85. */
  86. static inline void save_init_fpu( struct task_struct *tsk )
  87. {
  88. preempt_disable();
  89. __save_init_fpu(tsk);
  90. stts();
  91. preempt_enable();
  92. }
  93. #define unlazy_fpu( tsk ) do { \
  94. preempt_disable(); \
  95. __unlazy_fpu(tsk); \
  96. preempt_enable(); \
  97. } while (0)
  98. #define clear_fpu( tsk ) do { \
  99. preempt_disable(); \
  100. __clear_fpu( tsk ); \
  101. preempt_enable(); \
  102. } while (0)
  103. /*
  104. * FPU state interaction...
  105. */
  106. extern unsigned short get_fpu_cwd( struct task_struct *tsk );
  107. extern unsigned short get_fpu_swd( struct task_struct *tsk );
  108. extern unsigned short get_fpu_mxcsr( struct task_struct *tsk );
  109. extern asmlinkage void math_state_restore(void);
  110. /*
  111. * Signal frame handlers...
  112. */
  113. extern int save_i387( struct _fpstate __user *buf );
  114. extern int restore_i387( struct _fpstate __user *buf );
  115. /*
  116. * ptrace request handers...
  117. */
  118. extern int get_fpregs( struct user_i387_struct __user *buf,
  119. struct task_struct *tsk );
  120. extern int set_fpregs( struct task_struct *tsk,
  121. struct user_i387_struct __user *buf );
  122. extern int get_fpxregs( struct user_fxsr_struct __user *buf,
  123. struct task_struct *tsk );
  124. extern int set_fpxregs( struct task_struct *tsk,
  125. struct user_fxsr_struct __user *buf );
  126. /*
  127. * FPU state for core dumps...
  128. */
  129. extern int dump_fpu( struct pt_regs *regs,
  130. struct user_i387_struct *fpu );
  131. #endif /* __ASM_I386_I387_H */