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

TOMOYO Linux Cross Reference
Linux/arch/x86/include/asm/vmware.h

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ 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.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 or MIT */
  2 #ifndef _ASM_X86_VMWARE_H
  3 #define _ASM_X86_VMWARE_H
  4 
  5 #include <asm/cpufeatures.h>
  6 #include <asm/alternative.h>
  7 #include <linux/stringify.h>
  8 
  9 /*
 10  * VMware hypercall ABI.
 11  *
 12  * - Low bandwidth (LB) hypercalls (I/O port based, vmcall and vmmcall)
 13  * have up to 6 input and 6 output arguments passed and returned using
 14  * registers: %eax (arg0), %ebx (arg1), %ecx (arg2), %edx (arg3),
 15  * %esi (arg4), %edi (arg5).
 16  * The following input arguments must be initialized by the caller:
 17  * arg0 - VMWARE_HYPERVISOR_MAGIC
 18  * arg2 - Hypercall command
 19  * arg3 bits [15:0] - Port number, LB and direction flags
 20  *
 21  * - Low bandwidth TDX hypercalls (x86_64 only) are similar to LB
 22  * hypercalls. They also have up to 6 input and 6 output on registers
 23  * arguments, with different argument to register mapping:
 24  * %r12 (arg0), %rbx (arg1), %r13 (arg2), %rdx (arg3),
 25  * %rsi (arg4), %rdi (arg5).
 26  *
 27  * - High bandwidth (HB) hypercalls are I/O port based only. They have
 28  * up to 7 input and 7 output arguments passed and returned using
 29  * registers: %eax (arg0), %ebx (arg1), %ecx (arg2), %edx (arg3),
 30  * %esi (arg4), %edi (arg5), %ebp (arg6).
 31  * The following input arguments must be initialized by the caller:
 32  * arg0 - VMWARE_HYPERVISOR_MAGIC
 33  * arg1 - Hypercall command
 34  * arg3 bits [15:0] - Port number, HB and direction flags
 35  *
 36  * For compatibility purposes, x86_64 systems use only lower 32 bits
 37  * for input and output arguments.
 38  *
 39  * The hypercall definitions differ in the low word of the %edx (arg3)
 40  * in the following way: the old I/O port based interface uses the port
 41  * number to distinguish between high- and low bandwidth versions, and
 42  * uses IN/OUT instructions to define transfer direction.
 43  *
 44  * The new vmcall interface instead uses a set of flags to select
 45  * bandwidth mode and transfer direction. The flags should be loaded
 46  * into arg3 by any user and are automatically replaced by the port
 47  * number if the I/O port method is used.
 48  */
 49 
 50 #define VMWARE_HYPERVISOR_HB            BIT(0)
 51 #define VMWARE_HYPERVISOR_OUT           BIT(1)
 52 
 53 #define VMWARE_HYPERVISOR_PORT          0x5658
 54 #define VMWARE_HYPERVISOR_PORT_HB       (VMWARE_HYPERVISOR_PORT | \
 55                                          VMWARE_HYPERVISOR_HB)
 56 
 57 #define VMWARE_HYPERVISOR_MAGIC         0x564d5868U
 58 
 59 #define VMWARE_CMD_GETVERSION           10
 60 #define VMWARE_CMD_GETHZ                45
 61 #define VMWARE_CMD_GETVCPU_INFO         68
 62 #define VMWARE_CMD_STEALCLOCK           91
 63 /*
 64  * Hypercall command mask:
 65  *   bits [6:0] command, range [0, 127]
 66  *   bits [19:16] sub-command, range [0, 15]
 67  */
 68 #define VMWARE_CMD_MASK                 0xf007fU
 69 
 70 #define CPUID_VMWARE_FEATURES_ECX_VMMCALL       BIT(0)
 71 #define CPUID_VMWARE_FEATURES_ECX_VMCALL        BIT(1)
 72 
 73 extern unsigned long vmware_hypercall_slow(unsigned long cmd,
 74                                            unsigned long in1, unsigned long in3,
 75                                            unsigned long in4, unsigned long in5,
 76                                            u32 *out1, u32 *out2, u32 *out3,
 77                                            u32 *out4, u32 *out5);
 78 
 79 #define VMWARE_TDX_VENDOR_LEAF 0x1af7e4909ULL
 80 #define VMWARE_TDX_HCALL_FUNC  1
 81 
 82 extern unsigned long vmware_tdx_hypercall(unsigned long cmd,
 83                                           unsigned long in1, unsigned long in3,
 84                                           unsigned long in4, unsigned long in5,
 85                                           u32 *out1, u32 *out2, u32 *out3,
 86                                           u32 *out4, u32 *out5);
 87 
 88 /*
 89  * The low bandwidth call. The low word of %edx is presumed to have OUT bit
 90  * set. The high word of %edx may contain input data from the caller.
 91  */
 92 #define VMWARE_HYPERCALL                                        \
 93         ALTERNATIVE_2("movw %[port], %%dx\n\t"                  \
 94                       "inl (%%dx), %%eax",                      \
 95                       "vmcall", X86_FEATURE_VMCALL,             \
 96                       "vmmcall", X86_FEATURE_VMW_VMMCALL)
 97 
 98 static inline
 99 unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1)
