fpu.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __KVM_FPU_H_
  3. #define __KVM_FPU_H_
  4. #include <asm/fpu/api.h>
  5. typedef u32 __attribute__((vector_size(16))) sse128_t;
  6. #define __sse128_u union { sse128_t vec; u64 as_u64[2]; u32 as_u32[4]; }
  7. #define sse128_lo(x) ({ __sse128_u t; t.vec = x; t.as_u64[0]; })
  8. #define sse128_hi(x) ({ __sse128_u t; t.vec = x; t.as_u64[1]; })
  9. #define sse128_l0(x) ({ __sse128_u t; t.vec = x; t.as_u32[0]; })
  10. #define sse128_l1(x) ({ __sse128_u t; t.vec = x; t.as_u32[1]; })
  11. #define sse128_l2(x) ({ __sse128_u t; t.vec = x; t.as_u32[2]; })
  12. #define sse128_l3(x) ({ __sse128_u t; t.vec = x; t.as_u32[3]; })
  13. #define sse128(lo, hi) ({ __sse128_u t; t.as_u64[0] = lo; t.as_u64[1] = hi; t.vec; })
  14. static inline void _kvm_read_sse_reg(int reg, sse128_t *data)
  15. {
  16. switch (reg) {
  17. case 0: asm("movdqa %%xmm0, %0" : "=m"(*data)); break;
  18. case 1: asm("movdqa %%xmm1, %0" : "=m"(*data)); break;
  19. case 2: asm("movdqa %%xmm2, %0" : "=m"(*data)); break;
  20. case 3: asm("movdqa %%xmm3, %0" : "=m"(*data)); break;
  21. case 4: asm("movdqa %%xmm4, %0" : "=m"(*data)); break;
  22. case 5: asm("movdqa %%xmm5, %0" : "=m"(*data)); break;
  23. case 6: asm("movdqa %%xmm6, %0" : "=m"(*data)); break;
  24. case 7: asm("movdqa %%xmm7, %0" : "=m"(*data)); break;
  25. #ifdef CONFIG_X86_64
  26. case 8: asm("movdqa %%xmm8, %0" : "=m"(*data)); break;
  27. case 9: asm("movdqa %%xmm9, %0" : "=m"(*data)); break;
  28. case 10: asm("movdqa %%xmm10, %0" : "=m"(*data)); break;
  29. case 11: asm("movdqa %%xmm11, %0" : "=m"(*data)); break;
  30. case 12: asm("movdqa %%xmm12, %0" : "=m"(*data)); break;
  31. case 13: asm("movdqa %%xmm13, %0" : "=m"(*data)); break;
  32. case 14: asm("movdqa %%xmm14, %0" : "=m"(*data)); break;
  33. case 15: asm("movdqa %%xmm15, %0" : "=m"(*data)); break;
  34. #endif
  35. default: BUG();
  36. }
  37. }
  38. static inline void _kvm_write_sse_reg(int reg, const sse128_t *data)
  39. {
  40. switch (reg) {
  41. case 0: asm("movdqa %0, %%xmm0" : : "m"(*data)); break;
  42. case 1: asm("movdqa %0, %%xmm1" : : "m"(*data)); break;
  43. case 2: asm("movdqa %0, %%xmm2" : : "m"(*data)); break;
  44. case 3: asm("movdqa %0, %%xmm3" : : "m"(*data)); break;
  45. case 4: asm("movdqa %0, %%xmm4" : : "m"(*data)); break;
  46. case 5: asm("movdqa %0, %%xmm5" : : "m"(*data)); break;
  47. case 6: asm("movdqa %0, %%xmm6" : : "m"(*data)); break;
  48. case 7: asm("movdqa %0, %%xmm7" : : "m"(*data)); break;
  49. #ifdef CONFIG_X86_64
  50. case 8: asm("movdqa %0, %%xmm8" : : "m"(*data)); break;
  51. case 9: asm("movdqa %0, %%xmm9" : : "m"(*data)); break;
  52. case 10: asm("movdqa %0, %%xmm10" : : "m"(*data)); break;
  53. case 11: asm("movdqa %0, %%xmm11" : : "m"(*data)); break;
  54. case 12: asm("movdqa %0, %%xmm12" : : "m"(*data)); break;
  55. case 13: asm("movdqa %0, %%xmm13" : : "m"(*data)); break;
  56. case 14: asm("movdqa %0, %%xmm14" : : "m"(*data)); break;
  57. case 15: asm("movdqa %0, %%xmm15" : : "m"(*data)); break;
  58. #endif
  59. default: BUG();
  60. }
  61. }
  62. static inline void _kvm_read_mmx_reg(int reg, u64 *data)
  63. {
  64. switch (reg) {
  65. case 0: asm("movq %%mm0, %0" : "=m"(*data)); break;
  66. case 1: asm("movq %%mm1, %0" : "=m"(*data)); break;
  67. case 2: asm("movq %%mm2, %0" : "=m"(*data)); break;
  68. case 3: asm("movq %%mm3, %0" : "=m"(*data)); break;
  69. case 4: asm("movq %%mm4, %0" : "=m"(*data)); break;
  70. case 5: asm("movq %%mm5, %0" : "=m"(*data)); break;
  71. case 6: asm("movq %%mm6, %0" : "=m"(*data)); break;
  72. case 7: asm("movq %%mm7, %0" : "=m"(*data)); break;
  73. default: BUG();
  74. }
  75. }
  76. static inline void _kvm_write_mmx_reg(int reg, const u64 *data)
  77. {
  78. switch (reg) {
  79. case 0: asm("movq %0, %%mm0" : : "m"(*data)); break;
  80. case 1: asm("movq %0, %%mm1" : : "m"(*data)); break;
  81. case 2: asm("movq %0, %%mm2" : : "m"(*data)); break;
  82. case 3: asm("movq %0, %%mm3" : : "m"(*data)); break;
  83. case 4: asm("movq %0, %%mm4" : : "m"(*data)); break;
  84. case 5: asm("movq %0, %%mm5" : : "m"(*data)); break;
  85. case 6: asm("movq %0, %%mm6" : : "m"(*data)); break;
  86. case 7: asm("movq %0, %%mm7" : : "m"(*data)); break;
  87. default: BUG();
  88. }
  89. }
  90. static inline void kvm_fpu_get(void)
  91. {
  92. fpregs_lock();
  93. fpregs_assert_state_consistent();
  94. if (test_thread_flag(TIF_NEED_FPU_LOAD))
  95. switch_fpu_return();
  96. }
  97. static inline void kvm_fpu_put(void)
  98. {
  99. fpregs_unlock();
  100. }
  101. static inline void kvm_read_sse_reg(int reg, sse128_t *data)
  102. {
  103. kvm_fpu_get();
  104. _kvm_read_sse_reg(reg, data);
  105. kvm_fpu_put();
  106. }
  107. static inline void kvm_write_sse_reg(int reg, const sse128_t *data)
  108. {
  109. kvm_fpu_get();
  110. _kvm_write_sse_reg(reg, data);
  111. kvm_fpu_put();
  112. }
  113. static inline void kvm_read_mmx_reg(int reg, u64 *data)
  114. {
  115. kvm_fpu_get();
  116. _kvm_read_mmx_reg(reg, data);
  117. kvm_fpu_put();
  118. }
  119. static inline void kvm_write_mmx_reg(int reg, const u64 *data)
  120. {
  121. kvm_fpu_get();
  122. _kvm_write_mmx_reg(reg, data);
  123. kvm_fpu_put();
  124. }
  125. #endif