xref: /openbmc/linux/arch/x86/kvm/cpuid.h (revision 55e43d6abd078ed6d219902ce8cb4d68e3c993ba)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
200b27a3eSAvi Kivity #ifndef ARCH_X86_KVM_CPUID_H
300b27a3eSAvi Kivity #define ARCH_X86_KVM_CPUID_H
400b27a3eSAvi Kivity 
500b27a3eSAvi Kivity #include "x86.h"
601338078SRicardo Koller #include "reverse_cpuid.h"
791713fafSBorislav Petkov #include <asm/cpu.h>
8d6321d49SRadim Krčmář #include <asm/processor.h>
966570e96SOliver Upton #include <uapi/asm/kvm_para.h>
1000b27a3eSAvi Kivity 
114e66c0cbSSean Christopherson extern u32 kvm_cpu_caps[NR_KVM_CPU_CAPS] __read_mostly;
1266a6950fSSean Christopherson void kvm_set_cpu_caps(void);
1366a6950fSSean Christopherson 
14aedbaf4fSXiaoyao Li void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu);
1501b4f510SOliver Upton void kvm_update_pv_runtime(struct kvm_vcpu *vcpu);
16277ad7d5SSean Christopherson struct kvm_cpuid_entry2 *kvm_find_cpuid_entry_index(struct kvm_vcpu *vcpu,
1700b27a3eSAvi Kivity 						    u32 function, u32 index);
18277ad7d5SSean Christopherson struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu,
19277ad7d5SSean Christopherson 					      u32 function);
209c15bb1dSBorislav Petkov int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid,
219c15bb1dSBorislav Petkov 			    struct kvm_cpuid_entry2 __user *entries,
229c15bb1dSBorislav Petkov 			    unsigned int type);
2300b27a3eSAvi Kivity int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
2400b27a3eSAvi Kivity 			     struct kvm_cpuid *cpuid,
2500b27a3eSAvi Kivity 			     struct kvm_cpuid_entry __user *entries);
2600b27a3eSAvi Kivity int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu,
2700b27a3eSAvi Kivity 			      struct kvm_cpuid2 *cpuid,
2800b27a3eSAvi Kivity 			      struct kvm_cpuid_entry2 __user *entries);
2900b27a3eSAvi Kivity int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu,
3000b27a3eSAvi Kivity 			      struct kvm_cpuid2 *cpuid,
3100b27a3eSAvi Kivity 			      struct kvm_cpuid_entry2 __user *entries);
32e911eb3bSYu Zhang bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
33f91af517SSean Christopherson 	       u32 *ecx, u32 *edx, bool exact_only);
3400b27a3eSAvi Kivity 
35*65fac86cSSean Christopherson void __init kvm_init_xstate_sizes(void);
36be50b206SGuang Zeng u32 xstate_required_size(u64 xstate_bv, bool compacted);
37be50b206SGuang Zeng 
385a4f55cdSEugene Korenevsky int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu);
39a8ac864aSSean Christopherson u64 kvm_vcpu_reserved_gpa_bits_raw(struct kvm_vcpu *vcpu);
405a4f55cdSEugene Korenevsky 
cpuid_maxphyaddr(struct kvm_vcpu * vcpu)415a4f55cdSEugene Korenevsky static inline int cpuid_maxphyaddr(struct kvm_vcpu *vcpu)
425a4f55cdSEugene Korenevsky {
435a4f55cdSEugene Korenevsky 	return vcpu->arch.maxphyaddr;
445a4f55cdSEugene Korenevsky }
4500b27a3eSAvi Kivity 
kvm_vcpu_is_legal_gpa(struct kvm_vcpu * vcpu,gpa_t gpa)464bda0e97SSean Christopherson static inline bool kvm_vcpu_is_legal_gpa(struct kvm_vcpu *vcpu, gpa_t gpa)
474bda0e97SSean Christopherson {
48ca29e145SSean Christopherson 	return !(gpa & vcpu->arch.reserved_gpa_bits);
494bda0e97SSean Christopherson }
504bda0e97SSean Christopherson 
kvm_vcpu_is_illegal_gpa(struct kvm_vcpu * vcpu,gpa_t gpa)51dc46515cSSean Christopherson static inline bool kvm_vcpu_is_illegal_gpa(struct kvm_vcpu *vcpu, gpa_t gpa)
52dc46515cSSean Christopherson {
534bda0e97SSean Christopherson 	return !kvm_vcpu_is_legal_gpa(vcpu, gpa);
544bda0e97SSean Christopherson }
554bda0e97SSean Christopherson 
kvm_vcpu_is_legal_aligned_gpa(struct kvm_vcpu * vcpu,gpa_t gpa,gpa_t alignment)56da6c6a7cSSean Christopherson static inline bool kvm_vcpu_is_legal_aligned_gpa(struct kvm_vcpu *vcpu,
57da6c6a7cSSean Christopherson 						 gpa_t gpa, gpa_t alignment)
58da6c6a7cSSean Christopherson {
59da6c6a7cSSean Christopherson 	return IS_ALIGNED(gpa, alignment) && kvm_vcpu_is_legal_gpa(vcpu, gpa);
60da6c6a7cSSean Christopherson }
61da6c6a7cSSean Christopherson 
page_address_valid(struct kvm_vcpu * vcpu,gpa_t gpa)624bda0e97SSean Christopherson static inline bool page_address_valid(struct kvm_vcpu *vcpu, gpa_t gpa)
634bda0e97SSean Christopherson {
64da6c6a7cSSean Christopherson 	return kvm_vcpu_is_legal_aligned_gpa(vcpu, gpa, PAGE_SIZE);
65dc46515cSSean Christopherson }
66dc46515cSSean Christopherson 
cpuid_entry_override(struct kvm_cpuid_entry2 * entry,unsigned int leaf)67bd791999SSean Christopherson static __always_inline void cpuid_entry_override(struct kvm_cpuid_entry2 *entry,
68462f8ddeSSean Christopherson 						 unsigned int leaf)
69e745e37dSSean Christopherson {
70e745e37dSSean Christopherson 	u32 *reg = cpuid_entry_get_reg(entry, leaf * 32);
71e745e37dSSean Christopherson 
7266a6950fSSean Christopherson 	BUILD_BUG_ON(leaf >= ARRAY_SIZE(kvm_cpu_caps));
73bd791999SSean Christopherson 	*reg = kvm_cpu_caps[leaf];
74e745e37dSSean Christopherson }
75e745e37dSSean Christopherson 
guest_cpuid_get_register(struct kvm_vcpu * vcpu,unsigned int x86_feature)764c61534aSSean Christopherson static __always_inline u32 *guest_cpuid_get_register(struct kvm_vcpu *vcpu,
774c61534aSSean Christopherson 						     unsigned int x86_feature)
784c61534aSSean Christopherson {
794c61534aSSean Christopherson 	const struct cpuid_reg cpuid = x86_feature_cpuid(x86_feature);
804c61534aSSean Christopherson 	struct kvm_cpuid_entry2 *entry;
814c61534aSSean Christopherson 
82277ad7d5SSean Christopherson 	entry = kvm_find_cpuid_entry_index(vcpu, cpuid.function, cpuid.index);
834c61534aSSean Christopherson 	if (!entry)
844c61534aSSean Christopherson 		return NULL;
854c61534aSSean Christopherson 
86855c7e9bSSean Christopherson 	return __cpuid_entry_get_reg(entry, cpuid.reg);
874c61534aSSean Christopherson }
884c61534aSSean Christopherson 
guest_cpuid_has(struct kvm_vcpu * vcpu,unsigned int x86_feature)895e12b2bbSSean Christopherson static __always_inline bool guest_cpuid_has(struct kvm_vcpu *vcpu,
905e12b2bbSSean Christopherson 					    unsigned int x86_feature)
91d6321d49SRadim Krčmář {
923be5a60bSSean Christopherson 	u32 *reg;
93d6321d49SRadim Krčmář 
94d6321d49SRadim Krčmář 	reg = guest_cpuid_get_register(vcpu, x86_feature);
95d6321d49SRadim Krčmář 	if (!reg)
96d6321d49SRadim Krčmář 		return false;
9700b27a3eSAvi Kivity 
9887382003SSean Christopherson 	return *reg & __feature_bit(x86_feature);
9958cb628dSJan Kiszka }
10058cb628dSJan Kiszka 
guest_cpuid_clear(struct kvm_vcpu * vcpu,unsigned int x86_feature)1015e12b2bbSSean Christopherson static __always_inline void guest_cpuid_clear(struct kvm_vcpu *vcpu,
1025e12b2bbSSean Christopherson 					      unsigned int x86_feature)
1031b4d56b8SRadim Krčmář {
1043be5a60bSSean Christopherson 	u32 *reg;
1051b4d56b8SRadim Krčmář 
1061b4d56b8SRadim Krčmář 	reg = guest_cpuid_get_register(vcpu, x86_feature);
1071b4d56b8SRadim Krčmář 	if (reg)
10887382003SSean Christopherson 		*reg &= ~__feature_bit(x86_feature);
1091b4d56b8SRadim Krčmář }
1101b4d56b8SRadim Krčmář 
guest_cpuid_is_amd_or_hygon(struct kvm_vcpu * vcpu)11123493d0aSSean Christopherson static inline bool guest_cpuid_is_amd_or_hygon(struct kvm_vcpu *vcpu)
112a0c0feb5SPaolo Bonzini {
113a0c0feb5SPaolo Bonzini 	struct kvm_cpuid_entry2 *best;
114a0c0feb5SPaolo Bonzini 
115277ad7d5SSean Christopherson 	best = kvm_find_cpuid_entry(vcpu, 0);
11623493d0aSSean Christopherson 	return best &&
11723493d0aSSean Christopherson 	       (is_guest_vendor_amd(best->ebx, best->ecx, best->edx) ||
11823493d0aSSean Christopherson 		is_guest_vendor_hygon(best->ebx, best->ecx, best->edx));
119a0c0feb5SPaolo Bonzini }
120a0c0feb5SPaolo Bonzini 
guest_cpuid_is_intel(struct kvm_vcpu * vcpu)121c1df4aacSMaxim Levitsky static inline bool guest_cpuid_is_intel(struct kvm_vcpu *vcpu)
122c1df4aacSMaxim Levitsky {
123c1df4aacSMaxim Levitsky 	struct kvm_cpuid_entry2 *best;
124c1df4aacSMaxim Levitsky 
125277ad7d5SSean Christopherson 	best = kvm_find_cpuid_entry(vcpu, 0);
126c1df4aacSMaxim Levitsky 	return best && is_guest_vendor_intel(best->ebx, best->ecx, best->edx);
127c1df4aacSMaxim Levitsky }
128c1df4aacSMaxim Levitsky 
guest_cpuid_is_amd_compatible(struct kvm_vcpu * vcpu)129bdda0c17SSean Christopherson static inline bool guest_cpuid_is_amd_compatible(struct kvm_vcpu *vcpu)
130bdda0c17SSean Christopherson {
131bdda0c17SSean Christopherson 	return vcpu->arch.is_amd_compatible;
132bdda0c17SSean Christopherson }
133bdda0c17SSean Christopherson 
guest_cpuid_is_intel_compatible(struct kvm_vcpu * vcpu)134bdda0c17SSean Christopherson static inline bool guest_cpuid_is_intel_compatible(struct kvm_vcpu *vcpu)
135bdda0c17SSean Christopherson {
136bdda0c17SSean Christopherson 	return !guest_cpuid_is_amd_compatible(vcpu);
137bdda0c17SSean Christopherson }
138bdda0c17SSean Christopherson 
guest_cpuid_family(struct kvm_vcpu * vcpu)13991713fafSBorislav Petkov static inline int guest_cpuid_family(struct kvm_vcpu *vcpu)
14091713fafSBorislav Petkov {
14191713fafSBorislav Petkov 	struct kvm_cpuid_entry2 *best;
14291713fafSBorislav Petkov 
143277ad7d5SSean Christopherson 	best = kvm_find_cpuid_entry(vcpu, 0x1);
14491713fafSBorislav Petkov 	if (!best)
14591713fafSBorislav Petkov 		return -1;
14691713fafSBorislav Petkov 
14791713fafSBorislav Petkov 	return x86_family(best->eax);
14891713fafSBorislav Petkov }
14991713fafSBorislav Petkov 
guest_cpuid_model(struct kvm_vcpu * vcpu)15091713fafSBorislav Petkov static inline int guest_cpuid_model(struct kvm_vcpu *vcpu)
15191713fafSBorislav Petkov {
15291713fafSBorislav Petkov 	struct kvm_cpuid_entry2 *best;
15391713fafSBorislav Petkov 
154277ad7d5SSean Christopherson 	best = kvm_find_cpuid_entry(vcpu, 0x1);
15591713fafSBorislav Petkov 	if (!best)
15691713fafSBorislav Petkov 		return -1;
15791713fafSBorislav Petkov 
15891713fafSBorislav Petkov 	return x86_model(best->eax);
15991713fafSBorislav Petkov }
16091713fafSBorislav Petkov 
cpuid_model_is_consistent(struct kvm_vcpu * vcpu)16159cc99f6SLike Xu static inline bool cpuid_model_is_consistent(struct kvm_vcpu *vcpu)
16259cc99f6SLike Xu {
16359cc99f6SLike Xu 	return boot_cpu_data.x86_model == guest_cpuid_model(vcpu);
16459cc99f6SLike Xu }
16559cc99f6SLike Xu 
guest_cpuid_stepping(struct kvm_vcpu * vcpu)16691713fafSBorislav Petkov static inline int guest_cpuid_stepping(struct kvm_vcpu *vcpu)
16791713fafSBorislav Petkov {
16891713fafSBorislav Petkov 	struct kvm_cpuid_entry2 *best;
16991713fafSBorislav Petkov 
170277ad7d5SSean Christopherson 	best = kvm_find_cpuid_entry(vcpu, 0x1);
17191713fafSBorislav Petkov 	if (!best)
17291713fafSBorislav Petkov 		return -1;
17391713fafSBorislav Petkov 
17491713fafSBorislav Petkov 	return x86_stepping(best->eax);
17591713fafSBorislav Petkov }
17691713fafSBorislav Petkov 
guest_has_spec_ctrl_msr(struct kvm_vcpu * vcpu)17739485ed9SPaolo Bonzini static inline bool guest_has_spec_ctrl_msr(struct kvm_vcpu *vcpu)
17839485ed9SPaolo Bonzini {
17939485ed9SPaolo Bonzini 	return (guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL) ||
18039485ed9SPaolo Bonzini 		guest_cpuid_has(vcpu, X86_FEATURE_AMD_STIBP) ||
18139485ed9SPaolo Bonzini 		guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBRS) ||
18239485ed9SPaolo Bonzini 		guest_cpuid_has(vcpu, X86_FEATURE_AMD_SSBD));
18339485ed9SPaolo Bonzini }
18439485ed9SPaolo Bonzini 
guest_has_pred_cmd_msr(struct kvm_vcpu * vcpu)18539485ed9SPaolo Bonzini static inline bool guest_has_pred_cmd_msr(struct kvm_vcpu *vcpu)
18639485ed9SPaolo Bonzini {
18739485ed9SPaolo Bonzini 	return (guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL) ||
18839485ed9SPaolo Bonzini 		guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBPB));
18939485ed9SPaolo Bonzini }
19039485ed9SPaolo Bonzini 
supports_cpuid_fault(struct kvm_vcpu * vcpu)191db2336a8SKyle Huey static inline bool supports_cpuid_fault(struct kvm_vcpu *vcpu)
192db2336a8SKyle Huey {
193db2336a8SKyle Huey 	return vcpu->arch.msr_platform_info & MSR_PLATFORM_INFO_CPUID_FAULT;
194db2336a8SKyle Huey }
195db2336a8SKyle Huey 
cpuid_fault_enabled(struct kvm_vcpu * vcpu)196db2336a8SKyle Huey static inline bool cpuid_fault_enabled(struct kvm_vcpu *vcpu)
197db2336a8SKyle Huey {
198db2336a8SKyle Huey 	return vcpu->arch.msr_misc_features_enables &
199db2336a8SKyle Huey 		  MSR_MISC_FEATURES_ENABLES_CPUID_FAULT;
200db2336a8SKyle Huey }
201db2336a8SKyle Huey 
kvm_cpu_cap_clear(unsigned int x86_feature)20266a6950fSSean Christopherson static __always_inline void kvm_cpu_cap_clear(unsigned int x86_feature)
20366a6950fSSean Christopherson {
2044e66c0cbSSean Christopherson 	unsigned int x86_leaf = __feature_leaf(x86_feature);
20566a6950fSSean Christopherson 
20666a6950fSSean Christopherson 	reverse_cpuid_check(x86_leaf);
20766a6950fSSean Christopherson 	kvm_cpu_caps[x86_leaf] &= ~__feature_bit(x86_feature);
20866a6950fSSean Christopherson }
20966a6950fSSean Christopherson 
kvm_cpu_cap_set(unsigned int x86_feature)21066a6950fSSean Christopherson static __always_inline void kvm_cpu_cap_set(unsigned int x86_feature)
21166a6950fSSean Christopherson {
2124e66c0cbSSean Christopherson 	unsigned int x86_leaf = __feature_leaf(x86_feature);
21366a6950fSSean Christopherson 
21466a6950fSSean Christopherson 	reverse_cpuid_check(x86_leaf);
21566a6950fSSean Christopherson 	kvm_cpu_caps[x86_leaf] |= __feature_bit(x86_feature);
21666a6950fSSean Christopherson }
21766a6950fSSean Christopherson 
kvm_cpu_cap_get(unsigned int x86_feature)218c10398b6SSean Christopherson static __always_inline u32 kvm_cpu_cap_get(unsigned int x86_feature)
219c10398b6SSean Christopherson {
2204e66c0cbSSean Christopherson 	unsigned int x86_leaf = __feature_leaf(x86_feature);
221c10398b6SSean Christopherson 
222c10398b6SSean Christopherson 	reverse_cpuid_check(x86_leaf);
223c10398b6SSean Christopherson 	return kvm_cpu_caps[x86_leaf] & __feature_bit(x86_feature);
224c10398b6SSean Christopherson }
225c10398b6SSean Christopherson 
kvm_cpu_cap_has(unsigned int x86_feature)226c10398b6SSean Christopherson static __always_inline bool kvm_cpu_cap_has(unsigned int x86_feature)
227c10398b6SSean Christopherson {
228c10398b6SSean Christopherson 	return !!kvm_cpu_cap_get(x86_feature);
229c10398b6SSean Christopherson }
230c10398b6SSean Christopherson 
kvm_cpu_cap_check_and_set(unsigned int x86_feature)2318721f5b0SSean Christopherson static __always_inline void kvm_cpu_cap_check_and_set(unsigned int x86_feature)
2328721f5b0SSean Christopherson {
2338721f5b0SSean Christopherson 	if (boot_cpu_has(x86_feature))
2348721f5b0SSean Christopherson 		kvm_cpu_cap_set(x86_feature);
2358721f5b0SSean Christopherson }
2368721f5b0SSean Christopherson 
guest_pv_has(struct kvm_vcpu * vcpu,unsigned int kvm_feature)23766570e96SOliver Upton static __always_inline bool guest_pv_has(struct kvm_vcpu *vcpu,
23866570e96SOliver Upton 					 unsigned int kvm_feature)
23966570e96SOliver Upton {
24066570e96SOliver Upton 	if (!vcpu->arch.pv_cpuid.enforce)
24166570e96SOliver Upton 		return true;
24266570e96SOliver Upton 
24366570e96SOliver Upton 	return vcpu->arch.pv_cpuid.features & (1u << kvm_feature);
24466570e96SOliver Upton }
24566570e96SOliver Upton 
24642764413SSean Christopherson enum kvm_governed_features {
24742764413SSean Christopherson #define KVM_GOVERNED_FEATURE(x) KVM_GOVERNED_##x,
24842764413SSean Christopherson #include "governed_features.h"
24942764413SSean Christopherson 	KVM_NR_GOVERNED_FEATURES
25042764413SSean Christopherson };
25142764413SSean Christopherson 
kvm_governed_feature_index(unsigned int x86_feature)25242764413SSean Christopherson static __always_inline int kvm_governed_feature_index(unsigned int x86_feature)
25342764413SSean Christopherson {
25442764413SSean Christopherson 	switch (x86_feature) {
25542764413SSean Christopherson #define KVM_GOVERNED_FEATURE(x) case x: return KVM_GOVERNED_##x;
25642764413SSean Christopherson #include "governed_features.h"
25742764413SSean Christopherson 	default:
25842764413SSean Christopherson 		return -1;
25942764413SSean Christopherson 	}
26042764413SSean Christopherson }
26142764413SSean Christopherson 
kvm_is_governed_feature(unsigned int x86_feature)26242764413SSean Christopherson static __always_inline bool kvm_is_governed_feature(unsigned int x86_feature)
26342764413SSean Christopherson {
26442764413SSean Christopherson 	return kvm_governed_feature_index(x86_feature) >= 0;
26542764413SSean Christopherson }
26642764413SSean Christopherson 
kvm_governed_feature_set(struct kvm_vcpu * vcpu,unsigned int x86_feature)26742764413SSean Christopherson static __always_inline void kvm_governed_feature_set(struct kvm_vcpu *vcpu,
26842764413SSean Christopherson 						     unsigned int x86_feature)
26942764413SSean Christopherson {
27042764413SSean Christopherson 	BUILD_BUG_ON(!kvm_is_governed_feature(x86_feature));
27142764413SSean Christopherson 
27242764413SSean Christopherson 	__set_bit(kvm_governed_feature_index(x86_feature),
27342764413SSean Christopherson 		  vcpu->arch.governed_features.enabled);
27442764413SSean Christopherson }
27542764413SSean Christopherson 
kvm_governed_feature_check_and_set(struct kvm_vcpu * vcpu,unsigned int x86_feature)27642764413SSean Christopherson static __always_inline void kvm_governed_feature_check_and_set(struct kvm_vcpu *vcpu,
27742764413SSean Christopherson 							       unsigned int x86_feature)
27842764413SSean Christopherson {
27942764413SSean Christopherson 	if (kvm_cpu_cap_has(x86_feature) && guest_cpuid_has(vcpu, x86_feature))
28042764413SSean Christopherson 		kvm_governed_feature_set(vcpu, x86_feature);
28142764413SSean Christopherson }
28242764413SSean Christopherson 
guest_can_use(struct kvm_vcpu * vcpu,unsigned int x86_feature)28342764413SSean Christopherson static __always_inline bool guest_can_use(struct kvm_vcpu *vcpu,
28442764413SSean Christopherson 					  unsigned int x86_feature)
28542764413SSean Christopherson {
28642764413SSean Christopherson 	BUILD_BUG_ON(!kvm_is_governed_feature(x86_feature));
28742764413SSean Christopherson 
28842764413SSean Christopherson 	return test_bit(kvm_governed_feature_index(x86_feature),
28942764413SSean Christopherson 			vcpu->arch.governed_features.enabled);
29042764413SSean Christopherson }
29142764413SSean Christopherson 
29200b27a3eSAvi Kivity #endif
293