xref: /linux/arch/x86/kvm/regs.h (revision 4e6df939687caf878bb493570ff1c583bba86e7c)
1ece08316SSean Christopherson /* SPDX-License-Identifier: GPL-2.0 */
2ece08316SSean Christopherson #ifndef ARCH_X86_KVM_REGS_H
3ece08316SSean Christopherson #define ARCH_X86_KVM_REGS_H
4ece08316SSean Christopherson 
5ece08316SSean Christopherson #include <linux/kvm_host.h>
6ece08316SSean Christopherson 
7ece08316SSean Christopherson #define KVM_POSSIBLE_CR0_GUEST_BITS	(X86_CR0_TS | X86_CR0_WP)
8ece08316SSean Christopherson #define KVM_POSSIBLE_CR4_GUEST_BITS				  \
9ece08316SSean Christopherson 	(X86_CR4_PVI | X86_CR4_DE | X86_CR4_PCE | X86_CR4_OSFXSR  \
10ece08316SSean Christopherson 	 | X86_CR4_OSXMMEXCPT | X86_CR4_PGE | X86_CR4_TSD | X86_CR4_FSGSBASE \
11ece08316SSean Christopherson 	 | X86_CR4_CET)
12ece08316SSean Christopherson 
13ece08316SSean Christopherson #define X86_CR0_PDPTR_BITS    (X86_CR0_CD | X86_CR0_NW | X86_CR0_PG)
14ece08316SSean Christopherson #define X86_CR4_TLBFLUSH_BITS (X86_CR4_PGE | X86_CR4_PCIDE | X86_CR4_PAE | X86_CR4_SMEP)
15ece08316SSean Christopherson #define X86_CR4_PDPTR_BITS    (X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_SMEP)
16ece08316SSean Christopherson 
17ece08316SSean Christopherson static_assert(!(KVM_POSSIBLE_CR0_GUEST_BITS & X86_CR0_PDPTR_BITS));
18ece08316SSean Christopherson 
19ed8a7b89SSean Christopherson static inline bool is_long_mode(struct kvm_vcpu *vcpu)
20ed8a7b89SSean Christopherson {
21ed8a7b89SSean Christopherson #ifdef CONFIG_X86_64
22ed8a7b89SSean Christopherson 	return !!(vcpu->arch.efer & EFER_LMA);
23ed8a7b89SSean Christopherson #else
24ed8a7b89SSean Christopherson 	return false;
25ed8a7b89SSean Christopherson #endif
26ed8a7b89SSean Christopherson }
27ed8a7b89SSean Christopherson 
28ed8a7b89SSean Christopherson static inline bool is_64_bit_mode(struct kvm_vcpu *vcpu)
29ed8a7b89SSean Christopherson {
30ed8a7b89SSean Christopherson 	int cs_db, cs_l;
31ed8a7b89SSean Christopherson 
32ed8a7b89SSean Christopherson 	WARN_ON_ONCE(vcpu->arch.guest_state_protected);
33ed8a7b89SSean Christopherson 
34ed8a7b89SSean Christopherson 	if (!is_long_mode(vcpu))
35ed8a7b89SSean Christopherson 		return false;
36ed8a7b89SSean Christopherson 	kvm_x86_call(get_cs_db_l_bits)(vcpu, &cs_db, &cs_l);
37ed8a7b89SSean Christopherson 	return cs_l;
38ed8a7b89SSean Christopherson }
39ed8a7b89SSean Christopherson 
40ed8a7b89SSean Christopherson static inline bool is_64_bit_hypercall(struct kvm_vcpu *vcpu)
41ed8a7b89SSean Christopherson {
42879fffc0SSean Christopherson #ifdef CONFIG_X86_64
43ed8a7b89SSean Christopherson 	/*
44ed8a7b89SSean Christopherson 	 * If running with protected guest state, the CS register is not
45ed8a7b89SSean Christopherson 	 * accessible. The hypercall register values will have had to been
46ed8a7b89SSean Christopherson 	 * provided in 64-bit mode, so assume the guest is in 64-bit.
47ed8a7b89SSean Christopherson 	 */
48ed8a7b89SSean Christopherson 	return vcpu->arch.guest_state_protected || is_64_bit_mode(vcpu);
49879fffc0SSean Christopherson #else
50879fffc0SSean Christopherson 	return false;
51879fffc0SSean Christopherson #endif
52ed8a7b89SSean Christopherson }
53ed8a7b89SSean Christopherson 
54fc40b125SSean Christopherson static __always_inline unsigned long kvm_reg_mode_mask(struct kvm_vcpu *vcpu)
55fc40b125SSean Christopherson {
56fc40b125SSean Christopherson #ifdef CONFIG_X86_64
57fc40b125SSean Christopherson 	return is_64_bit_mode(vcpu) ? GENMASK(63, 0) : GENMASK(31, 0);
58fc40b125SSean Christopherson #else
59fc40b125SSean Christopherson 	return GENMASK(31, 0);
60fc40b125SSean Christopherson #endif
61fc40b125SSean Christopherson }
62fc40b125SSean Christopherson 
63fc40b125SSean Christopherson #define __BUILD_KVM_GPR_ACCESSORS(lname, uname)						\
64ece08316SSean Christopherson static __always_inline unsigned long kvm_##lname##_read(struct kvm_vcpu *vcpu)		\
65ece08316SSean Christopherson {											\
66fc40b125SSean Christopherson 	return vcpu->arch.regs[VCPU_REGS_##uname] & kvm_reg_mode_mask(vcpu);		\
67ece08316SSean Christopherson }											\
68fc40b125SSean Christopherson static __always_inline unsigned long kvm_##lname##_read_raw(struct kvm_vcpu *vcpu)	\
69fc40b125SSean Christopherson {											\
70fc40b125SSean Christopherson 	return vcpu->arch.regs[VCPU_REGS_##uname];					\
71fc40b125SSean Christopherson }											\
72fc40b125SSean Christopherson static __always_inline void kvm_##lname##_write_raw(struct kvm_vcpu *vcpu,		\
73fc40b125SSean Christopherson 						    unsigned long val)			\
74fc40b125SSean Christopherson {											\
75ece08316SSean Christopherson 	vcpu->arch.regs[VCPU_REGS_##uname] = val;					\
76ece08316SSean Christopherson }
77fc40b125SSean Christopherson #define BUILD_KVM_GPR_ACCESSORS(lname, uname)						\
78fc40b125SSean Christopherson static __always_inline u32 kvm_e##lname##_read(struct kvm_vcpu *vcpu)			\
79fc40b125SSean Christopherson {											\
80fc40b125SSean Christopherson 	return vcpu->arch.regs[VCPU_REGS_##uname];					\
81fc40b125SSean Christopherson }											\
82fc40b125SSean Christopherson static __always_inline void kvm_e##lname##_write(struct kvm_vcpu *vcpu, u32 val)	\
83fc40b125SSean Christopherson {											\
84fc40b125SSean Christopherson 	vcpu->arch.regs[VCPU_REGS_##uname] = val;					\
85fc40b125SSean Christopherson }											\
86fc40b125SSean Christopherson __BUILD_KVM_GPR_ACCESSORS(r##lname, uname)
87fc40b125SSean Christopherson 
88fc40b125SSean Christopherson BUILD_KVM_GPR_ACCESSORS(ax, RAX)
89fc40b125SSean Christopherson BUILD_KVM_GPR_ACCESSORS(bx, RBX)
90fc40b125SSean Christopherson BUILD_KVM_GPR_ACCESSORS(cx, RCX)
91fc40b125SSean Christopherson BUILD_KVM_GPR_ACCESSORS(dx, RDX)
92fc40b125SSean Christopherson BUILD_KVM_GPR_ACCESSORS(bp, RBP)
93fc40b125SSean Christopherson BUILD_KVM_GPR_ACCESSORS(si, RSI)
94fc40b125SSean Christopherson BUILD_KVM_GPR_ACCESSORS(di, RDI)
95ece08316SSean Christopherson #ifdef CONFIG_X86_64
96fc40b125SSean Christopherson __BUILD_KVM_GPR_ACCESSORS(r8,  R8)
97fc40b125SSean Christopherson __BUILD_KVM_GPR_ACCESSORS(r9,  R9)
98fc40b125SSean Christopherson __BUILD_KVM_GPR_ACCESSORS(r10, R10)
99fc40b125SSean Christopherson __BUILD_KVM_GPR_ACCESSORS(r11, R11)
100fc40b125SSean Christopherson __BUILD_KVM_GPR_ACCESSORS(r12, R12)
101fc40b125SSean Christopherson __BUILD_KVM_GPR_ACCESSORS(r13, R13)
102fc40b125SSean Christopherson __BUILD_KVM_GPR_ACCESSORS(r14, R14)
103fc40b125SSean Christopherson __BUILD_KVM_GPR_ACCESSORS(r15, R15)
104ece08316SSean Christopherson #endif
105ece08316SSean Christopherson 
106ece08316SSean Christopherson /*
107ece08316SSean Christopherson  * Using the register cache from interrupt context is generally not allowed, as
108ece08316SSean Christopherson  * caching a register and marking it available/dirty can't be done atomically,
109ece08316SSean Christopherson  * i.e. accesses from interrupt context may clobber state or read stale data if
110ece08316SSean Christopherson  * the vCPU task is in the process of updating the cache.  The exception is if
111ece08316SSean Christopherson  * KVM is handling a PMI IRQ/NMI VM-Exit, as that bound code sequence doesn't
112ece08316SSean Christopherson  * touch the cache, it runs after the cache is reset (post VM-Exit), and PMIs
113ece08316SSean Christopherson  * need to access several registers that are cacheable.
114ece08316SSean Christopherson  */
115ece08316SSean Christopherson #define kvm_assert_register_caching_allowed(vcpu)		\
116ece08316SSean Christopherson 	lockdep_assert_once(in_task() || kvm_arch_pmi_in_guest(vcpu))
117ece08316SSean Christopherson 
118ece08316SSean Christopherson /*
119ece08316SSean Christopherson  * avail  dirty
120ece08316SSean Christopherson  * 0	  0	  register in VMCS/VMCB
121ece08316SSean Christopherson  * 0	  1	  *INVALID*
122ece08316SSean Christopherson  * 1	  0	  register in vcpu->arch
123ece08316SSean Christopherson  * 1	  1	  register in vcpu->arch, needs to be stored back
124ece08316SSean Christopherson  */
125ece08316SSean Christopherson static inline bool kvm_register_is_available(struct kvm_vcpu *vcpu,
126ece08316SSean Christopherson 					     enum kvm_reg reg)
127ece08316SSean Christopherson {
128ece08316SSean Christopherson 	kvm_assert_register_caching_allowed(vcpu);
129ece08316SSean Christopherson 	return test_bit(reg, vcpu->arch.regs_avail);
130ece08316SSean Christopherson }
131ece08316SSean Christopherson 
132ece08316SSean Christopherson static inline bool kvm_register_is_dirty(struct kvm_vcpu *vcpu,
133ece08316SSean Christopherson 					 enum kvm_reg reg)
134ece08316SSean Christopherson {
135ece08316SSean Christopherson 	kvm_assert_register_caching_allowed(vcpu);
136ece08316SSean Christopherson 	return test_bit(reg, vcpu->arch.regs_dirty);
137ece08316SSean Christopherson }
138ece08316SSean Christopherson 
139*4e6df939SPaolo Bonzini static inline void kvm_register_mark_for_reload(struct kvm_vcpu *vcpu,
140*4e6df939SPaolo Bonzini 					       enum kvm_reg reg)
141*4e6df939SPaolo Bonzini {
142*4e6df939SPaolo Bonzini 	kvm_assert_register_caching_allowed(vcpu);
143*4e6df939SPaolo Bonzini 	__clear_bit(reg, vcpu->arch.regs_avail);
144*4e6df939SPaolo Bonzini 	__clear_bit(reg, vcpu->arch.regs_dirty);
145*4e6df939SPaolo Bonzini }
146*4e6df939SPaolo Bonzini 
147ece08316SSean Christopherson static inline void kvm_register_mark_available(struct kvm_vcpu *vcpu,
148ece08316SSean Christopherson 					       enum kvm_reg reg)
149ece08316SSean Christopherson {
150ece08316SSean Christopherson 	kvm_assert_register_caching_allowed(vcpu);
151ece08316SSean Christopherson 	__set_bit(reg, vcpu->arch.regs_avail);
152ece08316SSean Christopherson }
153ece08316SSean Christopherson 
154ece08316SSean Christopherson static inline void kvm_register_mark_dirty(struct kvm_vcpu *vcpu,
155ece08316SSean Christopherson 					   enum kvm_reg reg)
156ece08316SSean Christopherson {
157ece08316SSean Christopherson 	kvm_assert_register_caching_allowed(vcpu);
158ece08316SSean Christopherson 	__set_bit(reg, vcpu->arch.regs_avail);
159ece08316SSean Christopherson 	__set_bit(reg, vcpu->arch.regs_dirty);
160ece08316SSean Christopherson }
161ece08316SSean Christopherson 
162ece08316SSean Christopherson /*
163ece08316SSean Christopherson  * kvm_register_test_and_mark_available() is a special snowflake that uses an
164ece08316SSean Christopherson  * arch bitop directly to avoid the explicit instrumentation that comes with
165ece08316SSean Christopherson  * the generic bitops.  This allows code that cannot be instrumented (noinstr
166ece08316SSean Christopherson  * functions), e.g. the low level VM-Enter/VM-Exit paths, to cache registers.
167ece08316SSean Christopherson  */
168ece08316SSean Christopherson static __always_inline bool kvm_register_test_and_mark_available(struct kvm_vcpu *vcpu,
169ece08316SSean Christopherson 								 enum kvm_reg reg)
170ece08316SSean Christopherson {
171ece08316SSean Christopherson 	kvm_assert_register_caching_allowed(vcpu);
172ece08316SSean Christopherson 	return arch___test_and_set_bit(reg, vcpu->arch.regs_avail);
173ece08316SSean Christopherson }
174ece08316SSean Christopherson 
175ece08316SSean Christopherson static __always_inline void kvm_clear_available_registers(struct kvm_vcpu *vcpu,
176ece08316SSean Christopherson 							  unsigned long clear_mask)
177ece08316SSean Christopherson {
178ece08316SSean Christopherson 	BUILD_BUG_ON(sizeof(clear_mask) != sizeof(vcpu->arch.regs_avail[0]));
179ece08316SSean Christopherson 	BUILD_BUG_ON(ARRAY_SIZE(vcpu->arch.regs_avail) != 1);
180ece08316SSean Christopherson 
181ece08316SSean Christopherson 	/*
182ece08316SSean Christopherson 	 * Note the bitwise-AND!  In practice, a straight write would also work
183ece08316SSean Christopherson 	 * as KVM initializes the mask to all ones and never clears registers
184ece08316SSean Christopherson 	 * that are eagerly synchronized.  Using a bitwise-AND adds a bit of
185ece08316SSean Christopherson 	 * sanity checking as incorrectly marking an eagerly sync'd register
186ece08316SSean Christopherson 	 * unavailable will generate a WARN due to an unexpected cache request.
187ece08316SSean Christopherson 	 */
188ece08316SSean Christopherson 	vcpu->arch.regs_avail[0] &= ~clear_mask;
189ece08316SSean Christopherson }
190ece08316SSean Christopherson 
191ece08316SSean Christopherson static __always_inline void kvm_reset_dirty_registers(struct kvm_vcpu *vcpu)
192ece08316SSean Christopherson {
193ece08316SSean Christopherson 	BUILD_BUG_ON(ARRAY_SIZE(vcpu->arch.regs_dirty) != 1);
194ece08316SSean Christopherson 	vcpu->arch.regs_dirty[0] = 0;
195ece08316SSean Christopherson }
196ece08316SSean Christopherson 
197ece08316SSean Christopherson /*
198ece08316SSean Christopherson  * The "raw" register helpers are only for cases where the full 64 bits of a
199ece08316SSean Christopherson  * register are read/written irrespective of current vCPU mode.  In other words,
200ece08316SSean Christopherson  * odds are good you shouldn't be using the raw variants.
201ece08316SSean Christopherson  */
202ece08316SSean Christopherson static inline unsigned long kvm_register_read_raw(struct kvm_vcpu *vcpu, int reg)
203ece08316SSean Christopherson {
204ece08316SSean Christopherson 	if (WARN_ON_ONCE((unsigned int)reg >= NR_VCPU_GENERAL_PURPOSE_REGS))
205ece08316SSean Christopherson 		return 0;
206ece08316SSean Christopherson 
207ece08316SSean Christopherson 	if (!kvm_register_is_available(vcpu, reg))
208ece08316SSean Christopherson 		kvm_x86_call(cache_reg)(vcpu, reg);
209ece08316SSean Christopherson 
210ece08316SSean Christopherson 	return vcpu->arch.regs[reg];
211ece08316SSean Christopherson }
212ece08316SSean Christopherson 
213ed8a7b89SSean Christopherson static inline unsigned long kvm_register_read(struct kvm_vcpu *vcpu, int reg)
214ed8a7b89SSean Christopherson {
215fc40b125SSean Christopherson 	return kvm_register_read_raw(vcpu, reg) & kvm_reg_mode_mask(vcpu);
216ed8a7b89SSean Christopherson }
217ed8a7b89SSean Christopherson 
218ece08316SSean Christopherson static inline void kvm_register_write_raw(struct kvm_vcpu *vcpu, int reg,
219ece08316SSean Christopherson 					  unsigned long val)
220ece08316SSean Christopherson {
221ece08316SSean Christopherson 	if (WARN_ON_ONCE((unsigned int)reg >= NR_VCPU_GENERAL_PURPOSE_REGS))
222ece08316SSean Christopherson 		return;
223ece08316SSean Christopherson 
224ece08316SSean Christopherson 	vcpu->arch.regs[reg] = val;
225ece08316SSean Christopherson 	kvm_register_mark_dirty(vcpu, reg);
226ece08316SSean Christopherson }
227ece08316SSean Christopherson 
228ed8a7b89SSean Christopherson static inline void kvm_register_write(struct kvm_vcpu *vcpu,
229ed8a7b89SSean Christopherson 				       int reg, unsigned long val)
230ed8a7b89SSean Christopherson {
231fc40b125SSean Christopherson 	return kvm_register_write_raw(vcpu, reg, val & kvm_reg_mode_mask(vcpu));
232ed8a7b89SSean Christopherson }
233ed8a7b89SSean Christopherson 
234ece08316SSean Christopherson static inline unsigned long kvm_rip_read(struct kvm_vcpu *vcpu)
235ece08316SSean Christopherson {
236ece08316SSean Christopherson 	if (!kvm_register_is_available(vcpu, VCPU_REG_RIP))
237ece08316SSean Christopherson 		kvm_x86_call(cache_reg)(vcpu, VCPU_REG_RIP);
238ece08316SSean Christopherson 
239ece08316SSean Christopherson 	return vcpu->arch.rip;
240ece08316SSean Christopherson }
241ece08316SSean Christopherson 
242ece08316SSean Christopherson static inline void kvm_rip_write(struct kvm_vcpu *vcpu, unsigned long val)
243ece08316SSean Christopherson {
244ece08316SSean Christopherson 	vcpu->arch.rip = val;
245ece08316SSean Christopherson 	kvm_register_mark_dirty(vcpu, VCPU_REG_RIP);
246ece08316SSean Christopherson }
247ece08316SSean Christopherson 
248ece08316SSean Christopherson static inline unsigned long kvm_rsp_read(struct kvm_vcpu *vcpu)
249ece08316SSean Christopherson {
250ece08316SSean Christopherson 	return kvm_register_read_raw(vcpu, VCPU_REGS_RSP);
251ece08316SSean Christopherson }
252ece08316SSean Christopherson 
253ece08316SSean Christopherson static inline void kvm_rsp_write(struct kvm_vcpu *vcpu, unsigned long val)
254ece08316SSean Christopherson {
255ece08316SSean Christopherson 	kvm_register_write_raw(vcpu, VCPU_REGS_RSP, val);
256ece08316SSean Christopherson }
257ece08316SSean Christopherson 
258ed8a7b89SSean Christopherson static inline u64 kvm_read_edx_eax(struct kvm_vcpu *vcpu)
259ed8a7b89SSean Christopherson {
260fc40b125SSean Christopherson 	return kvm_eax_read(vcpu) | (u64)(kvm_edx_read(vcpu)) << 32;
261ed8a7b89SSean Christopherson }
262ed8a7b89SSean Christopherson 
263ece08316SSean Christopherson static inline u64 kvm_pdptr_read(struct kvm_vcpu *vcpu, int index)
264ece08316SSean Christopherson {
265ece08316SSean Christopherson 	might_sleep();  /* on svm */
266ece08316SSean Christopherson 
267ece08316SSean Christopherson 	if (!kvm_register_is_available(vcpu, VCPU_REG_PDPTR))
268ece08316SSean Christopherson 		kvm_x86_call(cache_reg)(vcpu, VCPU_REG_PDPTR);
269ece08316SSean Christopherson 
270*4e6df939SPaolo Bonzini 	return vcpu->arch.pdptrs[index];
271ece08316SSean Christopherson }
272ece08316SSean Christopherson 
273ece08316SSean Christopherson static inline void kvm_pdptr_write(struct kvm_vcpu *vcpu, int index, u64 value)
274ece08316SSean Christopherson {
275*4e6df939SPaolo Bonzini 	vcpu->arch.pdptrs[index] = value;
276ece08316SSean Christopherson }
277ece08316SSean Christopherson 
278ece08316SSean Christopherson static inline ulong kvm_read_cr0_bits(struct kvm_vcpu *vcpu, ulong mask)
279ece08316SSean Christopherson {
280ece08316SSean Christopherson 	ulong tmask = mask & KVM_POSSIBLE_CR0_GUEST_BITS;
281ece08316SSean Christopherson 	if ((tmask & vcpu->arch.cr0_guest_owned_bits) &&
282ece08316SSean Christopherson 	    !kvm_register_is_available(vcpu, VCPU_REG_CR0))
283ece08316SSean Christopherson 		kvm_x86_call(cache_reg)(vcpu, VCPU_REG_CR0);
284ece08316SSean Christopherson 	return vcpu->arch.cr0 & mask;
285ece08316SSean Christopherson }
286ece08316SSean Christopherson 
287ece08316SSean Christopherson static __always_inline bool kvm_is_cr0_bit_set(struct kvm_vcpu *vcpu,
288ece08316SSean Christopherson 					       unsigned long cr0_bit)
289ece08316SSean Christopherson {
290ece08316SSean Christopherson 	BUILD_BUG_ON(!is_power_of_2(cr0_bit));
291ece08316SSean Christopherson 
292ece08316SSean Christopherson 	return !!kvm_read_cr0_bits(vcpu, cr0_bit);
293ece08316SSean Christopherson }
294ece08316SSean Christopherson 
295ece08316SSean Christopherson static inline ulong kvm_read_cr0(struct kvm_vcpu *vcpu)
296ece08316SSean Christopherson {
297ece08316SSean Christopherson 	return kvm_read_cr0_bits(vcpu, ~0UL);
298ece08316SSean Christopherson }
299ece08316SSean Christopherson 
300ece08316SSean Christopherson static inline ulong kvm_read_cr4_bits(struct kvm_vcpu *vcpu, ulong mask)
301ece08316SSean Christopherson {
302ece08316SSean Christopherson 	ulong tmask = mask & KVM_POSSIBLE_CR4_GUEST_BITS;
303ece08316SSean Christopherson 	if ((tmask & vcpu->arch.cr4_guest_owned_bits) &&
304ece08316SSean Christopherson 	    !kvm_register_is_available(vcpu, VCPU_REG_CR4))
305ece08316SSean Christopherson 		kvm_x86_call(cache_reg)(vcpu, VCPU_REG_CR4);
306ece08316SSean Christopherson 	return vcpu->arch.cr4 & mask;
307ece08316SSean Christopherson }
308ece08316SSean Christopherson 
309ece08316SSean Christopherson static __always_inline bool kvm_is_cr4_bit_set(struct kvm_vcpu *vcpu,
310ece08316SSean Christopherson 					       unsigned long cr4_bit)
311ece08316SSean Christopherson {
312ece08316SSean Christopherson 	BUILD_BUG_ON(!is_power_of_2(cr4_bit));
313ece08316SSean Christopherson 
314ece08316SSean Christopherson 	return !!kvm_read_cr4_bits(vcpu, cr4_bit);
315ece08316SSean Christopherson }
316ece08316SSean Christopherson 
317ece08316SSean Christopherson static inline ulong kvm_read_cr3(struct kvm_vcpu *vcpu)
318ece08316SSean Christopherson {
319ece08316SSean Christopherson 	if (!kvm_register_is_available(vcpu, VCPU_REG_CR3))
320ece08316SSean Christopherson 		kvm_x86_call(cache_reg)(vcpu, VCPU_REG_CR3);
321ece08316SSean Christopherson 	return vcpu->arch.cr3;
322ece08316SSean Christopherson }
323ece08316SSean Christopherson 
324ece08316SSean Christopherson static inline ulong kvm_read_cr4(struct kvm_vcpu *vcpu)
325ece08316SSean Christopherson {
326ece08316SSean Christopherson 	return kvm_read_cr4_bits(vcpu, ~0UL);
327ece08316SSean Christopherson }
328ece08316SSean Christopherson 
329ed8a7b89SSean Christopherson static inline bool __kvm_is_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
330ece08316SSean Christopherson {
331ed8a7b89SSean Christopherson 	return !(cr4 & vcpu->arch.cr4_guest_rsvd_bits);
332ed8a7b89SSean Christopherson }
333ed8a7b89SSean Christopherson 
334ed8a7b89SSean Christopherson #define __cr4_reserved_bits(__cpu_has, __c)             \
335ed8a7b89SSean Christopherson ({                                                      \
336ed8a7b89SSean Christopherson 	u64 __reserved_bits = CR4_RESERVED_BITS;        \
337ed8a7b89SSean Christopherson                                                         \
338ed8a7b89SSean Christopherson 	if (!__cpu_has(__c, X86_FEATURE_XSAVE))         \
339ed8a7b89SSean Christopherson 		__reserved_bits |= X86_CR4_OSXSAVE;     \
340ed8a7b89SSean Christopherson 	if (!__cpu_has(__c, X86_FEATURE_SMEP))          \
341ed8a7b89SSean Christopherson 		__reserved_bits |= X86_CR4_SMEP;        \
342ed8a7b89SSean Christopherson 	if (!__cpu_has(__c, X86_FEATURE_SMAP))          \
343ed8a7b89SSean Christopherson 		__reserved_bits |= X86_CR4_SMAP;        \
344ed8a7b89SSean Christopherson 	if (!__cpu_has(__c, X86_FEATURE_FSGSBASE))      \
345ed8a7b89SSean Christopherson 		__reserved_bits |= X86_CR4_FSGSBASE;    \
346ed8a7b89SSean Christopherson 	if (!__cpu_has(__c, X86_FEATURE_PKU))           \
347ed8a7b89SSean Christopherson 		__reserved_bits |= X86_CR4_PKE;         \
348ed8a7b89SSean Christopherson 	if (!__cpu_has(__c, X86_FEATURE_LA57))          \
349ed8a7b89SSean Christopherson 		__reserved_bits |= X86_CR4_LA57;        \
350ed8a7b89SSean Christopherson 	if (!__cpu_has(__c, X86_FEATURE_UMIP))          \
351ed8a7b89SSean Christopherson 		__reserved_bits |= X86_CR4_UMIP;        \
352ed8a7b89SSean Christopherson 	if (!__cpu_has(__c, X86_FEATURE_VMX))           \
353ed8a7b89SSean Christopherson 		__reserved_bits |= X86_CR4_VMXE;        \
354ed8a7b89SSean Christopherson 	if (!__cpu_has(__c, X86_FEATURE_PCID))          \
355ed8a7b89SSean Christopherson 		__reserved_bits |= X86_CR4_PCIDE;       \
356ed8a7b89SSean Christopherson 	if (!__cpu_has(__c, X86_FEATURE_LAM))           \
357ed8a7b89SSean Christopherson 		__reserved_bits |= X86_CR4_LAM_SUP;     \
358ed8a7b89SSean Christopherson 	if (!__cpu_has(__c, X86_FEATURE_SHSTK) &&       \
359ed8a7b89SSean Christopherson 	    !__cpu_has(__c, X86_FEATURE_IBT))           \
360ed8a7b89SSean Christopherson 		__reserved_bits |= X86_CR4_CET;         \
361ed8a7b89SSean Christopherson 	__reserved_bits;                                \
362ed8a7b89SSean Christopherson })
363ed8a7b89SSean Christopherson 
364ed8a7b89SSean Christopherson static inline bool is_protmode(struct kvm_vcpu *vcpu)
365ed8a7b89SSean Christopherson {
366ed8a7b89SSean Christopherson 	return kvm_is_cr0_bit_set(vcpu, X86_CR0_PE);
367ed8a7b89SSean Christopherson }
368ed8a7b89SSean Christopherson 
369ed8a7b89SSean Christopherson static inline bool is_pae(struct kvm_vcpu *vcpu)
370ed8a7b89SSean Christopherson {
371ed8a7b89SSean Christopherson 	return kvm_is_cr4_bit_set(vcpu, X86_CR4_PAE);
372ed8a7b89SSean Christopherson }
373ed8a7b89SSean Christopherson 
374ed8a7b89SSean Christopherson static inline bool is_pse(struct kvm_vcpu *vcpu)
375ed8a7b89SSean Christopherson {
376ed8a7b89SSean Christopherson 	return kvm_is_cr4_bit_set(vcpu, X86_CR4_PSE);
377ed8a7b89SSean Christopherson }
378ed8a7b89SSean Christopherson 
379ed8a7b89SSean Christopherson static inline bool is_paging(struct kvm_vcpu *vcpu)
380ed8a7b89SSean Christopherson {
381ed8a7b89SSean Christopherson 	return likely(kvm_is_cr0_bit_set(vcpu, X86_CR0_PG));
382ed8a7b89SSean Christopherson }
383ed8a7b89SSean Christopherson 
384ed8a7b89SSean Christopherson static inline bool is_pae_paging(struct kvm_vcpu *vcpu)
385ed8a7b89SSean Christopherson {
386ed8a7b89SSean Christopherson 	return !is_long_mode(vcpu) && is_pae(vcpu) && is_paging(vcpu);
387ed8a7b89SSean Christopherson }
388ed8a7b89SSean Christopherson 
389ed8a7b89SSean Christopherson static inline bool kvm_dr7_valid(u64 data)
390ed8a7b89SSean Christopherson {
391ed8a7b89SSean Christopherson 	/* Bits [63:32] are reserved */
392ed8a7b89SSean Christopherson 	return !(data >> 32);
393ed8a7b89SSean Christopherson }
394ed8a7b89SSean Christopherson static inline bool kvm_dr6_valid(u64 data)
395ed8a7b89SSean Christopherson {
396ed8a7b89SSean Christopherson 	/* Bits [63:32] are reserved */
397ed8a7b89SSean Christopherson 	return !(data >> 32);
398ece08316SSean Christopherson }
399ece08316SSean Christopherson 
400ece08316SSean Christopherson static inline void enter_guest_mode(struct kvm_vcpu *vcpu)
401ece08316SSean Christopherson {
402ece08316SSean Christopherson 	vcpu->arch.hflags |= HF_GUEST_MASK;
403ece08316SSean Christopherson 	vcpu->stat.guest_mode = 1;
404ece08316SSean Christopherson }
405ece08316SSean Christopherson 
406ece08316SSean Christopherson static inline void leave_guest_mode(struct kvm_vcpu *vcpu)
407ece08316SSean Christopherson {
408ece08316SSean Christopherson 	vcpu->arch.hflags &= ~HF_GUEST_MASK;
409ece08316SSean Christopherson 
410ece08316SSean Christopherson 	if (vcpu->arch.load_eoi_exitmap_pending) {
411ece08316SSean Christopherson 		vcpu->arch.load_eoi_exitmap_pending = false;
412ece08316SSean Christopherson 		kvm_make_request(KVM_REQ_LOAD_EOI_EXITMAP, vcpu);
413ece08316SSean Christopherson 	}
414ece08316SSean Christopherson 
415ece08316SSean Christopherson 	vcpu->stat.guest_mode = 0;
416ece08316SSean Christopherson }
417ece08316SSean Christopherson 
418ece08316SSean Christopherson static inline bool is_guest_mode(struct kvm_vcpu *vcpu)
419ece08316SSean Christopherson {
420ece08316SSean Christopherson 	return vcpu->arch.hflags & HF_GUEST_MASK;
421ece08316SSean Christopherson }
422ece08316SSean Christopherson 
423ece08316SSean Christopherson #endif
424