tdcall.S 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #include <asm/asm-offsets.h>
  3. #include <asm/asm.h>
  4. #include <asm/frame.h>
  5. #include <asm/unwind_hints.h>
  6. #include <linux/linkage.h>
  7. #include <linux/bits.h>
  8. #include <linux/errno.h>
  9. #include "../../virt/vmx/tdx/tdxcall.S"
  10. /*
  11. * Bitmasks of exposed registers (with VMM).
  12. */
  13. #define TDX_R10 BIT(10)
  14. #define TDX_R11 BIT(11)
  15. #define TDX_R12 BIT(12)
  16. #define TDX_R13 BIT(13)
  17. #define TDX_R14 BIT(14)
  18. #define TDX_R15 BIT(15)
  19. /*
  20. * These registers are clobbered to hold arguments for each
  21. * TDVMCALL. They are safe to expose to the VMM.
  22. * Each bit in this mask represents a register ID. Bit field
  23. * details can be found in TDX GHCI specification, section
  24. * titled "TDCALL [TDG.VP.VMCALL] leaf".
  25. */
  26. #define TDVMCALL_EXPOSE_REGS_MASK ( TDX_R10 | TDX_R11 | \
  27. TDX_R12 | TDX_R13 | \
  28. TDX_R14 | TDX_R15 )
  29. /*
  30. * __tdx_module_call() - Used by TDX guests to request services from
  31. * the TDX module (does not include VMM services) using TDCALL instruction.
  32. *
  33. * Transforms function call register arguments into the TDCALL register ABI.
  34. * After TDCALL operation, TDX module output is saved in @out (if it is
  35. * provided by the user).
  36. *
  37. *-------------------------------------------------------------------------
  38. * TDCALL ABI:
  39. *-------------------------------------------------------------------------
  40. * Input Registers:
  41. *
  42. * RAX - TDCALL Leaf number.
  43. * RCX,RDX,R8-R9 - TDCALL Leaf specific input registers.
  44. *
  45. * Output Registers:
  46. *
  47. * RAX - TDCALL instruction error code.
  48. * RCX,RDX,R8-R11 - TDCALL Leaf specific output registers.
  49. *
  50. *-------------------------------------------------------------------------
  51. *
  52. * __tdx_module_call() function ABI:
  53. *
  54. * @fn (RDI) - TDCALL Leaf ID, moved to RAX
  55. * @rcx (RSI) - Input parameter 1, moved to RCX
  56. * @rdx (RDX) - Input parameter 2, moved to RDX
  57. * @r8 (RCX) - Input parameter 3, moved to R8
  58. * @r9 (R8) - Input parameter 4, moved to R9
  59. *
  60. * @out (R9) - struct tdx_module_output pointer
  61. * stored temporarily in R12 (not
  62. * shared with the TDX module). It
  63. * can be NULL.
  64. *
  65. * Return status of TDCALL via RAX.
  66. */
  67. SYM_FUNC_START(__tdx_module_call)
  68. FRAME_BEGIN
  69. TDX_MODULE_CALL host=0
  70. FRAME_END
  71. RET
  72. SYM_FUNC_END(__tdx_module_call)
  73. /*
  74. * __tdx_hypercall() - Make hypercalls to a TDX VMM using TDVMCALL leaf
  75. * of TDCALL instruction
  76. *
  77. * Transforms values in function call argument struct tdx_hypercall_args @args
  78. * into the TDCALL register ABI. After TDCALL operation, VMM output is saved
  79. * back in @args.
  80. *
  81. *-------------------------------------------------------------------------
  82. * TD VMCALL ABI:
  83. *-------------------------------------------------------------------------
  84. *
  85. * Input Registers:
  86. *
  87. * RAX - TDCALL instruction leaf number (0 - TDG.VP.VMCALL)
  88. * RCX - BITMAP which controls which part of TD Guest GPR
  89. * is passed as-is to the VMM and back.
  90. * R10 - Set 0 to indicate TDCALL follows standard TDX ABI
  91. * specification. Non zero value indicates vendor
  92. * specific ABI.
  93. * R11 - VMCALL sub function number
  94. * RBX, RBP, RDI, RSI - Used to pass VMCALL sub function specific arguments.
  95. * R8-R9, R12-R15 - Same as above.
  96. *
  97. * Output Registers:
  98. *
  99. * RAX - TDCALL instruction status (Not related to hypercall
  100. * output).
  101. * R10 - Hypercall output error code.
  102. * R11-R15 - Hypercall sub function specific output values.
  103. *
  104. *-------------------------------------------------------------------------
  105. *
  106. * __tdx_hypercall() function ABI:
  107. *
  108. * @args (RDI) - struct tdx_hypercall_args for input and output
  109. * @flags (RSI) - TDX_HCALL_* flags
  110. *
  111. * On successful completion, return the hypercall error code.
  112. */
  113. SYM_FUNC_START(__tdx_hypercall)
  114. FRAME_BEGIN
  115. /* Save callee-saved GPRs as mandated by the x86_64 ABI */
  116. push %r15
  117. push %r14
  118. push %r13
  119. push %r12
  120. /* Mangle function call ABI into TDCALL ABI: */
  121. /* Set TDCALL leaf ID (TDVMCALL (0)) in RAX */
  122. xor %eax, %eax
  123. /* Copy hypercall registers from arg struct: */
  124. movq TDX_HYPERCALL_r10(%rdi), %r10
  125. movq TDX_HYPERCALL_r11(%rdi), %r11
  126. movq TDX_HYPERCALL_r12(%rdi), %r12
  127. movq TDX_HYPERCALL_r13(%rdi), %r13
  128. movq TDX_HYPERCALL_r14(%rdi), %r14
  129. movq TDX_HYPERCALL_r15(%rdi), %r15
  130. movl $TDVMCALL_EXPOSE_REGS_MASK, %ecx
  131. /*
  132. * For the idle loop STI needs to be called directly before the TDCALL
  133. * that enters idle (EXIT_REASON_HLT case). STI instruction enables
  134. * interrupts only one instruction later. If there is a window between
  135. * STI and the instruction that emulates the HALT state, there is a
  136. * chance for interrupts to happen in this window, which can delay the
  137. * HLT operation indefinitely. Since this is the not the desired
  138. * result, conditionally call STI before TDCALL.
  139. */
  140. testq $TDX_HCALL_ISSUE_STI, %rsi
  141. jz .Lskip_sti
  142. sti
  143. .Lskip_sti:
  144. tdcall
  145. /*
  146. * RAX==0 indicates a failure of the TDVMCALL mechanism itself and that
  147. * something has gone horribly wrong with the TDX module.
  148. *
  149. * The return status of the hypercall operation is in a separate
  150. * register (in R10). Hypercall errors are a part of normal operation
  151. * and are handled by callers.
  152. */
  153. testq %rax, %rax
  154. jne .Lpanic
  155. /* TDVMCALL leaf return code is in R10 */
  156. movq %r10, %rax
  157. /* Copy hypercall result registers to arg struct if needed */
  158. testq $TDX_HCALL_HAS_OUTPUT, %rsi
  159. jz .Lout
  160. movq %r10, TDX_HYPERCALL_r10(%rdi)
  161. movq %r11, TDX_HYPERCALL_r11(%rdi)
  162. movq %r12, TDX_HYPERCALL_r12(%rdi)
  163. movq %r13, TDX_HYPERCALL_r13(%rdi)
  164. movq %r14, TDX_HYPERCALL_r14(%rdi)
  165. movq %r15, TDX_HYPERCALL_r15(%rdi)
  166. .Lout:
  167. /*
  168. * Zero out registers exposed to the VMM to avoid speculative execution
  169. * with VMM-controlled values. This needs to include all registers
  170. * present in TDVMCALL_EXPOSE_REGS_MASK (except R12-R15). R12-R15
  171. * context will be restored.
  172. */
  173. xor %r10d, %r10d
  174. xor %r11d, %r11d
  175. /* Restore callee-saved GPRs as mandated by the x86_64 ABI */
  176. pop %r12
  177. pop %r13
  178. pop %r14
  179. pop %r15
  180. FRAME_END
  181. RET
  182. .Lpanic:
  183. call __tdx_hypercall_failed
  184. /* __tdx_hypercall_failed never returns */
  185. REACHABLE
  186. jmp .Lpanic
  187. SYM_FUNC_END(__tdx_hypercall)