tdxcall.S 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #include <asm/asm-offsets.h>
  3. #include <asm/frame.h>
  4. #include <asm/asm.h>
  5. #include <asm/tdx.h>
  6. /*
  7. * TDCALL and SEAMCALL are supported in Binutils >= 2.36.
  8. */
  9. #define tdcall .byte 0x66,0x0f,0x01,0xcc
  10. #define seamcall .byte 0x66,0x0f,0x01,0xcf
  11. /*
  12. * TDX_MODULE_CALL - common helper macro for both
  13. * TDCALL and SEAMCALL instructions.
  14. *
  15. * TDCALL - used by TDX guests to make requests to the
  16. * TDX module and hypercalls to the VMM.
  17. * SEAMCALL - used by TDX hosts to make requests to the
  18. * TDX module.
  19. *
  20. *-------------------------------------------------------------------------
  21. * TDCALL/SEAMCALL ABI:
  22. *-------------------------------------------------------------------------
  23. * Input Registers:
  24. *
  25. * RAX - TDCALL/SEAMCALL Leaf number.
  26. * RCX,RDX,RDI,RSI,RBX,R8-R15 - TDCALL/SEAMCALL Leaf specific input registers.
  27. *
  28. * Output Registers:
  29. *
  30. * RAX - TDCALL/SEAMCALL instruction error code.
  31. * RCX,RDX,RDI,RSI,RBX,R8-R15 - TDCALL/SEAMCALL Leaf specific output registers.
  32. *
  33. *-------------------------------------------------------------------------
  34. *
  35. * So while the common core (RAX,RCX,RDX,R8-R11) fits nicely in the
  36. * callee-clobbered registers and even leaves RDI,RSI free to act as a
  37. * base pointer, some leafs (e.g., VP.ENTER) make a giant mess of things.
  38. *
  39. * For simplicity, assume that anything that needs the callee-saved regs
  40. * also tramples on RDI,RSI. This isn't strictly true, see for example
  41. * TDH.EXPORT.MEM.
  42. */
  43. .macro TDX_MODULE_CALL host:req ret=0 saved=0
  44. FRAME_BEGIN
  45. /* Move Leaf ID to RAX */
  46. mov %rdi, %rax
  47. /* Move other input regs from 'struct tdx_module_args' */
  48. movq TDX_MODULE_rcx(%rsi), %rcx
  49. movq TDX_MODULE_rdx(%rsi), %rdx
  50. movq TDX_MODULE_r8(%rsi), %r8
  51. movq TDX_MODULE_r9(%rsi), %r9
  52. movq TDX_MODULE_r10(%rsi), %r10
  53. movq TDX_MODULE_r11(%rsi), %r11
  54. .if \saved
  55. /*
  56. * Move additional input regs from the structure. For simplicity
  57. * assume that anything needs the callee-saved regs also tramples
  58. * on RDI/RSI (see VP.ENTER).
  59. */
  60. /* Save those callee-saved GPRs as mandated by the x86_64 ABI */
  61. pushq %rbx
  62. pushq %r12
  63. pushq %r13
  64. pushq %r14
  65. pushq %r15
  66. movq TDX_MODULE_r12(%rsi), %r12
  67. movq TDX_MODULE_r13(%rsi), %r13
  68. movq TDX_MODULE_r14(%rsi), %r14
  69. movq TDX_MODULE_r15(%rsi), %r15
  70. movq TDX_MODULE_rbx(%rsi), %rbx
  71. .if \ret
  72. /* Save the structure pointer as RSI is about to be clobbered */
  73. pushq %rsi
  74. .endif
  75. movq TDX_MODULE_rdi(%rsi), %rdi
  76. /* RSI needs to be done at last */
  77. movq TDX_MODULE_rsi(%rsi), %rsi
  78. .endif /* \saved */
  79. .if \host
  80. .Lseamcall\@:
  81. seamcall
  82. /*
  83. * SEAMCALL instruction is essentially a VMExit from VMX root
  84. * mode to SEAM VMX root mode. VMfailInvalid (CF=1) indicates
  85. * that the targeted SEAM firmware is not loaded or disabled,
  86. * or P-SEAMLDR is busy with another SEAMCALL. %rax is not
  87. * changed in this case.
  88. *
  89. * Set %rax to TDX_SEAMCALL_VMFAILINVALID for VMfailInvalid.
  90. * This value will never be used as actual SEAMCALL error code as
  91. * it is from the Reserved status code class.
  92. */
  93. jc .Lseamcall_vmfailinvalid\@
  94. .else
  95. tdcall
  96. .endif
  97. .if \ret
  98. .if \saved
  99. /*
  100. * Restore the structure from stack to save the output registers
  101. *
  102. * In case of VP.ENTER returns due to TDVMCALL, all registers are
  103. * valid thus no register can be used as spare to restore the
  104. * structure from the stack (see "TDH.VP.ENTER Output Operands
  105. * Definition on TDCALL(TDG.VP.VMCALL) Following a TD Entry").
  106. * For this case, need to make one register as spare by saving it
  107. * to the stack and then manually load the structure pointer to
  108. * the spare register.
  109. *
  110. * Note for other TDCALLs/SEAMCALLs there are spare registers
  111. * thus no need for such hack but just use this for all.
  112. */
  113. pushq %rax /* save the TDCALL/SEAMCALL return code */
  114. movq 8(%rsp), %rax /* restore the structure pointer */
  115. movq %rsi, TDX_MODULE_rsi(%rax) /* save RSI */
  116. popq %rax /* restore the return code */
  117. popq %rsi /* pop the structure pointer */
  118. /* Copy additional output regs to the structure */
  119. movq %r12, TDX_MODULE_r12(%rsi)
  120. movq %r13, TDX_MODULE_r13(%rsi)
  121. movq %r14, TDX_MODULE_r14(%rsi)
  122. movq %r15, TDX_MODULE_r15(%rsi)
  123. movq %rbx, TDX_MODULE_rbx(%rsi)
  124. movq %rdi, TDX_MODULE_rdi(%rsi)
  125. .endif /* \saved */
  126. /* Copy output registers to the structure */
  127. movq %rcx, TDX_MODULE_rcx(%rsi)
  128. movq %rdx, TDX_MODULE_rdx(%rsi)
  129. movq %r8, TDX_MODULE_r8(%rsi)
  130. movq %r9, TDX_MODULE_r9(%rsi)
  131. movq %r10, TDX_MODULE_r10(%rsi)
  132. movq %r11, TDX_MODULE_r11(%rsi)
  133. .endif /* \ret */
  134. .if \saved && \ret
  135. /*
  136. * Clear registers shared by guest for VP.VMCALL/VP.ENTER to prevent
  137. * speculative use of guest's/VMM's values, including those are
  138. * restored from the stack.
  139. *
  140. * See arch/x86/kvm/vmx/vmenter.S:
  141. *
  142. * In theory, a L1 cache miss when restoring register from stack
  143. * could lead to speculative execution with guest's values.
  144. *
  145. * Note: RBP/RSP are not used as shared register. RSI has been
  146. * restored already.
  147. *
  148. * XOR is cheap, thus unconditionally do for all leafs.
  149. */
  150. xorl %ecx, %ecx
  151. xorl %edx, %edx
  152. xorl %r8d, %r8d
  153. xorl %r9d, %r9d
  154. xorl %r10d, %r10d
  155. xorl %r11d, %r11d
  156. xorl %r12d, %r12d
  157. xorl %r13d, %r13d
  158. xorl %r14d, %r14d
  159. xorl %r15d, %r15d
  160. xorl %ebx, %ebx
  161. xorl %edi, %edi
  162. .endif /* \ret && \host */
  163. .if \host
  164. .Lout\@:
  165. .endif
  166. .if \saved
  167. /* Restore callee-saved GPRs as mandated by the x86_64 ABI */
  168. popq %r15
  169. popq %r14
  170. popq %r13
  171. popq %r12
  172. popq %rbx
  173. .endif /* \saved */
  174. FRAME_END
  175. RET
  176. .if \host
  177. .Lseamcall_vmfailinvalid\@:
  178. mov $TDX_SEAMCALL_VMFAILINVALID, %rax
  179. jmp .Lseamcall_fail\@
  180. .Lseamcall_trap\@:
  181. /*
  182. * SEAMCALL caused #GP or #UD. By reaching here RAX contains
  183. * the trap number. Convert the trap number to the TDX error
  184. * code by setting TDX_SW_ERROR to the high 32-bits of RAX.
  185. *
  186. * Note cannot OR TDX_SW_ERROR directly to RAX as OR instruction
  187. * only accepts 32-bit immediate at most.
  188. */
  189. movq $TDX_SW_ERROR, %rdi
  190. orq %rdi, %rax
  191. .Lseamcall_fail\@:
  192. .if \ret && \saved
  193. /* pop the unused structure pointer back to RSI */
  194. popq %rsi
  195. .endif
  196. jmp .Lout\@
  197. _ASM_EXTABLE_FAULT(.Lseamcall\@, .Lseamcall_trap\@)
  198. .endif /* \host */
  199. .endm