100 {
101         unsigned long out0;
102 
103         if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
104                 return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
105                                             NULL, NULL, NULL, NULL, NULL);
106 
107         if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
108                 return vmware_hypercall_slow(cmd, in1, 0, 0, 0,
109                                              NULL, NULL, NULL, NULL, NULL);
110 
111         asm_inline volatile (VMWARE_HYPERCALL
112                 : "=a" (out0)
113                 : [port] "i" (VMWARE_HYPERVISOR_PORT),
114                   "a" (VMWARE_HYPERVISOR_MAGIC),
115                   "b" (in1),
116                   "c" (cmd),
117                   "d" (0)
118                 : "cc", "memory");
119         return out0;
120 }
121 
122 static inline
123 unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1,
124                                 u32 *out1, u32 *out2)
125 {
126         unsigned long out0;
127 
128         if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
129                 return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
130                                             out1, out2, NULL, NULL, NULL);
131 
132         if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
133                 return vmware_hypercall_slow(cmd, in1, 0, 0, 0,
134                                              out1, out2, NULL, NULL, NULL);
135 
136         asm_inline volatile (VMWARE_HYPERCALL
137                 : "=a" (out0), "=b" (*out1), "=c" (*out2)
138                 : [port] "i" (VMWARE_HYPERVISOR_PORT),
139                   "a" (VMWARE_HYPERVISOR_MAGIC),
140                   "b" (in1),
141                   "c" (cmd),
142                   "d" (0)
143                 : "cc", "memory");
144         return out0;
145 }
146 
147 static inline
148 unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1,
149                                 u32 *out1, u32 *out2, u32 *out3)
150 {
151         unsigned long out0;
152 
153         if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
154                 return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
155                                             out1, out2, out3, NULL, NULL);
156 
157         if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
158                 return vmware_hypercall_slow(cmd, in1, 0, 0, 0,
159                                              out1, out2, out3, NULL, NULL);
160 
161         asm_inline volatile (VMWARE_HYPERCALL
162                 : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3)
163                 : [port] "i" (VMWARE_HYPERVISOR_PORT),
164                   "a" (VMWARE_HYPERVISOR_MAGIC),
165                   "b" (in1),
166                   "c" (cmd),
167                   "d" (0)
168                 : "cc", "memory");
169         return out0;
170 }
171 
172 static inline
173 unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1,
174                                 unsigned long in3, unsigned long in4,
175                                 unsigned long in5, u32 *out2)
176 {
177         unsigned long out0;
178 
179         if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
180                 return vmware_tdx_hypercall(cmd, in1, in3, in4, in5,
181                                             NULL, out2, NULL, NULL, NULL);
182 
183         if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
184                 return vmware_hypercall_slow(cmd, in1, in3, in4, in5,
185                                              NULL, out2, NULL, NULL, NULL);
186 
187         asm_inline volatile (VMWARE_HYPERCALL
188                 : "=a" (out0), "=c" (*out2)
189                 : [port] "i" (VMWARE_HYPERVISOR_PORT),
190                   "a" (VMWARE_HYPERVISOR_MAGIC),
191                   "b" (in1),
192                   "c" (cmd),
193                   "d" (in3),
194                   "S" (in4),
195                   "D" (in5)
196                 : "cc", "memory");
197         return out0;
198 }
199 
200 static inline
201 unsigned long vmware_hypercall6(unsigned long cmd, unsigned long in1,
202                                 unsigned long in3, u32 *out2,
203                                 u32 *out3, u32 *out4, u32 *out5)
204 {
205         unsigned long out0;
206 
207         if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
208                 return vmware_tdx_hypercall(cmd, in1, in3, 0, 0,
209                                             NULL, out2, out3, out4, out5);
210 
211         if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
212                 return vmware_hypercall_slow(cmd, in1, in3, 0, 0,
213                                              NULL, out2, out3, out4, out5);
214 
215         asm_inline volatile (VMWARE_HYPERCALL
216                 : "=a" (out0), "=c" (*out2), "=d" (*out3), "=S" (*out4),
217                   "=D" (*out5)
218                 : [port] "i" (VMWARE_HYPERVISOR_PORT),
219                   "a" (VMWARE_HYPERVISOR_MAGIC),
220                   "b" (in1),
221                   "c" (cmd),
222                   "d" (in3)
223                 : "cc", "memory");
224         return out0;
225 }
226 
227 static inline
228 unsigned long vmware_hypercall7(unsigned long cmd, unsigned long in1,
229                                 unsigned long in3, unsigned long in4,
230                                 unsigned long in5, u32 *out1,
231                                 u32 *out2, u32 *out3)
232 {
233         unsigned long out0;
234 
235         if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
236                 return vmware_tdx_hypercall(cmd, in1, in3, in4, in5,
237                                             out1, out2, out3, NULL, NULL);
238 
239         if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
240                 return vmware_hypercall_slow(cmd, in1, in3, in4, in5,
241                                              out1, out2, out3, NULL, NULL);
242 
243         asm_inline volatile (VMWARE_HYPERCALL
244                 : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3)
245                 : [port] "i" (VMWARE_HYPERVISOR_PORT),
246                   "a" (VMWARE_HYPERVISOR_MAGIC),
247                   "b" (in1),
248                   "c" (cmd),
249                   "d" (in3),
250                   "S" (in4),
251                   "D" (in5)
252                 : "cc", "memory");
253         return out0;
254 }
255 
256 #ifdef CONFIG_X86_64
257 #define VMW_BP_CONSTRAINT "r"
258 #else
259 #define VMW_BP_CONSTRAINT "m"
260 #endif
261 
262 /*
263  * High bandwidth calls are not supported on encrypted memory guests.
264  * The caller should check cc_platform_has(CC_ATTR_MEM_ENCRYPT) and use
265  * low bandwidth hypercall if memory encryption is set.
266  * This assumption simplifies HB hypercall implementation to just I/O port
267  * based approach without alternative patching.
268  */
269 static inline
270 unsigned long vmware_hypercall_hb_out(unsigned long cmd, unsigned long in2,
271                                       unsigned long in3, unsigned long in4,
272                                       unsigned long in5, unsigned long in6,
273                                       u32 *out1)
274 {
275         unsigned long out0;
276 
277         asm_inline volatile (
278                 UNWIND_HINT_SAVE
279                 "push %%" _ASM_BP "\n\t"
280                 UNWIND_HINT_UNDEFINED
281                 "mov %[in6], %%" _ASM_BP "\n\t"
282                 "rep outsb\n\t"
283                 "pop %%" _ASM_BP "\n\t"
284                 UNWIND_HINT_RESTORE
285                 : "=a" (out0), "=b" (*out1)
286                 : "a" (VMWARE_HYPERVISOR_MAGIC),
287                   "b" (cmd),
288                   "c" (in2),
289                   "d" (in3 | VMWARE_HYPERVISOR_PORT_HB),
290                   "S" (in4),
291                   "D" (in5),
292                   [in6] VMW_BP_CONSTRAINT (in6)
293                 : "cc", "memory");
294         return out0;
295 }
296 
297 static inline
298 unsigned long vmware_hypercall_hb_in(unsigned long cmd, unsigned long in2,
299                                      unsigned long in3, unsigned long in4,
300                                      unsigned long in5, unsigned long in6,
301                                      u32 *out1)
302 {
303         unsigned long out0;
304 
305         asm_inline volatile (
306                 UNWIND_HINT_SAVE
307                 "push %%" _ASM_BP "\n\t"
308                 UNWIND_HINT_UNDEFINED
309                 "mov %[in6], %%" _ASM_BP "\n\t"
310                 "rep insb\n\t"
311                 "pop %%" _ASM_BP "\n\t"
312                 UNWIND_HINT_RESTORE
313                 : "=a" (out0), "=b" (*out1)
314                 : "a" (VMWARE_HYPERVISOR_MAGIC),
315                   "b" (cmd),
316                   "c" (in2),
317                   "d" (in3 | VMWARE_HYPERVISOR_PORT_HB),
318                   "S" (in4),
319                   "D" (in5),
320                   [in6] VMW_BP_CONSTRAINT (in6)
321                 : "cc", "memory");
322         return out0;
323 }
324 #undef VMW_BP_CONSTRAINT
325 #undef VMWARE_HYPERCALL
326 
327 #endif
328 

~ [ 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