~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/x86/virt/vmx/tdx/tdxcall.S

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 #include <asm/asm-offsets.h>
  3 #include <asm/frame.h>
  4 #include <asm/asm.h>
  5 #include <asm/tdx.h>
  6 
  7 /*
  8  * TDCALL and SEAMCALL are supported in Binutils >= 2.36.
  9  */
 10 #define tdcall          .byte 0x66,0x0f,0x01,0xcc
 11 #define seamcall        .byte 0x66,0x0f,0x01,0xcf
 12 
 13 /*
 14  * TDX_MODULE_CALL - common helper macro for both
 15  *                 TDCALL and SEAMCALL instructions.
 16  *
 17  * TDCALL   - used by TDX guests to make requests to the
 18  *            TDX module and hypercalls to the VMM.
 19  * SEAMCALL - used by TDX hosts to make requests to the
 20  *            TDX module.
 21  *
 22  *-------------------------------------------------------------------------
 23  * TDCALL/SEAMCALL ABI:
 24  *-------------------------------------------------------------------------
 25  * Input Registers:
 26  *
 27  * RAX                        - TDCALL/SEAMCALL Leaf number.
 28  * RCX,RDX,RDI,RSI,RBX,R8-R15 - TDCALL/SEAMCALL Leaf specific input registers.
 29  *
 30  * Output Registers:
 31  *
 32  * RAX                        - TDCALL/SEAMCALL instruction error code.
 33  * RCX,RDX,RDI,RSI,RBX,R8-R15 - TDCALL/SEAMCALL Leaf specific output registers.
 34  *
 35  *-------------------------------------------------------------------------
 36  *
 37  * So while the common core (RAX,RCX,RDX,R8-R11) fits nicely in the
 38  * callee-clobbered registers and even leaves RDI,RSI free to act as a
 39  * base pointer, some leafs (e.g., VP.ENTER) make a giant mess of things.
 40  *
 41  * For simplicity, assume that anything that needs the callee-saved regs
 42  * also tramples on RDI,RSI.  This isn't strictly true, see for example
 43  * TDH.EXPORT.MEM.
 44  */
 45 .macro TDX_MODULE_CALL host:req ret=0 saved=0
 46         FRAME_BEGIN
 47 
 48         /* Move Leaf ID to RAX */
 49         mov %rdi, %rax
 50 
 51         /* Move other input regs from 'struct tdx_module_args' */
 52         movq    TDX_MODULE_rcx(%rsi), %rcx
 53         movq    TDX_MODULE_rdx(%rsi), %rdx
 54         movq    TDX_MODULE_r8(%rsi),  %r8
 55         movq    TDX_MODULE_r9(%rsi),  %r9
 56         movq    TDX_MODULE_r10(%rsi), %r10
 57         movq    TDX_MODULE_r11(%rsi), %r11
 58 
 59 .if \saved
 60         /*
 61          * Move additional input regs from the structure.  For simplicity
 62          * assume that anything needs the callee-saved regs also tramples
 63          * on RDI/RSI (see VP.ENTER).
 64          */
 65         /* Save those callee-saved GPRs as mandated by the x86_64 ABI */
 66         pushq   %rbx
 67         pushq   %r12
 68         pushq   %r13
 69         pushq   %r14
 70         pushq   %r15
 71 
 72         movq    TDX_MODULE_r12(%rsi), %r12
 73         movq    TDX_MODULE_r13(%rsi), %r13
 74         movq    TDX_MODULE_r14(%rsi), %r14
 75         movq    TDX_MODULE_r15(%rsi), %r15
 76         movq    TDX_MODULE_rbx(%rsi), %rbx
 77 
 78 .if \ret
 79         /* Save the structure pointer as RSI is about to be clobbered */
 80         pushq   %rsi
 81 .endif
 82 
 83         movq    TDX_MODULE_rdi(%rsi), %rdi
 84         /* RSI needs to be done at last */
 85         movq    TDX_MODULE_rsi(%rsi), %rsi
 86 .endif  /* \saved */
 87 
 88 .if \host
 89 .Lseamcall\@:
 90         seamcall
 91         /*
 92          * SEAMCALL instruction is essentially a VMExit from VMX root
 93          * mode to SEAM VMX root mode.  VMfailInvalid (CF=1) indicates
 94          * that the targeted SEAM firmware is not loaded or disabled,
 95          * or P-SEAMLDR is busy with another SEAMCALL.  %rax is not
 96          * changed in this case.
 97          *
 98          * Set %rax to TDX_SEAMCALL_VMFAILINVALID for VMfailInvalid.
 99          * This value will never be used as actual SEAMCALL error code as
100          * it is from the Reserved status code class.
101          */
102         jc .Lseamcall_vmfailinvalid\@
103 .else
104         tdcall
105 .endif
106 
107 .if \ret
108 .if \saved
109         /*
110          * Restore the structure from stack to save the output registers
111          *
112          * In case of VP.ENTER returns due to TDVMCALL, all registers are
113          * valid thus no register can be used as spare to restore the
114          * structure from the stack (see "TDH.VP.ENTER Output Operands
115          * Definition on TDCALL(TDG.VP.VMCALL) Following a TD Entry").
116          * For this case, need to make one register as spare by saving it
117          * to the stack and then manually load the structure pointer to
118          * the spare register.
119          *
120          * Note for other TDCALLs/SEAMCALLs there are spare registers
121          * thus no need for such hack but just use this for all.
122          */
123         pushq   %rax            /* save the TDCALL/SEAMCALL return code */
124         movq    8(%rsp), %rax   /* restore the structure pointer */
125         movq    %rsi, TDX_MODULE_rsi(%rax)      /* save RSI */
126         popq    %rax            /* restore the return code */
127         popq    %rsi            /* pop the structure pointer */
128 
129         /* Copy additional output regs to the structure  */
130         movq %r12, TDX_MODULE_r12(%rsi)
131         movq %r13, TDX_MODULE_r13(%rsi)
132         movq %r14, TDX_MODULE_r14(%rsi)
133         movq %r15, TDX_MODULE_r15(%rsi)
134         movq %rbx, TDX_MODULE_rbx(%rsi)
135         movq %rdi, TDX_MODULE_rdi(%rsi)
136 .endif  /* \saved */
137 
138         /* Copy output registers to the structure */
139         movq %rcx, TDX_MODULE_rcx(%rsi)
140         movq %rdx, TDX_MODULE_rdx(%rsi)
141         movq %r8,  TDX_MODULE_r8(%rsi)
142         movq %r9,  TDX_MODULE_r9(%rsi)
143         movq %r10, TDX_MODULE_r10(%rsi)
144         movq %r11, TDX_MODULE_r11(%rsi)
145 .endif  /* \ret */
146 
147 .if \saved && \ret
148         /*
149          * Clear registers shared by guest for VP.VMCALL/VP.ENTER to prevent
150          * speculative use of guest's/VMM's values, including those are
151          * restored from the stack.
152          *
153          * See arch/x86/kvm/vmx/vmenter.S:
154          *
155          * In theory, a L1 cache miss when restoring register from stack
156          * could lead to speculative execution with guest's values.
157          *
158          * Note: RBP/RSP are not used as shared register.  RSI has been
159          * restored already.
160          *
161          * XOR is cheap, thus unconditionally do for all leafs.
162          */
163         xorl %ecx,  %ecx
164         xorl %edx,  %edx
165         xorl %r8d,  %r8d
166         xorl %r9d,  %r9d
167         xorl %r10d, %r10d
168         xorl %r11d, %r11d
169         xorl %r12d, %r12d
170         xorl %r13d, %r13d
171         xorl %r14d, %r14d
172         xorl %r15d, %r15d
173         xorl %ebx,  %ebx
174         xorl %edi,  %edi
175 .endif  /* \ret && \host */
176 
177 .if \host
178 .Lout\@:
179 .endif
180 
181 .if \saved
182         /* Restore callee-saved GPRs as mandated by the x86_64 ABI */
183         popq    %r15
184         popq    %r14
185         popq    %r13
186         popq    %r12
187         popq    %rbx
188 .endif  /* \saved */
189 
190         FRAME_END
191         RET
192 
193 .if \host
194 .Lseamcall_vmfailinvalid\@:
195         mov $TDX_SEAMCALL_VMFAILINVALID, %rax
196         jmp .Lseamcall_fail\@
197 
198 .Lseamcall_trap\@:
199         /*
200          * SEAMCALL caused #GP or #UD.  By reaching here RAX contains
201          * the trap number.  Convert the trap number to the TDX error
202          * code by setting TDX_SW_ERROR to the high 32-bits of RAX.
203          *
204          * Note cannot OR TDX_SW_ERROR directly to RAX as OR instruction
205          * only accepts 32-bit immediate at most.
206          */
207         movq $TDX_SW_ERROR, %rdi
208         orq  %rdi, %rax
209 
210 .Lseamcall_fail\@:
211 .if \ret && \saved
212         /* pop the unused structure pointer back to RSI */
213         popq %rsi
214 .endif
215         jmp .Lout\@
216 
217         _ASM_EXTABLE_FAULT(.Lseamcall\@, .Lseamcall_trap\@)
218 .endif  /* \host */
219 
220 .endm

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php