Merge branches 'acpi-battery', 'acpi-video' and 'acpi-misc'
[sfrench/cifs-2.6.git] / arch / x86 / coco / tdx / tdcall.S
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  */
72 SYM_FUNC_START(__tdx_module_call)
73         FRAME_BEGIN
74         TDX_MODULE_CALL host=0
75         FRAME_END
76         RET
77 SYM_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  */
119 SYM_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
205 SYM_FUNC_END(__tdx_hypercall)