1 /* SPDX-License-Identifier: GPL-2.0 */
2 #include <asm/asm-offsets.h>
5 #include <asm/unwind_hints.h>
7 #include <linux/linkage.h>
8 #include <linux/bits.h>
9 #include <linux/errno.h>
11 #include "../../virt/vmx/tdx/tdxcall.S"
14 * Bitmasks of exposed registers (with VMM).
16 #define TDX_RDX BIT(2)
17 #define TDX_RBX BIT(3)
18 #define TDX_RSI BIT(6)
19 #define TDX_RDI BIT(7)
22 #define TDX_R10 BIT(10)
23 #define TDX_R11 BIT(11)
24 #define TDX_R12 BIT(12)
25 #define TDX_R13 BIT(13)
26 #define TDX_R14 BIT(14)
27 #define TDX_R15 BIT(15)
30 * These registers are clobbered to hold arguments for each
31 * TDVMCALL. They are safe to expose to the VMM.
32 * Each bit in this mask represents a register ID. Bit field
33 * details can be found in TDX GHCI specification, section
34 * titled "TDCALL [TDG.VP.VMCALL] leaf".
36 #define TDVMCALL_EXPOSE_REGS_MASK \
37 ( TDX_RDX | TDX_RBX | TDX_RSI | TDX_RDI | TDX_R8 | TDX_R9 | \
38 TDX_R10 | TDX_R11 | TDX_R12 | TDX_R13 | TDX_R14 | TDX_R15 )
41 * __tdx_module_call() - Used by TDX guests to request services from
42 * the TDX module (does not include VMM services) using TDCALL instruction.
44 * Transforms function call register arguments into the TDCALL register ABI.
45 * After TDCALL operation, TDX module output is saved in @out (if it is
46 * provided by the user).
48 *-------------------------------------------------------------------------
50 *-------------------------------------------------------------------------
53 * RAX - TDCALL Leaf number.
54 * RCX,RDX,R8-R9 - TDCALL Leaf specific input registers.
58 * RAX - TDCALL instruction error code.
59 * RCX,RDX,R8-R11 - TDCALL Leaf specific output registers.
61 *-------------------------------------------------------------------------
63 * __tdx_module_call() function ABI:
65 * @fn (RDI) - TDCALL Leaf ID, moved to RAX
66 * @rcx (RSI) - Input parameter 1, moved to RCX
67 * @rdx (RDX) - Input parameter 2, moved to RDX
68 * @r8 (RCX) - Input parameter 3, moved to R8
69 * @r9 (R8) - Input parameter 4, moved to R9
71 * @out (R9) - struct tdx_module_output pointer
72 * stored temporarily in R12 (not
73 * shared with the TDX module). It
76 * Return status of TDCALL via RAX.
78 SYM_FUNC_START(__tdx_module_call)
80 TDX_MODULE_CALL host=0
83 SYM_FUNC_END(__tdx_module_call)
86 * __tdx_hypercall() - Make hypercalls to a TDX VMM using TDVMCALL leaf
87 * of TDCALL instruction
89 * Transforms values in function call argument struct tdx_hypercall_args @args
90 * into the TDCALL register ABI. After TDCALL operation, VMM output is saved
93 *-------------------------------------------------------------------------
95 *-------------------------------------------------------------------------
99 * RAX - TDCALL instruction leaf number (0 - TDG.VP.VMCALL)
100 * RCX - BITMAP which controls which part of TD Guest GPR
101 * is passed as-is to the VMM and back.
102 * R10 - Set 0 to indicate TDCALL follows standard TDX ABI
103 * specification. Non zero value indicates vendor
105 * R11 - VMCALL sub function number
106 * RBX, RBP, RDI, RSI - Used to pass VMCALL sub function specific arguments.
107 * R8-R9, R12-R15 - Same as above.
111 * RAX - TDCALL instruction status (Not related to hypercall
113 * R10 - Hypercall output error code.
114 * R11-R15 - Hypercall sub function specific output values.
116 *-------------------------------------------------------------------------
118 * __tdx_hypercall() function ABI:
120 * @args (RDI) - struct tdx_hypercall_args for input and output
121 * @flags (RSI) - TDX_HCALL_* flags
123 * On successful completion, return the hypercall error code.
125 SYM_FUNC_START(__tdx_hypercall)
128 /* Save callee-saved GPRs as mandated by the x86_64 ABI */
135 /* Free RDI and RSI to be used as TDVMCALL arguments */
139 /* Copy hypercall registers from arg struct: */
140 movq TDX_HYPERCALL_r8(%rax), %r8
141 movq TDX_HYPERCALL_r9(%rax), %r9
142 movq TDX_HYPERCALL_r10(%rax), %r10
143 movq TDX_HYPERCALL_r11(%rax), %r11
144 movq TDX_HYPERCALL_r12(%rax), %r12
145 movq TDX_HYPERCALL_r13(%rax), %r13
146 movq TDX_HYPERCALL_r14(%rax), %r14
147 movq TDX_HYPERCALL_r15(%rax), %r15
148 movq TDX_HYPERCALL_rdi(%rax), %rdi
149 movq TDX_HYPERCALL_rsi(%rax), %rsi
150 movq TDX_HYPERCALL_rbx(%rax), %rbx
151 movq TDX_HYPERCALL_rdx(%rax), %rdx
155 /* Mangle function call ABI into TDCALL ABI: */
156 /* Set TDCALL leaf ID (TDVMCALL (0)) in RAX */
159 movl $TDVMCALL_EXPOSE_REGS_MASK, %ecx
162 * For the idle loop STI needs to be called directly before the TDCALL
163 * that enters idle (EXIT_REASON_HLT case). STI instruction enables
164 * interrupts only one instruction later. If there is a window between
165 * STI and the instruction that emulates the HALT state, there is a
166 * chance for interrupts to happen in this window, which can delay the
167 * HLT operation indefinitely. Since this is the not the desired
168 * result, conditionally call STI before TDCALL.
170 testq $TDX_HCALL_ISSUE_STI, 8(%rsp)
177 * RAX!=0 indicates a failure of the TDVMCALL mechanism itself and that
178 * something has gone horribly wrong with the TDX module.
180 * The return status of the hypercall operation is in a separate
181 * register (in R10). Hypercall errors are a part of normal operation
182 * and are handled by callers.
189 /* Copy hypercall result registers to arg struct if needed */
190 testq $TDX_HCALL_HAS_OUTPUT, (%rsp)
193 movq %r8, TDX_HYPERCALL_r8(%rax)
194 movq %r9, TDX_HYPERCALL_r9(%rax)
195 movq %r10, TDX_HYPERCALL_r10(%rax)
196 movq %r11, TDX_HYPERCALL_r11(%rax)
197 movq %r12, TDX_HYPERCALL_r12(%rax)
198 movq %r13, TDX_HYPERCALL_r13(%rax)
199 movq %r14, TDX_HYPERCALL_r14(%rax)
200 movq %r15, TDX_HYPERCALL_r15(%rax)
201 movq %rdi, TDX_HYPERCALL_rdi(%rax)
202 movq %rsi, TDX_HYPERCALL_rsi(%rax)
203 movq %rbx, TDX_HYPERCALL_rbx(%rax)
204 movq %rdx, TDX_HYPERCALL_rdx(%rax)
206 /* TDVMCALL leaf return code is in R10 */
210 * Zero out registers exposed to the VMM to avoid speculative execution
211 * with VMM-controlled values. This needs to include all registers
212 * present in TDVMCALL_EXPOSE_REGS_MASK, except RBX, and R12-R15 which
222 /* Remove TDX_HCALL_* flags from the stack */
225 /* Restore callee-saved GPRs as mandated by the x86_64 ABI */
236 call __tdx_hypercall_failed
237 /* __tdx_hypercall_failed never returns */
240 SYM_FUNC_END(__tdx_hypercall)