GNU Linux-libre 5.19-rc6-gnu
[releases.git] / arch / x86 / virt / vmx / tdx / tdxcall.S
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #include <asm/asm-offsets.h>
3 #include <asm/tdx.h>
4
5 /*
6  * TDCALL and SEAMCALL are supported in Binutils >= 2.36.
7  */
8 #define tdcall          .byte 0x66,0x0f,0x01,0xcc
9 #define seamcall        .byte 0x66,0x0f,0x01,0xcf
10
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 .macro TDX_MODULE_CALL host:req
21         /*
22          * R12 will be used as temporary storage for struct tdx_module_output
23          * pointer. Since R12-R15 registers are not used by TDCALL/SEAMCALL
24          * services supported by this function, it can be reused.
25          */
26
27         /* Callee saved, so preserve it */
28         push %r12
29
30         /*
31          * Push output pointer to stack.
32          * After the operation, it will be fetched into R12 register.
33          */
34         push %r9
35
36         /* Mangle function call ABI into TDCALL/SEAMCALL ABI: */
37         /* Move Leaf ID to RAX */
38         mov %rdi, %rax
39         /* Move input 4 to R9 */
40         mov %r8,  %r9
41         /* Move input 3 to R8 */
42         mov %rcx, %r8
43         /* Move input 1 to RCX */
44         mov %rsi, %rcx
45         /* Leave input param 2 in RDX */
46
47         .if \host
48         seamcall
49         /*
50          * SEAMCALL instruction is essentially a VMExit from VMX root
51          * mode to SEAM VMX root mode.  VMfailInvalid (CF=1) indicates
52          * that the targeted SEAM firmware is not loaded or disabled,
53          * or P-SEAMLDR is busy with another SEAMCALL.  %rax is not
54          * changed in this case.
55          *
56          * Set %rax to TDX_SEAMCALL_VMFAILINVALID for VMfailInvalid.
57          * This value will never be used as actual SEAMCALL error code as
58          * it is from the Reserved status code class.
59          */
60         jnc .Lno_vmfailinvalid
61         mov $TDX_SEAMCALL_VMFAILINVALID, %rax
62 .Lno_vmfailinvalid:
63
64         .else
65         tdcall
66         .endif
67
68         /*
69          * Fetch output pointer from stack to R12 (It is used
70          * as temporary storage)
71          */
72         pop %r12
73
74         /*
75          * Since this macro can be invoked with NULL as an output pointer,
76          * check if caller provided an output struct before storing output
77          * registers.
78          *
79          * Update output registers, even if the call failed (RAX != 0).
80          * Other registers may contain details of the failure.
81          */
82         test %r12, %r12
83         jz .Lno_output_struct
84
85         /* Copy result registers to output struct: */
86         movq %rcx, TDX_MODULE_rcx(%r12)
87         movq %rdx, TDX_MODULE_rdx(%r12)
88         movq %r8,  TDX_MODULE_r8(%r12)
89         movq %r9,  TDX_MODULE_r9(%r12)
90         movq %r10, TDX_MODULE_r10(%r12)
91         movq %r11, TDX_MODULE_r11(%r12)
92
93 .Lno_output_struct:
94         /* Restore the state of R12 register */
95         pop %r12
96 .endm