xref: /linux/arch/x86/kvm/vmx/vmx_ops.h (revision 4f9786035f9e519db41375818e1d0b5f20da2f10)
189b0c9f5SSean Christopherson /* SPDX-License-Identifier: GPL-2.0 */
289b0c9f5SSean Christopherson #ifndef __KVM_X86_VMX_INSN_H
389b0c9f5SSean Christopherson #define __KVM_X86_VMX_INSN_H
489b0c9f5SSean Christopherson 
589b0c9f5SSean Christopherson #include <linux/nospec.h>
689b0c9f5SSean Christopherson 
789b0c9f5SSean Christopherson #include <asm/vmx.h>
889b0c9f5SSean Christopherson 
950a82b0eSVitaly Kuznetsov #include "vmx_onhyperv.h"
1089b0c9f5SSean Christopherson #include "vmcs.h"
1107853adcSJosh Poimboeuf #include "../x86.h"
1289b0c9f5SSean Christopherson 
13c20d403fSSean Christopherson void vmread_error(unsigned long field);
1452a9fcbcSSean Christopherson void vmwrite_error(unsigned long field, unsigned long value);
1552a9fcbcSSean Christopherson void vmclear_error(struct vmcs *vmcs, u64 phys_addr);
1652a9fcbcSSean Christopherson void vmptrld_error(struct vmcs *vmcs, u64 phys_addr);
1752a9fcbcSSean Christopherson void invvpid_error(unsigned long ext, u16 vpid, gva_t gva);
18bc17fccbSYan Zhao void invept_error(unsigned long ext, u64 eptp);
1952a9fcbcSSean Christopherson 
200b5e7a16SSean Christopherson #ifndef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
210b5e7a16SSean Christopherson /*
220b5e7a16SSean Christopherson  * The VMREAD error trampoline _always_ uses the stack to pass parameters, even
230b5e7a16SSean Christopherson  * for 64-bit targets.  Preserving all registers allows the VMREAD inline asm
240b5e7a16SSean Christopherson  * blob to avoid clobbering GPRs, which in turn allows the compiler to better
250b5e7a16SSean Christopherson  * optimize sequences of VMREADs.
260b5e7a16SSean Christopherson  *
270b5e7a16SSean Christopherson  * Declare the trampoline as an opaque label as it's not safe to call from C
280b5e7a16SSean Christopherson  * code; there is no way to tell the compiler to pass params on the stack for
290b5e7a16SSean Christopherson  * 64-bit targets.
300b5e7a16SSean Christopherson  *
310b5e7a16SSean Christopherson  * void vmread_error_trampoline(unsigned long field, bool fault);
320b5e7a16SSean Christopherson  */
330b5e7a16SSean Christopherson extern unsigned long vmread_error_trampoline;
34c20d403fSSean Christopherson 
35c20d403fSSean Christopherson /*
36c20d403fSSean Christopherson  * The second VMREAD error trampoline, called from the assembly trampoline,
37c20d403fSSean Christopherson  * exists primarily to enable instrumentation for the VM-Fail path.
38c20d403fSSean Christopherson  */
39c20d403fSSean Christopherson void vmread_error_trampoline2(unsigned long field, bool fault);
40c20d403fSSean Christopherson 
410b5e7a16SSean Christopherson #endif
420b5e7a16SSean Christopherson 
vmcs_check16(unsigned long field)4389b0c9f5SSean Christopherson static __always_inline void vmcs_check16(unsigned long field)
4489b0c9f5SSean Christopherson {
4589b0c9f5SSean Christopherson 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2000,
4689b0c9f5SSean Christopherson 			 "16-bit accessor invalid for 64-bit field");
4789b0c9f5SSean Christopherson 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2001,
4889b0c9f5SSean Christopherson 			 "16-bit accessor invalid for 64-bit high field");
4989b0c9f5SSean Christopherson 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x4000,
50caf22c6dSQiang Liu 			 "16-bit accessor invalid for 32-bit field");
5189b0c9f5SSean Christopherson 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x6000,
5289b0c9f5SSean Christopherson 			 "16-bit accessor invalid for natural width field");
5389b0c9f5SSean Christopherson }
5489b0c9f5SSean Christopherson 
vmcs_check32(unsigned long field)5589b0c9f5SSean Christopherson static __always_inline void vmcs_check32(unsigned long field)
5689b0c9f5SSean Christopherson {
5789b0c9f5SSean Christopherson 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0,
5889b0c9f5SSean Christopherson 			 "32-bit accessor invalid for 16-bit field");
59870c575aSHaiwei Li 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2000,
60870c575aSHaiwei Li 			 "32-bit accessor invalid for 64-bit field");
61870c575aSHaiwei Li 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2001,
62870c575aSHaiwei Li 			 "32-bit accessor invalid for 64-bit high field");
6389b0c9f5SSean Christopherson 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x6000,
6489b0c9f5SSean Christopherson 			 "32-bit accessor invalid for natural width field");
6589b0c9f5SSean Christopherson }
6689b0c9f5SSean Christopherson 
vmcs_check64(unsigned long field)6789b0c9f5SSean Christopherson static __always_inline void vmcs_check64(unsigned long field)
6889b0c9f5SSean Christopherson {
6989b0c9f5SSean Christopherson 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0,
7089b0c9f5SSean Christopherson 			 "64-bit accessor invalid for 16-bit field");
7189b0c9f5SSean Christopherson 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2001,
7289b0c9f5SSean Christopherson 			 "64-bit accessor invalid for 64-bit high field");
7389b0c9f5SSean Christopherson 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x4000,
7489b0c9f5SSean Christopherson 			 "64-bit accessor invalid for 32-bit field");
7589b0c9f5SSean Christopherson 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x6000,
7689b0c9f5SSean Christopherson 			 "64-bit accessor invalid for natural width field");
7789b0c9f5SSean Christopherson }
7889b0c9f5SSean Christopherson 
vmcs_checkl(unsigned long field)7989b0c9f5SSean Christopherson static __always_inline void vmcs_checkl(unsigned long field)
8089b0c9f5SSean Christopherson {
8189b0c9f5SSean Christopherson 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0,
8289b0c9f5SSean Christopherson 			 "Natural width accessor invalid for 16-bit field");
8389b0c9f5SSean Christopherson 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2000,
8489b0c9f5SSean Christopherson 			 "Natural width accessor invalid for 64-bit field");
8589b0c9f5SSean Christopherson 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2001,
8689b0c9f5SSean Christopherson 			 "Natural width accessor invalid for 64-bit high field");
8789b0c9f5SSean Christopherson 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x4000,
8889b0c9f5SSean Christopherson 			 "Natural width accessor invalid for 32-bit field");
8989b0c9f5SSean Christopherson }
9089b0c9f5SSean Christopherson 
__vmcs_readl(unsigned long field)9189b0c9f5SSean Christopherson static __always_inline unsigned long __vmcs_readl(unsigned long field)
9289b0c9f5SSean Christopherson {
9389b0c9f5SSean Christopherson 	unsigned long value;
9489b0c9f5SSean Christopherson 
95907d1393SPeter Zijlstra #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
96907d1393SPeter Zijlstra 
974356e9f8SLinus Torvalds 	asm_goto_output("1: vmread %[field], %[output]\n\t"
98907d1393SPeter Zijlstra 			  "jna %l[do_fail]\n\t"
99907d1393SPeter Zijlstra 
100907d1393SPeter Zijlstra 			  _ASM_EXTABLE(1b, %l[do_exception])
101907d1393SPeter Zijlstra 
102907d1393SPeter Zijlstra 			  : [output] "=r" (value)
103907d1393SPeter Zijlstra 			  : [field] "r" (field)
104907d1393SPeter Zijlstra 			  : "cc"
105907d1393SPeter Zijlstra 			  : do_fail, do_exception);
106907d1393SPeter Zijlstra 
107907d1393SPeter Zijlstra 	return value;
108907d1393SPeter Zijlstra 
109907d1393SPeter Zijlstra do_fail:
1108578f596SSean Christopherson 	instrumentation_begin();
111a062dad7SSean Christopherson 	vmread_error(field);
1128578f596SSean Christopherson 	instrumentation_end();
113907d1393SPeter Zijlstra 	return 0;
114907d1393SPeter Zijlstra 
115907d1393SPeter Zijlstra do_exception:
116907d1393SPeter Zijlstra 	kvm_spurious_fault();
117907d1393SPeter Zijlstra 	return 0;
118907d1393SPeter Zijlstra 
119907d1393SPeter Zijlstra #else /* !CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
120907d1393SPeter Zijlstra 
121*e1c49eaeSJosh Poimboeuf 	asm volatile("1: vmread %[field], %[output]\n\t"
1226e202097SSean Christopherson 		     ".byte 0x3e\n\t" /* branch taken hint */
1236e202097SSean Christopherson 		     "ja 3f\n\t"
124842f4be9SSean Christopherson 
125842f4be9SSean Christopherson 		     /*
126842f4be9SSean Christopherson 		      * VMREAD failed.  Push '0' for @fault, push the failing
127842f4be9SSean Christopherson 		      * @field, and bounce through the trampoline to preserve
128842f4be9SSean Christopherson 		      * volatile registers.
129842f4be9SSean Christopherson 		      */
130*e1c49eaeSJosh Poimboeuf 		     "xorl %k[output], %k[output]\n\t"
1313e8ea780SPeter Zijlstra 		     "2:\n\t"
132*e1c49eaeSJosh Poimboeuf 		     "push %[output]\n\t"
133*e1c49eaeSJosh Poimboeuf 		     "push %[field]\n\t"
1343e8ea780SPeter Zijlstra 		     "call vmread_error_trampoline\n\t"
135842f4be9SSean Christopherson 
136842f4be9SSean Christopherson 		     /*
137842f4be9SSean Christopherson 		      * Unwind the stack.  Note, the trampoline zeros out the
138842f4be9SSean Christopherson 		      * memory for @fault so that the result is '0' on error.
139842f4be9SSean Christopherson 		      */
140*e1c49eaeSJosh Poimboeuf 		     "pop %[field]\n\t"
141*e1c49eaeSJosh Poimboeuf 		     "pop %[output]\n\t"
1426e202097SSean Christopherson 		     "3:\n\t"
1436e202097SSean Christopherson 
144842f4be9SSean Christopherson 		     /* VMREAD faulted.  As above, except push '1' for @fault. */
145*e1c49eaeSJosh Poimboeuf 		     _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_ONE_REG, %[output])
1463e8ea780SPeter Zijlstra 
147*e1c49eaeSJosh Poimboeuf 		     : ASM_CALL_CONSTRAINT, [output] "=&r" (value)
148*e1c49eaeSJosh Poimboeuf 		     : [field] "r" (field)
149*e1c49eaeSJosh Poimboeuf 		     : "cc");
15089b0c9f5SSean Christopherson 	return value;
151907d1393SPeter Zijlstra 
152907d1393SPeter Zijlstra #endif /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
15389b0c9f5SSean Christopherson }
15489b0c9f5SSean Christopherson 
vmcs_read16(unsigned long field)15589b0c9f5SSean Christopherson static __always_inline u16 vmcs_read16(unsigned long field)
15689b0c9f5SSean Christopherson {
15789b0c9f5SSean Christopherson 	vmcs_check16(field);
15819f10315SSean Christopherson 	if (kvm_is_using_evmcs())
15989b0c9f5SSean Christopherson 		return evmcs_read16(field);
16089b0c9f5SSean Christopherson 	return __vmcs_readl(field);
16189b0c9f5SSean Christopherson }
16289b0c9f5SSean Christopherson 
vmcs_read32(unsigned long field)16389b0c9f5SSean Christopherson static __always_inline u32 vmcs_read32(unsigned long field)
16489b0c9f5SSean Christopherson {
16589b0c9f5SSean Christopherson 	vmcs_check32(field);
16619f10315SSean Christopherson 	if (kvm_is_using_evmcs())
16789b0c9f5SSean Christopherson 		return evmcs_read32(field);
16889b0c9f5SSean Christopherson 	return __vmcs_readl(field);
16989b0c9f5SSean Christopherson }
17089b0c9f5SSean Christopherson 
vmcs_read64(unsigned long field)17189b0c9f5SSean Christopherson static __always_inline u64 vmcs_read64(unsigned long field)
17289b0c9f5SSean Christopherson {
17389b0c9f5SSean Christopherson 	vmcs_check64(field);
17419f10315SSean Christopherson 	if (kvm_is_using_evmcs())
17589b0c9f5SSean Christopherson 		return evmcs_read64(field);
17689b0c9f5SSean Christopherson #ifdef CONFIG_X86_64
17789b0c9f5SSean Christopherson 	return __vmcs_readl(field);
17889b0c9f5SSean Christopherson #else
17989b0c9f5SSean Christopherson 	return __vmcs_readl(field) | ((u64)__vmcs_readl(field+1) << 32);
18089b0c9f5SSean Christopherson #endif
18189b0c9f5SSean Christopherson }
18289b0c9f5SSean Christopherson 
vmcs_readl(unsigned long field)18389b0c9f5SSean Christopherson static __always_inline unsigned long vmcs_readl(unsigned long field)
18489b0c9f5SSean Christopherson {
18589b0c9f5SSean Christopherson 	vmcs_checkl(field);
18619f10315SSean Christopherson 	if (kvm_is_using_evmcs())
18789b0c9f5SSean Christopherson 		return evmcs_read64(field);
18889b0c9f5SSean Christopherson 	return __vmcs_readl(field);
18989b0c9f5SSean Christopherson }
19089b0c9f5SSean Christopherson 
19152a9fcbcSSean Christopherson #define vmx_asm1(insn, op1, error_args...)				\
19252a9fcbcSSean Christopherson do {									\
1934356e9f8SLinus Torvalds 	asm goto("1: " __stringify(insn) " %0\n\t"			\
19452a9fcbcSSean Christopherson 			  ".byte 0x2e\n\t" /* branch not taken hint */	\
19552a9fcbcSSean Christopherson 			  "jna %l[error]\n\t"				\
19652a9fcbcSSean Christopherson 			  _ASM_EXTABLE(1b, %l[fault])			\
19752a9fcbcSSean Christopherson 			  : : op1 : "cc" : error, fault);		\
19852a9fcbcSSean Christopherson 	return;								\
19952a9fcbcSSean Christopherson error:									\
2003ebccdf3SThomas Gleixner 	instrumentation_begin();					\
20152a9fcbcSSean Christopherson 	insn##_error(error_args);					\
2023ebccdf3SThomas Gleixner 	instrumentation_end();						\
20352a9fcbcSSean Christopherson 	return;								\
20452a9fcbcSSean Christopherson fault:									\
20552a9fcbcSSean Christopherson 	kvm_spurious_fault();						\
20652a9fcbcSSean Christopherson } while (0)
20752a9fcbcSSean Christopherson 
20852a9fcbcSSean Christopherson #define vmx_asm2(insn, op1, op2, error_args...)				\
20952a9fcbcSSean Christopherson do {									\
2104356e9f8SLinus Torvalds 	asm goto("1: "  __stringify(insn) " %1, %0\n\t"			\
21152a9fcbcSSean Christopherson 			  ".byte 0x2e\n\t" /* branch not taken hint */	\
21252a9fcbcSSean Christopherson 			  "jna %l[error]\n\t"				\
21352a9fcbcSSean Christopherson 			  _ASM_EXTABLE(1b, %l[fault])			\
21452a9fcbcSSean Christopherson 			  : : op1, op2 : "cc" : error, fault);		\
21552a9fcbcSSean Christopherson 	return;								\
21652a9fcbcSSean Christopherson error:									\
2173ebccdf3SThomas Gleixner 	instrumentation_begin();					\
21852a9fcbcSSean Christopherson 	insn##_error(error_args);					\
2193ebccdf3SThomas Gleixner 	instrumentation_end();						\
22052a9fcbcSSean Christopherson 	return;								\
22152a9fcbcSSean Christopherson fault:									\
22252a9fcbcSSean Christopherson 	kvm_spurious_fault();						\
22352a9fcbcSSean Christopherson } while (0)
22489b0c9f5SSean Christopherson 
__vmcs_writel(unsigned long field,unsigned long value)22589b0c9f5SSean Christopherson static __always_inline void __vmcs_writel(unsigned long field, unsigned long value)
22689b0c9f5SSean Christopherson {
22752a9fcbcSSean Christopherson 	vmx_asm2(vmwrite, "r"(field), "rm"(value), field, value);
22889b0c9f5SSean Christopherson }
22989b0c9f5SSean Christopherson 
vmcs_write16(unsigned long field,u16 value)23089b0c9f5SSean Christopherson static __always_inline void vmcs_write16(unsigned long field, u16 value)
23189b0c9f5SSean Christopherson {
23289b0c9f5SSean Christopherson 	vmcs_check16(field);
23319f10315SSean Christopherson 	if (kvm_is_using_evmcs())
23489b0c9f5SSean Christopherson 		return evmcs_write16(field, value);
23589b0c9f5SSean Christopherson 
23689b0c9f5SSean Christopherson 	__vmcs_writel(field, value);
23789b0c9f5SSean Christopherson }
23889b0c9f5SSean Christopherson 
vmcs_write32(unsigned long field,u32 value)23989b0c9f5SSean Christopherson static __always_inline void vmcs_write32(unsigned long field, u32 value)
24089b0c9f5SSean Christopherson {
24189b0c9f5SSean Christopherson 	vmcs_check32(field);
24219f10315SSean Christopherson 	if (kvm_is_using_evmcs())
24389b0c9f5SSean Christopherson 		return evmcs_write32(field, value);
24489b0c9f5SSean Christopherson 
24589b0c9f5SSean Christopherson 	__vmcs_writel(field, value);
24689b0c9f5SSean Christopherson }
24789b0c9f5SSean Christopherson 
vmcs_write64(unsigned long field,u64 value)24889b0c9f5SSean Christopherson static __always_inline void vmcs_write64(unsigned long field, u64 value)
24989b0c9f5SSean Christopherson {
25089b0c9f5SSean Christopherson 	vmcs_check64(field);
25119f10315SSean Christopherson 	if (kvm_is_using_evmcs())
25289b0c9f5SSean Christopherson 		return evmcs_write64(field, value);
25389b0c9f5SSean Christopherson 
25489b0c9f5SSean Christopherson 	__vmcs_writel(field, value);
25589b0c9f5SSean Christopherson #ifndef CONFIG_X86_64
25689b0c9f5SSean Christopherson 	__vmcs_writel(field+1, value >> 32);
25789b0c9f5SSean Christopherson #endif
25889b0c9f5SSean Christopherson }
25989b0c9f5SSean Christopherson 
vmcs_writel(unsigned long field,unsigned long value)26089b0c9f5SSean Christopherson static __always_inline void vmcs_writel(unsigned long field, unsigned long value)
26189b0c9f5SSean Christopherson {
26289b0c9f5SSean Christopherson 	vmcs_checkl(field);
26319f10315SSean Christopherson 	if (kvm_is_using_evmcs())
26489b0c9f5SSean Christopherson 		return evmcs_write64(field, value);
26589b0c9f5SSean Christopherson 
26689b0c9f5SSean Christopherson 	__vmcs_writel(field, value);
26789b0c9f5SSean Christopherson }
26889b0c9f5SSean Christopherson 
vmcs_clear_bits(unsigned long field,u32 mask)26989b0c9f5SSean Christopherson static __always_inline void vmcs_clear_bits(unsigned long field, u32 mask)
27089b0c9f5SSean Christopherson {
27189b0c9f5SSean Christopherson 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x2000,
27289b0c9f5SSean Christopherson 			 "vmcs_clear_bits does not support 64-bit fields");
27319f10315SSean Christopherson 	if (kvm_is_using_evmcs())
27489b0c9f5SSean Christopherson 		return evmcs_write32(field, evmcs_read32(field) & ~mask);
27589b0c9f5SSean Christopherson 
27689b0c9f5SSean Christopherson 	__vmcs_writel(field, __vmcs_readl(field) & ~mask);
27789b0c9f5SSean Christopherson }
27889b0c9f5SSean Christopherson 
vmcs_set_bits(unsigned long field,u32 mask)27989b0c9f5SSean Christopherson static __always_inline void vmcs_set_bits(unsigned long field, u32 mask)
28089b0c9f5SSean Christopherson {
28189b0c9f5SSean Christopherson 	BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x2000,
28289b0c9f5SSean Christopherson 			 "vmcs_set_bits does not support 64-bit fields");
28319f10315SSean Christopherson 	if (kvm_is_using_evmcs())
28489b0c9f5SSean Christopherson 		return evmcs_write32(field, evmcs_read32(field) | mask);
28589b0c9f5SSean Christopherson 
28689b0c9f5SSean Christopherson 	__vmcs_writel(field, __vmcs_readl(field) | mask);
28789b0c9f5SSean Christopherson }
28889b0c9f5SSean Christopherson 
vmcs_clear(struct vmcs * vmcs)28989b0c9f5SSean Christopherson static inline void vmcs_clear(struct vmcs *vmcs)
29089b0c9f5SSean Christopherson {
29189b0c9f5SSean Christopherson 	u64 phys_addr = __pa(vmcs);
29289b0c9f5SSean Christopherson 
29352a9fcbcSSean Christopherson 	vmx_asm1(vmclear, "m"(phys_addr), vmcs, phys_addr);
29489b0c9f5SSean Christopherson }
29589b0c9f5SSean Christopherson 
vmcs_load(struct vmcs * vmcs)29689b0c9f5SSean Christopherson static inline void vmcs_load(struct vmcs *vmcs)
29789b0c9f5SSean Christopherson {
29889b0c9f5SSean Christopherson 	u64 phys_addr = __pa(vmcs);
29989b0c9f5SSean Christopherson 
30019f10315SSean Christopherson 	if (kvm_is_using_evmcs())
30189b0c9f5SSean Christopherson 		return evmcs_load(phys_addr);
30289b0c9f5SSean Christopherson 
30352a9fcbcSSean Christopherson 	vmx_asm1(vmptrld, "m"(phys_addr), vmcs, phys_addr);
30489b0c9f5SSean Christopherson }
30589b0c9f5SSean Christopherson 
__invvpid(unsigned long ext,u16 vpid,gva_t gva)30689b0c9f5SSean Christopherson static inline void __invvpid(unsigned long ext, u16 vpid, gva_t gva)
30789b0c9f5SSean Christopherson {
30889b0c9f5SSean Christopherson 	struct {
30989b0c9f5SSean Christopherson 		u64 vpid : 16;
31089b0c9f5SSean Christopherson 		u64 rsvd : 48;
31189b0c9f5SSean Christopherson 		u64 gva;
31289b0c9f5SSean Christopherson 	} operand = { vpid, 0, gva };
31389b0c9f5SSean Christopherson 
31452a9fcbcSSean Christopherson 	vmx_asm2(invvpid, "r"(ext), "m"(operand), ext, vpid, gva);
31589b0c9f5SSean Christopherson }
31689b0c9f5SSean Christopherson 
__invept(unsigned long ext,u64 eptp)317bc17fccbSYan Zhao static inline void __invept(unsigned long ext, u64 eptp)
31889b0c9f5SSean Christopherson {
31989b0c9f5SSean Christopherson 	struct {
320bc17fccbSYan Zhao 		u64 eptp;
321bc17fccbSYan Zhao 		u64 reserved_0;
322bc17fccbSYan Zhao 	} operand = { eptp, 0 };
323bc17fccbSYan Zhao 	vmx_asm2(invept, "r"(ext), "m"(operand), ext, eptp);
32489b0c9f5SSean Christopherson }
32589b0c9f5SSean Christopherson 
vpid_sync_vcpu_single(int vpid)32689b0c9f5SSean Christopherson static inline void vpid_sync_vcpu_single(int vpid)
32789b0c9f5SSean Christopherson {
32889b0c9f5SSean Christopherson 	if (vpid == 0)
32989b0c9f5SSean Christopherson 		return;
33089b0c9f5SSean Christopherson 
33189b0c9f5SSean Christopherson 	__invvpid(VMX_VPID_EXTENT_SINGLE_CONTEXT, vpid, 0);
33289b0c9f5SSean Christopherson }
33389b0c9f5SSean Christopherson 
vpid_sync_vcpu_global(void)33489b0c9f5SSean Christopherson static inline void vpid_sync_vcpu_global(void)
33589b0c9f5SSean Christopherson {
33689b0c9f5SSean Christopherson 	__invvpid(VMX_VPID_EXTENT_ALL_CONTEXT, 0, 0);
33789b0c9f5SSean Christopherson }
33889b0c9f5SSean Christopherson 
vpid_sync_context(int vpid)33989b0c9f5SSean Christopherson static inline void vpid_sync_context(int vpid)
34089b0c9f5SSean Christopherson {
34189b0c9f5SSean Christopherson 	if (cpu_has_vmx_invvpid_single())
34289b0c9f5SSean Christopherson 		vpid_sync_vcpu_single(vpid);
343c746b3a4SSean Christopherson 	else if (vpid != 0)
34489b0c9f5SSean Christopherson 		vpid_sync_vcpu_global();
34589b0c9f5SSean Christopherson }
34689b0c9f5SSean Christopherson 
vpid_sync_vcpu_addr(int vpid,gva_t addr)347ab4b3597SSean Christopherson static inline void vpid_sync_vcpu_addr(int vpid, gva_t addr)
3488a8b097cSSean Christopherson {
3498a8b097cSSean Christopherson 	if (vpid == 0)
350ab4b3597SSean Christopherson 		return;
3518a8b097cSSean Christopherson 
352ab4b3597SSean Christopherson 	if (cpu_has_vmx_invvpid_individual_addr())
3538a8b097cSSean Christopherson 		__invvpid(VMX_VPID_EXTENT_INDIVIDUAL_ADDR, vpid, addr);
354ab4b3597SSean Christopherson 	else
355ab4b3597SSean Christopherson 		vpid_sync_context(vpid);
3568a8b097cSSean Christopherson }
3578a8b097cSSean Christopherson 
ept_sync_global(void)35889b0c9f5SSean Christopherson static inline void ept_sync_global(void)
35989b0c9f5SSean Christopherson {
360bc17fccbSYan Zhao 	__invept(VMX_EPT_EXTENT_GLOBAL, 0);
36189b0c9f5SSean Christopherson }
36289b0c9f5SSean Christopherson 
ept_sync_context(u64 eptp)36389b0c9f5SSean Christopherson static inline void ept_sync_context(u64 eptp)
36489b0c9f5SSean Christopherson {
36589b0c9f5SSean Christopherson 	if (cpu_has_vmx_invept_context())
366bc17fccbSYan Zhao 		__invept(VMX_EPT_EXTENT_CONTEXT, eptp);
36789b0c9f5SSean Christopherson 	else
36889b0c9f5SSean Christopherson 		ept_sync_global();
36989b0c9f5SSean Christopherson }
37089b0c9f5SSean Christopherson 
37189b0c9f5SSean Christopherson #endif /* __KVM_X86_VMX_INSN_H */
372