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