/* SPDX-License-Identifier: GPL-2.0 or MIT */ #ifndef _ASM_X86_VMWARE_H #define _ASM_X86_VMWARE_H #include <asm/cpufeatures.h> #include <asm/alternative.h> #include <linux/stringify.h> /* * VMware hypercall ABI. * * - Low bandwidth (LB) hypercalls (I/O port based, vmcall and vmmcall) * have up to 6 input and 6 output arguments passed and returned using * registers: %eax (arg0), %ebx (arg1), %ecx (arg2), %edx (arg3), * %esi (arg4), %edi (arg5). * The following input arguments must be initialized by the caller: * arg0 - VMWARE_HYPERVISOR_MAGIC * arg2 - Hypercall command * arg3 bits [15:0] - Port number, LB and direction flags * * - Low bandwidth TDX hypercalls (x86_64 only) are similar to LB * hypercalls. They also have up to 6 input and 6 output on registers * arguments, with different argument to register mapping: * %r12 (arg0), %rbx (arg1), %r13 (arg2), %rdx (arg3), * %rsi (arg4), %rdi (arg5). * * - High bandwidth (HB) hypercalls are I/O port based only. They have * up to 7 input and 7 output arguments passed and returned using * registers: %eax (arg0), %ebx (arg1), %ecx (arg2), %edx (arg3), * %esi (arg4), %edi (arg5), %ebp (arg6). * The following input arguments must be initialized by the caller: * arg0 - VMWARE_HYPERVISOR_MAGIC * arg1 - Hypercall command * arg3 bits [15:0] - Port number, HB and direction flags * * For compatibility purposes, x86_64 systems use only lower 32 bits * for input and output arguments. * * The hypercall definitions differ in the low word of the %edx (arg3) * in the following way: the old I/O port based interface uses the port * number to distinguish between high- and low bandwidth versions, and * uses IN/OUT instructions to define transfer direction. * * The new vmcall interface instead uses a set of flags to select * bandwidth mode and transfer direction. The flags should be loaded * into arg3 by any user and are automatically replaced by the port * number if the I/O port method is used. */ #define VMWARE_HYPERVISOR_HB … #define VMWARE_HYPERVISOR_OUT … #define VMWARE_HYPERVISOR_PORT … #define VMWARE_HYPERVISOR_PORT_HB … #define VMWARE_HYPERVISOR_MAGIC … #define VMWARE_CMD_GETVERSION … #define VMWARE_CMD_GETHZ … #define VMWARE_CMD_GETVCPU_INFO … #define VMWARE_CMD_STEALCLOCK … /* * Hypercall command mask: * bits [6:0] command, range [0, 127] * bits [19:16] sub-command, range [0, 15] */ #define VMWARE_CMD_MASK … #define CPUID_VMWARE_FEATURES_ECX_VMMCALL … #define CPUID_VMWARE_FEATURES_ECX_VMCALL … extern unsigned long vmware_hypercall_slow(unsigned long cmd, unsigned long in1, unsigned long in3, unsigned long in4, unsigned long in5, u32 *out1, u32 *out2, u32 *out3, u32 *out4, u32 *out5); #define VMWARE_TDX_VENDOR_LEAF … #define VMWARE_TDX_HCALL_FUNC … extern unsigned long vmware_tdx_hypercall(unsigned long cmd, unsigned long in1, unsigned long in3, unsigned long in4, unsigned long in5, u32 *out1, u32 *out2, u32 *out3, u32 *out4, u32 *out5); /* * The low bandwidth call. The low word of %edx is presumed to have OUT bit * set. The high word of %edx may contain input data from the caller. */ #define VMWARE_HYPERCALL … static inline unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1) { … } static inline unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1, u32 *out1, u32 *out2) { … } static inline unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1, u32 *out1, u32 *out2, u32 *out3) { … } static inline unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1, unsigned long in3, unsigned long in4, unsigned long in5, u32 *out2) { … } static inline unsigned long vmware_hypercall6(unsigned long cmd, unsigned long in1, unsigned long in3, u32 *out2, u32 *out3, u32 *out4, u32 *out5) { … } static inline unsigned long vmware_hypercall7(unsigned long cmd, unsigned long in1, unsigned long in3, unsigned long in4, unsigned long in5, u32 *out1, u32 *out2, u32 *out3) { … } #ifdef CONFIG_X86_64 #define VMW_BP_CONSTRAINT … #else #define VMW_BP_CONSTRAINT … #endif /* * High bandwidth calls are not supported on encrypted memory guests. * The caller should check cc_platform_has(CC_ATTR_MEM_ENCRYPT) and use * low bandwidth hypercall if memory encryption is set. * This assumption simplifies HB hypercall implementation to just I/O port * based approach without alternative patching. */ static inline unsigned long vmware_hypercall_hb_out(unsigned long cmd, unsigned long in2, unsigned long in3, unsigned long in4, unsigned long in5, unsigned long in6, u32 *out1) { … } static inline unsigned long vmware_hypercall_hb_in(unsigned long cmd, unsigned long in2, unsigned long in3, unsigned long in4, unsigned long in5, unsigned long in6, u32 *out1) { … } #undef VMW_BP_CONSTRAINT #undef VMWARE_HYPERCALL #endif