xref: /openbmc/linux/arch/x86/kvm/cpuid.h (revision bdda0c17)
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 
35be50b206SGuang Zeng u32 xstate_required_size(u64 xstate_bv, bool compacted);
36be50b206SGuang Zeng 
375a4f55cdSEugene Korenevsky int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu);
38a8ac864aSSean Christopherson u64 kvm_vcpu_reserved_gpa_bits_raw(struct kvm_vcpu *vcpu);
395a4f55cdSEugene Korenevsky 
cpuid_maxphyaddr(struct kvm_vcpu * vcpu)405a4f55cdSEugene Korenevsky static inline int cpuid_maxphyaddr(struct kvm_vcpu *vcpu)
415a4f55cdSEugene Korenevsky {
425a4f55cdSEugene Korenevsky 	return vcpu->arch.maxphyaddr;
435a4f55cdSEugene Korenevsky }
4400b27a3eSAvi Kivity 
kvm_vcpu_is_legal_gpa(struct kvm_vcpu * vcpu,gpa_t gpa)454bda0e97SSean Christopherson static inline bool kvm_vcpu_is_legal_gpa(struct kvm_vcpu *vcpu, gpa_t gpa)
464bda0e97SSean Christopherson {
47ca29e145SSean Christopherson 	return !(gpa & vcpu->arch.reserved_gpa_bits);
484bda0e97SSean Christopherson }
494bda0e97SSean Christopherson 
kvm_vcpu_is_illegal_gpa(struct kvm_vcpu * vcpu,gpa_t gpa)50dc46515cSSean Christopherson static inline bool kvm_vcpu_is_illegal_gpa(struct kvm_vcpu *vcpu, gpa_t gpa)
51dc46515cSSean Christopherson {
524bda0e97SSean Christopherson 	return !kvm_vcpu_is_legal_gpa(vcpu, gpa);
534bda0e97SSean Christopherson }
544bda0e97SSean Christopherson 
kvm_vcpu_is_legal_aligned_gpa(struct kvm_vcpu * vcpu,gpa_t gpa,gpa_t alignment)55da6c6a7cSSean Christopherson static inline bool kvm_vcpu_is_legal_aligned_gpa(struct kvm_vcpu *vcpu,
56da6c6a7cSSean Christopherson 						 gpa_t gpa, gpa_t alignment)
57da6c6a7cSSean Christopherson {
58da6c6a7cSSean Christopherson 	return IS_ALIGNED(gpa, alignment) && kvm_vcpu_is_legal_gpa(vcpu, gpa);
59da6c6a7cSSean Christopherson }
60da6c6a7cSSean Christopherson 
page_address_valid(struct kvm_vcpu * vcpu,gpa_t gpa)614bda0e97SSean Christopherson static inline bool page_address_valid(struct kvm_vcpu *vcpu, gpa_t gpa)
624bda0e97SSean Christopherson {
63da6c6a7cSSean Christopherson 	return kvm_vcpu_is_legal_aligned_gpa(vcpu, gpa, PAGE_SIZE);
64dc46515cSSean Christopherson }
65dc46515cSSean Christopherson 
cpuid_entry_override(struct kvm_cpuid_entry2 * entry,unsigned int leaf)66bd791999SSean Christopherson static __always_inline void cpuid_entry_override(struct kvm_cpuid_entry2 *entry,
67462f8ddeSSean Christopherson 						 unsigned int leaf)
68e745e37dSSean Christopherson {
69e745e37dSSean Christopherson 	u32 *reg = cpuid_entry_get_reg(entry, leaf * 32);
70e745e37dSSean Christopherson 
7166a6950fSSean Christopherson 	BUILD_BUG_ON(leaf >= ARRAY_SIZE(kvm_cpu_caps));
72bd791999SSean Christopherson 	*reg = kvm_cpu_caps[leaf];
73e745e37dSSean Christopherson }
74e745e37dSSean Christopherson 
guest_cpuid_get_register(struct kvm_vcpu * vcpu,unsigned int x86_feature)754c61534aSSean Christopherson static __always_inline u32 *guest_cpuid_get_register(struct kvm_vcpu *vcpu,
764c61534aSSean Christopherson 						     unsigned int x86_feature)
774c61534aSSean Christopherson {
784c61534aSSean Christopherson 	const struct cpuid_reg cpuid = x86_feature_cpuid(x86_feature);
794c61534aSSean Christopherson 	struct kvm_cpuid_entry2 *entry;
804c61534aSSean Christopherson 
81277ad7d5SSean Christopherson 	entry = kvm_find_cpuid_entry_index(vcpu, cpuid.function, cpuid.index);
824c61534aSSean Christopherson 	if (!entry)
834c61534aSSean Christopherson 		return NULL;
844c61534aSSean Christopherson 
85855c7e9bSSean Christopherson 	return __cpuid_entry_get_reg(entry, cpuid.reg);
864c61534aSSean Christopherson }
874c61534aSSean Christopherson 
guest_cpuid_has(struct kvm_vcpu * vcpu,unsigned int x86_feature)885e12b2bbSSean Christopherson static __always_inline bool guest_cpuid_has(struct kvm_vcpu *vcpu,
895e12b2bbSSean Christopherson 					    unsigned int x86_feature)
90d6321d49SRadim Krčmář {
913be5a60bSSean Christopherson 	u32 *reg;
92d6321d49SRadim Krčmář 
93d6321d49SRadim Krčmář 	reg = guest_cpuid_get_register(vcpu, x86_feature);
94d6321d49SRadim Krčmář 	if (!reg)
95d6321d49SRadim Krčmář 		return false;
9600b27a3eSAvi Kivity 
9787382003SSean Christopherson 	return *reg & __feature_bit(x86_feature);
9858cb628dSJan Kiszka }
9958cb628dSJan Kiszka 
guest_cpuid_clear(struct kvm_vcpu * vcpu,unsigned int x86_feature)1005e12b2bbSSean Christopherson static __always_inline void guest_cpuid_clear(struct kvm_vcpu *vcpu,
1015e12b2bbSSean Christopherson 					      unsigned int x86_feature)
1021b4d56b8SRadim Krčmář {
1033be5a60bSSean Christopherson 	u32 *reg;
1041b4d56b8SRadim Krčmář 
1051b4d56b8SRadim Krčmář 	reg = guest_cpuid_get_register(vcpu, x86_feature);
1061b4d56b8SRadim Krčmář 	if (reg)
10787382003SSean Christopherson 		*reg &= ~__feature_bit(x86_feature);
1081b4d56b8SRadim Krčmář }
1091b4d56b8SRadim Krčmář 
guest_cpuid_is_amd_or_hygon(struct kvm_vcpu * vcpu)11023493d0aSSean Christopherson static inline bool guest_cpuid_is_amd_or_hygon(struct kvm_vcpu *vcpu)
111a0c0feb5SPaolo Bonzini {
112a0c0feb5SPaolo Bonzini 	struct kvm_cpuid_entry2 *best;
113a0c0feb5SPaolo Bonzini 
114277ad7d5SSean Christopherson 	best = kvm_find_cpuid_entry(vcpu, 0);
11523493d0aSSean Christopherson 	return best &&
11623493d0aSSean Christopherson 	       (is_guest_vendor_amd(best->ebx, best->ecx, best->edx) ||
11723493d0aSSean Christopherson 		is_guest_vendor_hygon(best->ebx, best->ecx, best->edx));
118a0c0feb5SPaolo Bonzini }
119a0c0feb5SPaolo Bonzini 
guest_cpuid_is_intel(struct kvm_vcpu * vcpu)120c1df4aacSMaxim Levitsky static inline bool guest_cpuid_is_intel(struct kvm_vcpu *vcpu)
121c1df4aacSMaxim Levitsky {
122c1df4aacSMaxim Levitsky 	struct kvm_cpuid_entry2 *best;
123c1df4aacSMaxim Levitsky 
124277ad7d5SSean Christopherson 	best = kvm_find_cpuid_entry(vcpu, 0);
125c1df4aacSMaxim Levitsky 	return best && is_guest_vendor_intel(best->ebx, best->ecx, best->edx);
126c1df4aacSMaxim Levitsky }
127c1df4aacSMaxim Levitsky 
guest_cpuid_is_amd_compatible(struct kvm_vcpu * vcpu)128bdda0c17SSean Christopherson static inline bool guest_cpuid_is_amd_compatible(struct kvm_vcpu *vcpu)
129bdda0c17SSean Christopherson {
130bdda0c17SSean Christopherson 	return vcpu->arch.is_amd_compatible;
131bdda0c17SSean Christopherson }
132bdda0c17SSean Christopherson 
guest_cpuid_is_intel_compatible(struct kvm_vcpu * vcpu)133bdda0c17SSean Christopherson static inline bool guest_cpuid_is_intel_compatible(struct kvm_vcpu *vcpu)
134bdda0c17SSean Christopherson {
135bdda0c17SSean Christopherson 	return !guest_cpuid_is_amd_compatible(vcpu);
136bdda0c17SSean Christopherson }
137bdda0c17SSean Christopherson 
guest_cpuid_family(struct kvm_vcpu * vcpu)13891713fafSBorislav Petkov static inline int guest_cpuid_family(struct kvm_vcpu *vcpu)
13991713fafSBorislav Petkov {
14091713fafSBorislav Petkov 	struct kvm_cpuid_entry2 *best;
14191713fafSBorislav Petkov 
142277ad7d5SSean Christopherson 	best = kvm_find_cpuid_entry(vcpu, 0x1);
14391713fafSBorislav Petkov 	if (!best)
14491713fafSBorislav Petkov 		return -1;
14591713fafSBorislav Petkov 
14691713fafSBorislav Petkov 	return x86_family(best->eax);
14791713fafSBorislav Petkov }
14891713fafSBorislav Petkov 
guest_cpuid_model(struct kvm_vcpu * vcpu)14991713fafSBorislav Petkov static inline int guest_cpuid_model(struct kvm_vcpu *vcpu)
15091713fafSBorislav Petkov {
15191713fafSBorislav Petkov 	struct kvm_cpuid_entry2 *best;
15291713fafSBorislav Petkov 
153277ad7d5SSean Christopherson 	best = kvm_find_cpuid_entry(vcpu, 0x1);
15491713fafSBorislav Petkov 	if (!best)
15591713fafSBorislav Petkov 		return -1;
15691713fafSBorislav Petkov 
15791713fafSBorislav Petkov 	return x86_model(best->eax);
15891713fafSBorislav Petkov }
15991713fafSBorislav Petkov 
cpuid_model_is_consistent(struct kvm_vcpu * vcpu)16059cc99f6SLike Xu static inline bool cpuid_model_is_consistent(struct kvm_vcpu *vcpu)
16159cc99f6SLike Xu {
16259cc99f6SLike Xu 	return boot_cpu_data.x86_model == guest_cpuid_model(vcpu);
16359cc99f6SLike Xu }
16459cc99f6SLike Xu 
guest_cpuid_stepping(struct kvm_vcpu * vcpu)16591713fafSBorislav Petkov static inline int guest_cpuid_stepping(struct kvm_vcpu *vcpu)
16691713fafSBorislav Petkov {
16791713fafSBorislav Petkov 	struct kvm_cpuid_entry2 *best;
16891713fafSBorislav Petkov 
169277ad7d5SSean Christopherson 	best = kvm_find_cpuid_entry(vcpu, 0x1);
17091713fafSBorislav Petkov 	if (!best)
17191713fafSBorislav Petkov 		return -1;
17291713fafSBorislav Petkov 
17391713fafSBorislav Petkov 	return x86_stepping(best->eax);
17491713fafSBorislav Petkov }
17591713fafSBorislav Petkov 
guest_has_spec_ctrl_msr(struct kvm_vcpu * vcpu)17639485ed9SPaolo Bonzini static inline bool guest_has_spec_ctrl_msr(struct kvm_vcpu *vcpu)
17739485ed9SPaolo Bonzini {
17839485ed9SPaolo Bonzini 	return (guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL) ||
17939485ed9SPaolo Bonzini 		guest_cpuid_has(vcpu, X86_FEATURE_AMD_STIBP) ||
18039485ed9SPaolo Bonzini 		guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBRS) ||
18139485ed9SPaolo Bonzini 		guest_cpuid_has(vcpu, X86_FEATURE_AMD_SSBD));
18239485ed9SPaolo Bonzini }
18339485ed9SPaolo Bonzini 
guest_has_pred_cmd_msr(struct kvm_vcpu * vcpu)18439485ed9SPaolo Bonzini static inline bool guest_has_pred_cmd_msr(struct kvm_vcpu *vcpu)
18539485ed9SPaolo Bonzini {
18639485ed9SPaolo Bonzini 	return (guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL) ||
18739485ed9SPaolo Bonzini 		guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBPB));
18839485ed9SPaolo Bonzini }
18939485ed9SPaolo Bonzini 
supports_cpuid_fault(struct kvm_vcpu * vcpu)190db2336a8SKyle Huey static inline bool supports_cpuid_fault(struct kvm_vcpu *vcpu)
191db2336a8SKyle Huey {
192db2336a8SKyle Huey 	return vcpu->arch.msr_platform_info & MSR_PLATFORM_INFO_CPUID_FAULT;
193db2336a8SKyle Huey }
194db2336a8SKyle Huey 
cpuid_fault_enabled(struct kvm_vcpu * vcpu)195db2336a8SKyle Huey static inline bool cpuid_fault_enabled(struct kvm_vcpu *vcpu)
196db2336a8SKyle Huey {
197db2336a8SKyle Huey 	return vcpu->arch.msr_misc_features_enables &
198db2336a8SKyle Huey 		  MSR_MISC_FEATURES_ENABLES_CPUID_FAULT;
199db2336a8SKyle Huey }
200db2336a8SKyle Huey 
kvm_cpu_cap_clear(unsigned int x86_feature)20166a6950fSSean Christopherson static __always_inline void kvm_cpu_cap_clear(unsigned int x86_feature)
20266a6950fSSean Christopherson {
2034e66c0cbSSean Christopherson 	unsigned int x86_leaf = __feature_leaf(x86_feature);
20466a6950fSSean Christopherson 
20566a6950fSSean Christopherson 	reverse_cpuid_check(x86_leaf);
20666a6950fSSean Christopherson 	kvm_cpu_caps[x86_leaf] &= ~__feature_bit(x86_feature);
20766a6950fSSean Christopherson }
20866a6950fSSean Christopherson 
kvm_cpu_cap_set(unsigned int x86_feature)20966a6950fSSean Christopherson static __always_inline void kvm_cpu_cap_set(unsigned int x86_feature)
21066a6950fSSean Christopherson {
2114e66c0cbSSean Christopherson 	unsigned int x86_leaf = __feature_leaf(x86_feature);
21266a6950fSSean Christopherson 
21366a6950fSSean Christopherson 	reverse_cpuid_check(x86_leaf);
21466a6950fSSean Christopherson 	kvm_cpu_caps[x86_leaf] |= __feature_bit(x86_feature);
21566a6950fSSean Christopherson }
21666a6950fSSean Christopherson 
kvm_cpu_cap_get(unsigned int x86_feature)217c10398b6SSean Christopherson static __always_inline u32 kvm_cpu_cap_get(unsigned int x86_feature)
218c10398b6SSean Christopherson {
2194e66c0cbSSean Christopherson 	unsigned int x86_leaf = __feature_leaf(x86_feature);
220c10398b6SSean Christopherson 
221c10398b6SSean Christopherson 	reverse_cpuid_check(x86_leaf);
222c10398b6SSean Christopherson 	return kvm_cpu_caps[x86_leaf] & __feature_bit(x86_feature);
223c10398b6SSean Christopherson }
224c10398b6SSean Christopherson 
kvm_cpu_cap_has(unsigned int x86_feature)225c10398b6SSean Christopherson static __always_inline bool kvm_cpu_cap_has(unsigned int x86_feature)
226c10398b6SSean Christopherson {
227c10398b6SSean Christopherson 	return !!kvm_cpu_cap_get(x86_feature);
228c10398b6SSean Christopherson }
229c10398b6SSean Christopherson 
kvm_cpu_cap_check_and_set(unsigned int x86_feature)2308721f5b0SSean Christopherson static __always_inline void kvm_cpu_cap_check_and_set(unsigned int x86_feature)
2318721f5b0SSean Christopherson {
2328721f5b0SSean Christopherson 	if (boot_cpu_has(x86_feature))
2338721f5b0SSean Christopherson 		kvm_cpu_cap_set(x86_feature);
2348721f5b0SSean Christopherson }
2358721f5b0SSean Christopherson 
guest_pv_has(struct kvm_vcpu * vcpu,unsigned int kvm_feature)23666570e96SOliver Upton static __always_inline bool guest_pv_has(struct kvm_vcpu *vcpu,
23766570e96SOliver Upton 					 unsigned int kvm_feature)
23866570e96SOliver Upton {
23966570e96SOliver Upton 	if (!vcpu->arch.pv_cpuid.enforce)
24066570e96SOliver Upton 		return true;
24166570e96SOliver Upton 
24266570e96SOliver Upton 	return vcpu->arch.pv_cpuid.features & (1u << kvm_feature);
24366570e96SOliver Upton }
24466570e96SOliver Upton 
24542764413SSean Christopherson enum kvm_governed_features {
24642764413SSean Christopherson #define KVM_GOVERNED_FEATURE(x) KVM_GOVERNED_##x,
24742764413SSean Christopherson #include "governed_features.h"
24842764413SSean Christopherson 	KVM_NR_GOVERNED_FEATURES
24942764413SSean Christopherson };
25042764413SSean Christopherson 
kvm_governed_feature_index(unsigned int x86_feature)25142764413SSean Christopherson static __always_inline int kvm_governed_feature_index(unsigned int x86_feature)
25242764413SSean Christopherson {
25342764413SSean Christopherson 	switch (x86_feature) {
25442764413SSean Christopherson #define KVM_GOVERNED_FEATURE(x) case x: return KVM_GOVERNED_##x;
25542764413SSean Christopherson #include "governed_features.h"
25642764413SSean Christopherson 	default:
25742764413SSean Christopherson 		return -1;
25842764413SSean Christopherson 	}
25942764413SSean Christopherson }
26042764413SSean Christopherson 
kvm_is_governed_feature(unsigned int x86_feature)26142764413SSean Christopherson static __always_inline bool kvm_is_governed_feature(unsigned int x86_feature)
26242764413SSean Christopherson {
26342764413SSean Christopherson 	return kvm_governed_feature_index(x86_feature) >= 0;
26442764413SSean Christopherson }
26542764413SSean Christopherson 
kvm_governed_feature_set(struct kvm_vcpu * vcpu,unsigned int x86_feature)26642764413SSean Christopherson static __always_inline void kvm_governed_feature_set(struct kvm_vcpu *vcpu,
26742764413SSean Christopherson 						     unsigned int x86_feature)
26842764413SSean Christopherson {
26942764413SSean Christopherson 	BUILD_BUG_ON(!kvm_is_governed_feature(x86_feature));
27042764413SSean Christopherson 
27142764413SSean Christopherson 	__set_bit(kvm_governed_feature_index(x86_feature),
27242764413SSean Christopherson 		  vcpu->arch.governed_features.enabled);
27342764413SSean Christopherson }
27442764413SSean Christopherson 
kvm_governed_feature_check_and_set(struct kvm_vcpu * vcpu,unsigned int x86_feature)27542764413SSean Christopherson static __always_inline void kvm_governed_feature_check_and_set(struct kvm_vcpu *vcpu,
27642764413SSean Christopherson 							       unsigned int x86_feature)
27742764413SSean Christopherson {
27842764413SSean Christopherson 	if (kvm_cpu_cap_has(x86_feature) && guest_cpuid_has(vcpu, x86_feature))
27942764413SSean Christopherson 		kvm_governed_feature_set(vcpu, x86_feature);
28042764413SSean Christopherson }
28142764413SSean Christopherson 
guest_can_use(struct kvm_vcpu * vcpu,unsigned int x86_feature)28242764413SSean Christopherson static __always_inline bool guest_can_use(struct kvm_vcpu *vcpu,
28342764413SSean Christopherson 					  unsigned int x86_feature)
28442764413SSean Christopherson {
28542764413SSean Christopherson 	BUILD_BUG_ON(!kvm_is_governed_feature(x86_feature));
28642764413SSean Christopherson 
28742764413SSean Christopherson 	return test_bit(kvm_governed_feature_index(x86_feature),
28842764413SSean Christopherson 			vcpu->arch.governed_features.enabled);
28942764413SSean Christopherson }
29042764413SSean Christopherson 
29100b27a3eSAvi Kivity #endif
292