xref: /openbmc/linux/arch/x86/kvm/cpuid.h (revision a7c48c3f)
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"
691713fafSBorislav Petkov #include <asm/cpu.h>
7d6321d49SRadim Krčmář #include <asm/processor.h>
800b27a3eSAvi Kivity 
9dd598091SNadav Amit int kvm_update_cpuid(struct kvm_vcpu *vcpu);
10a87036adSPaolo Bonzini bool kvm_mpx_supported(void);
1100b27a3eSAvi Kivity struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu,
1200b27a3eSAvi Kivity 					      u32 function, u32 index);
139c15bb1dSBorislav Petkov int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid,
149c15bb1dSBorislav Petkov 			    struct kvm_cpuid_entry2 __user *entries,
159c15bb1dSBorislav Petkov 			    unsigned int type);
1600b27a3eSAvi Kivity int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
1700b27a3eSAvi Kivity 			     struct kvm_cpuid *cpuid,
1800b27a3eSAvi Kivity 			     struct kvm_cpuid_entry __user *entries);
1900b27a3eSAvi Kivity int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu,
2000b27a3eSAvi Kivity 			      struct kvm_cpuid2 *cpuid,
2100b27a3eSAvi Kivity 			      struct kvm_cpuid_entry2 __user *entries);
2200b27a3eSAvi Kivity int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu,
2300b27a3eSAvi Kivity 			      struct kvm_cpuid2 *cpuid,
2400b27a3eSAvi Kivity 			      struct kvm_cpuid_entry2 __user *entries);
25e911eb3bSYu Zhang bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
26e911eb3bSYu Zhang 	       u32 *ecx, u32 *edx, bool check_limit);
2700b27a3eSAvi Kivity 
285a4f55cdSEugene Korenevsky int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu);
295a4f55cdSEugene Korenevsky 
305a4f55cdSEugene Korenevsky static inline int cpuid_maxphyaddr(struct kvm_vcpu *vcpu)
315a4f55cdSEugene Korenevsky {
325a4f55cdSEugene Korenevsky 	return vcpu->arch.maxphyaddr;
335a4f55cdSEugene Korenevsky }
3400b27a3eSAvi Kivity 
35d6321d49SRadim Krčmář struct cpuid_reg {
36d6321d49SRadim Krčmář 	u32 function;
37d6321d49SRadim Krčmář 	u32 index;
38d6321d49SRadim Krčmář 	int reg;
39d6321d49SRadim Krčmář };
4000b27a3eSAvi Kivity 
41d6321d49SRadim Krčmář static const struct cpuid_reg reverse_cpuid[] = {
42d6321d49SRadim Krčmář 	[CPUID_1_EDX]         = {         1, 0, CPUID_EDX},
43d6321d49SRadim Krčmář 	[CPUID_8000_0001_EDX] = {0x80000001, 0, CPUID_EDX},
44d6321d49SRadim Krčmář 	[CPUID_8086_0001_EDX] = {0x80860001, 0, CPUID_EDX},
45d6321d49SRadim Krčmář 	[CPUID_1_ECX]         = {         1, 0, CPUID_ECX},
46d6321d49SRadim Krčmář 	[CPUID_C000_0001_EDX] = {0xc0000001, 0, CPUID_EDX},
4750a671d4SJanakarajan Natarajan 	[CPUID_8000_0001_ECX] = {0x80000001, 0, CPUID_ECX},
48d6321d49SRadim Krčmář 	[CPUID_7_0_EBX]       = {         7, 0, CPUID_EBX},
49d6321d49SRadim Krčmář 	[CPUID_D_1_EAX]       = {       0xd, 1, CPUID_EAX},
50d6321d49SRadim Krčmář 	[CPUID_8000_0008_EBX] = {0x80000008, 0, CPUID_EBX},
51d6321d49SRadim Krčmář 	[CPUID_6_EAX]         = {         6, 0, CPUID_EAX},
52d6321d49SRadim Krčmář 	[CPUID_8000_000A_EDX] = {0x8000000a, 0, CPUID_EDX},
53d6321d49SRadim Krčmář 	[CPUID_7_ECX]         = {         7, 0, CPUID_ECX},
54d6321d49SRadim Krčmář 	[CPUID_8000_0007_EBX] = {0x80000007, 0, CPUID_EBX},
55b7b27aa0SKarimAllah Ahmed 	[CPUID_7_EDX]         = {         7, 0, CPUID_EDX},
56daa0d8c3SSean Christopherson 	[CPUID_7_1_EAX]       = {         7, 1, CPUID_EAX},
57d6321d49SRadim Krčmář };
58d6321d49SRadim Krčmář 
59a7c48c3fSSean Christopherson /*
60a7c48c3fSSean Christopherson  * Reverse CPUID and its derivatives can only be used for hardware-defined
61a7c48c3fSSean Christopherson  * feature words, i.e. words whose bits directly correspond to a CPUID leaf.
62a7c48c3fSSean Christopherson  * Retrieving a feature bit or masking guest CPUID from a Linux-defined word
63a7c48c3fSSean Christopherson  * is nonsensical as the bit number/mask is an arbitrary software-defined value
64a7c48c3fSSean Christopherson  * and can't be used by KVM to query/control guest capabilities.  And obviously
65a7c48c3fSSean Christopherson  * the leaf being queried must have an entry in the lookup table.
66a7c48c3fSSean Christopherson  */
67a7c48c3fSSean Christopherson static __always_inline void reverse_cpuid_check(unsigned x86_leaf)
68a0a2260cSSean Christopherson {
69a7c48c3fSSean Christopherson 	BUILD_BUG_ON(x86_leaf == CPUID_LNX_1);
70a7c48c3fSSean Christopherson 	BUILD_BUG_ON(x86_leaf == CPUID_LNX_2);
71a7c48c3fSSean Christopherson 	BUILD_BUG_ON(x86_leaf == CPUID_LNX_3);
72a7c48c3fSSean Christopherson 	BUILD_BUG_ON(x86_leaf == CPUID_LNX_4);
73a7c48c3fSSean Christopherson 	BUILD_BUG_ON(x86_leaf >= ARRAY_SIZE(reverse_cpuid));
74a7c48c3fSSean Christopherson 	BUILD_BUG_ON(reverse_cpuid[x86_leaf].function == 0);
75a7c48c3fSSean Christopherson }
76a7c48c3fSSean Christopherson 
77a7c48c3fSSean Christopherson /*
78a7c48c3fSSean Christopherson  * Retrieve the bit mask from an X86_FEATURE_* definition.  Features contain
79a7c48c3fSSean Christopherson  * the hardware defined bit number (stored in bits 4:0) and a software defined
80a7c48c3fSSean Christopherson  * "word" (stored in bits 31:5).  The word is used to index into arrays of
81a7c48c3fSSean Christopherson  * bit masks that hold the per-cpu feature capabilities, e.g. this_cpu_has().
82a7c48c3fSSean Christopherson  */
83a7c48c3fSSean Christopherson static __always_inline u32 bit(int x86_feature)
84a7c48c3fSSean Christopherson {
85a7c48c3fSSean Christopherson 	reverse_cpuid_check(x86_feature / 32);
86a7c48c3fSSean Christopherson 	return 1 << (x86_feature & 31);
87a0a2260cSSean Christopherson }
88a0a2260cSSean Christopherson 
89d6321d49SRadim Krčmář static __always_inline struct cpuid_reg x86_feature_cpuid(unsigned x86_feature)
90d6321d49SRadim Krčmář {
91d6321d49SRadim Krčmář 	unsigned x86_leaf = x86_feature / 32;
92d6321d49SRadim Krčmář 
93a7c48c3fSSean Christopherson 	reverse_cpuid_check(x86_leaf);
94d6321d49SRadim Krčmář 	return reverse_cpuid[x86_leaf];
95d6321d49SRadim Krčmář }
96d6321d49SRadim Krčmář 
97d6321d49SRadim Krčmář static __always_inline int *guest_cpuid_get_register(struct kvm_vcpu *vcpu, unsigned x86_feature)
98d6321d49SRadim Krčmář {
99d6321d49SRadim Krčmář 	struct kvm_cpuid_entry2 *entry;
100d6321d49SRadim Krčmář 	const struct cpuid_reg cpuid = x86_feature_cpuid(x86_feature);
101d6321d49SRadim Krčmář 
102d6321d49SRadim Krčmář 	entry = kvm_find_cpuid_entry(vcpu, cpuid.function, cpuid.index);
103d6321d49SRadim Krčmář 	if (!entry)
104d6321d49SRadim Krčmář 		return NULL;
105d6321d49SRadim Krčmář 
106d6321d49SRadim Krčmář 	switch (cpuid.reg) {
107d6321d49SRadim Krčmář 	case CPUID_EAX:
108d6321d49SRadim Krčmář 		return &entry->eax;
109d6321d49SRadim Krčmář 	case CPUID_EBX:
110d6321d49SRadim Krčmář 		return &entry->ebx;
111d6321d49SRadim Krčmář 	case CPUID_ECX:
112d6321d49SRadim Krčmář 		return &entry->ecx;
113d6321d49SRadim Krčmář 	case CPUID_EDX:
114d6321d49SRadim Krčmář 		return &entry->edx;
115d6321d49SRadim Krčmář 	default:
116d6321d49SRadim Krčmář 		BUILD_BUG();
117d6321d49SRadim Krčmář 		return NULL;
118d6321d49SRadim Krčmář 	}
119d6321d49SRadim Krčmář }
120d6321d49SRadim Krčmář 
121d6321d49SRadim Krčmář static __always_inline bool guest_cpuid_has(struct kvm_vcpu *vcpu, unsigned x86_feature)
122d6321d49SRadim Krčmář {
123d6321d49SRadim Krčmář 	int *reg;
124d6321d49SRadim Krčmář 
125d6321d49SRadim Krčmář 	reg = guest_cpuid_get_register(vcpu, x86_feature);
126d6321d49SRadim Krčmář 	if (!reg)
127d6321d49SRadim Krčmář 		return false;
12800b27a3eSAvi Kivity 
129d6321d49SRadim Krčmář 	return *reg & bit(x86_feature);
13058cb628dSJan Kiszka }
13158cb628dSJan Kiszka 
1321b4d56b8SRadim Krčmář static __always_inline void guest_cpuid_clear(struct kvm_vcpu *vcpu, unsigned x86_feature)
1331b4d56b8SRadim Krčmář {
1341b4d56b8SRadim Krčmář 	int *reg;
1351b4d56b8SRadim Krčmář 
1361b4d56b8SRadim Krčmář 	reg = guest_cpuid_get_register(vcpu, x86_feature);
1371b4d56b8SRadim Krčmář 	if (reg)
1381b4d56b8SRadim Krčmář 		*reg &= ~bit(x86_feature);
1391b4d56b8SRadim Krčmář }
1401b4d56b8SRadim Krčmář 
141a0c0feb5SPaolo Bonzini static inline bool guest_cpuid_is_amd(struct kvm_vcpu *vcpu)
142a0c0feb5SPaolo Bonzini {
143a0c0feb5SPaolo Bonzini 	struct kvm_cpuid_entry2 *best;
144a0c0feb5SPaolo Bonzini 
145a0c0feb5SPaolo Bonzini 	best = kvm_find_cpuid_entry(vcpu, 0, 0);
146a0c0feb5SPaolo Bonzini 	return best && best->ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx;
147a0c0feb5SPaolo Bonzini }
148a0c0feb5SPaolo Bonzini 
14991713fafSBorislav Petkov static inline int guest_cpuid_family(struct kvm_vcpu *vcpu)
15091713fafSBorislav Petkov {
15191713fafSBorislav Petkov 	struct kvm_cpuid_entry2 *best;
15291713fafSBorislav Petkov 
15391713fafSBorislav Petkov 	best = kvm_find_cpuid_entry(vcpu, 0x1, 0);
15491713fafSBorislav Petkov 	if (!best)
15591713fafSBorislav Petkov 		return -1;
15691713fafSBorislav Petkov 
15791713fafSBorislav Petkov 	return x86_family(best->eax);
15891713fafSBorislav Petkov }
15991713fafSBorislav Petkov 
16091713fafSBorislav Petkov static inline int guest_cpuid_model(struct kvm_vcpu *vcpu)
16191713fafSBorislav Petkov {
16291713fafSBorislav Petkov 	struct kvm_cpuid_entry2 *best;
16391713fafSBorislav Petkov 
16491713fafSBorislav Petkov 	best = kvm_find_cpuid_entry(vcpu, 0x1, 0);
16591713fafSBorislav Petkov 	if (!best)
16691713fafSBorislav Petkov 		return -1;
16791713fafSBorislav Petkov 
16891713fafSBorislav Petkov 	return x86_model(best->eax);
16991713fafSBorislav Petkov }
17091713fafSBorislav Petkov 
17191713fafSBorislav Petkov static inline int guest_cpuid_stepping(struct kvm_vcpu *vcpu)
17291713fafSBorislav Petkov {
17391713fafSBorislav Petkov 	struct kvm_cpuid_entry2 *best;
17491713fafSBorislav Petkov 
17591713fafSBorislav Petkov 	best = kvm_find_cpuid_entry(vcpu, 0x1, 0);
17691713fafSBorislav Petkov 	if (!best)
17791713fafSBorislav Petkov 		return -1;
17891713fafSBorislav Petkov 
17991713fafSBorislav Petkov 	return x86_stepping(best->eax);
18091713fafSBorislav Petkov }
18191713fafSBorislav Petkov 
182db2336a8SKyle Huey static inline bool supports_cpuid_fault(struct kvm_vcpu *vcpu)
183db2336a8SKyle Huey {
184db2336a8SKyle Huey 	return vcpu->arch.msr_platform_info & MSR_PLATFORM_INFO_CPUID_FAULT;
185db2336a8SKyle Huey }
186db2336a8SKyle Huey 
187db2336a8SKyle Huey static inline bool cpuid_fault_enabled(struct kvm_vcpu *vcpu)
188db2336a8SKyle Huey {
189db2336a8SKyle Huey 	return vcpu->arch.msr_misc_features_enables &
190db2336a8SKyle Huey 		  MSR_MISC_FEATURES_ENABLES_CPUID_FAULT;
191db2336a8SKyle Huey }
192db2336a8SKyle Huey 
19300b27a3eSAvi Kivity #endif
194