i387.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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. } while (0)
  72. #define __clear_fpu( tsk ) \
  73. do { \
  74. if (task_thread_info(tsk)->status & TS_USEDFPU) { \
  75. asm volatile("fnclex ; fwait"); \
  76. task_thread_info(tsk)->status &= ~TS_USEDFPU; \
  77. stts(); \
  78. } \
  79. } while (0)
  80. /*
  81. * These disable preemption on their own and are safe
  82. */
  83. static inline void save_init_fpu( struct task_struct *tsk )
  84. {
  85. preempt_disable();
  86. __save_init_fpu(tsk);
  87. stts();
  88. preempt_enable();
  89. }
  90. #define unlazy_fpu( tsk ) do { \
  91. preempt_disable(); \
  92. __unlazy_fpu(tsk); \
  93. preempt_enable(); \
  94. } while (0)
  95. #define clear_fpu( tsk ) do { \
  96. preempt_disable(); \
  97. __clear_fpu( tsk ); \
  98. preempt_enable(); \
  99. } while (0)
  100. \
  101. /*
  102. * FPU state interaction...
  103. */
  104. extern unsigned short get_fpu_cwd( struct task_struct *tsk );
  105. extern unsigned short get_fpu_swd( struct task_struct *tsk );
  106. extern unsigned short get_fpu_mxcsr( struct task_struct *tsk );
  107. /*
  108. * Signal frame handlers...
  109. */
  110. extern int save_i387( struct _fpstate __user *buf );
  111. extern int restore_i387( struct _fpstate __user *buf );
  112. /*
  113. * ptrace request handers...
  114. */
  115. extern int get_fpregs( struct user_i387_struct __user *buf,
  116. struct task_struct *tsk );
  117. extern int set_fpregs( struct task_struct *tsk,
  118. struct user_i387_struct __user *buf );
  119. extern int get_fpxregs( struct user_fxsr_struct __user *buf,
  120. struct task_struct *tsk );
  121. extern int set_fpxregs( struct task_struct *tsk,
  122. struct user_fxsr_struct __user *buf );
  123. /*
  124. * FPU state for core dumps...
  125. */
  126. extern int dump_fpu( struct pt_regs *regs,
  127. struct user_i387_struct *fpu );
  128. #endif /* __ASM_I386_I387_H */