33
44#include "x86.h"
55#include <asm/cpu.h>
6+ #include <asm/processor.h>
67
78int kvm_update_cpuid (struct kvm_vcpu * vcpu );
89bool kvm_mpx_supported (void );
@@ -29,95 +30,78 @@ static inline int cpuid_maxphyaddr(struct kvm_vcpu *vcpu)
2930 return vcpu -> arch .maxphyaddr ;
3031}
3132
32- static inline bool guest_cpuid_has_xsave (struct kvm_vcpu * vcpu )
33- {
34- struct kvm_cpuid_entry2 * best ;
33+ struct cpuid_reg {
34+ u32 function ;
35+ u32 index ;
36+ int reg ;
37+ };
3538
36- if (!static_cpu_has (X86_FEATURE_XSAVE ))
37- return false;
38-
39- best = kvm_find_cpuid_entry (vcpu , 1 , 0 );
40- return best && (best -> ecx & bit (X86_FEATURE_XSAVE ));
41- }
39+ static const struct cpuid_reg reverse_cpuid [] = {
40+ [CPUID_1_EDX ] = { 1 , 0 , CPUID_EDX },
41+ [CPUID_8000_0001_EDX ] = {0x80000001 , 0 , CPUID_EDX },
42+ [CPUID_8086_0001_EDX ] = {0x80860001 , 0 , CPUID_EDX },
43+ [CPUID_1_ECX ] = { 1 , 0 , CPUID_ECX },
44+ [CPUID_C000_0001_EDX ] = {0xc0000001 , 0 , CPUID_EDX },
45+ [CPUID_8000_0001_ECX ] = {0xc0000001 , 0 , CPUID_ECX },
46+ [CPUID_7_0_EBX ] = { 7 , 0 , CPUID_EBX },
47+ [CPUID_D_1_EAX ] = { 0xd , 1 , CPUID_EAX },
48+ [CPUID_F_0_EDX ] = { 0xf , 0 , CPUID_EDX },
49+ [CPUID_F_1_EDX ] = { 0xf , 1 , CPUID_EDX },
50+ [CPUID_8000_0008_EBX ] = {0x80000008 , 0 , CPUID_EBX },
51+ [CPUID_6_EAX ] = { 6 , 0 , CPUID_EAX },
52+ [CPUID_8000_000A_EDX ] = {0x8000000a , 0 , CPUID_EDX },
53+ [CPUID_7_ECX ] = { 7 , 0 , CPUID_ECX },
54+ [CPUID_8000_0007_EBX ] = {0x80000007 , 0 , CPUID_EBX },
55+ };
4256
43- static inline bool guest_cpuid_has_mtrr ( struct kvm_vcpu * vcpu )
57+ static __always_inline struct cpuid_reg x86_feature_cpuid ( unsigned x86_feature )
4458{
45- struct kvm_cpuid_entry2 * best ;
59+ unsigned x86_leaf = x86_feature / 32 ;
4660
47- best = kvm_find_cpuid_entry ( vcpu , 1 , 0 );
48- return best && ( best -> edx & bit ( X86_FEATURE_MTRR ));
49- }
61+ BUILD_BUG_ON (! __builtin_constant_p ( x86_leaf ) );
62+ BUILD_BUG_ON ( x86_leaf >= ARRAY_SIZE ( reverse_cpuid ));
63+ BUILD_BUG_ON ( reverse_cpuid [ x86_leaf ]. function == 0 );
5064
51- static inline bool guest_cpuid_has_tsc_adjust (struct kvm_vcpu * vcpu )
52- {
53- struct kvm_cpuid_entry2 * best ;
54-
55- best = kvm_find_cpuid_entry (vcpu , 7 , 0 );
56- return best && (best -> ebx & bit (X86_FEATURE_TSC_ADJUST ));
57- }
58-
59- static inline bool guest_cpuid_has_smep (struct kvm_vcpu * vcpu )
60- {
61- struct kvm_cpuid_entry2 * best ;
62-
63- best = kvm_find_cpuid_entry (vcpu , 7 , 0 );
64- return best && (best -> ebx & bit (X86_FEATURE_SMEP ));
65+ return reverse_cpuid [x86_leaf ];
6566}
6667
67- static inline bool guest_cpuid_has_smap (struct kvm_vcpu * vcpu )
68+ static __always_inline int * guest_cpuid_get_register (struct kvm_vcpu * vcpu , unsigned x86_feature )
6869{
69- struct kvm_cpuid_entry2 * best ;
70-
71- best = kvm_find_cpuid_entry (vcpu , 7 , 0 );
72- return best && (best -> ebx & bit (X86_FEATURE_SMAP ));
73- }
74-
75- static inline bool guest_cpuid_has_fsgsbase (struct kvm_vcpu * vcpu )
76- {
77- struct kvm_cpuid_entry2 * best ;
78-
79- best = kvm_find_cpuid_entry (vcpu , 7 , 0 );
80- return best && (best -> ebx & bit (X86_FEATURE_FSGSBASE ));
81- }
82-
83- static inline bool guest_cpuid_has_pku (struct kvm_vcpu * vcpu )
84- {
85- struct kvm_cpuid_entry2 * best ;
86-
87- best = kvm_find_cpuid_entry (vcpu , 7 , 0 );
88- return best && (best -> ecx & bit (X86_FEATURE_PKU ));
89- }
90-
91- static inline bool guest_cpuid_has_longmode (struct kvm_vcpu * vcpu )
92- {
93- struct kvm_cpuid_entry2 * best ;
94-
95- best = kvm_find_cpuid_entry (vcpu , 0x80000001 , 0 );
96- return best && (best -> edx & bit (X86_FEATURE_LM ));
97- }
70+ struct kvm_cpuid_entry2 * entry ;
71+ const struct cpuid_reg cpuid = x86_feature_cpuid (x86_feature );
9872
99- static inline bool guest_cpuid_has_osvw ( struct kvm_vcpu * vcpu )
100- {
101- struct kvm_cpuid_entry2 * best ;
73+ entry = kvm_find_cpuid_entry ( vcpu , cpuid . function , cpuid . index );
74+ if (! entry )
75+ return NULL ;
10276
103- best = kvm_find_cpuid_entry (vcpu , 0x80000001 , 0 );
104- return best && (best -> ecx & bit (X86_FEATURE_OSVW ));
77+ switch (cpuid .reg ) {
78+ case CPUID_EAX :
79+ return & entry -> eax ;
80+ case CPUID_EBX :
81+ return & entry -> ebx ;
82+ case CPUID_ECX :
83+ return & entry -> ecx ;
84+ case CPUID_EDX :
85+ return & entry -> edx ;
86+ default :
87+ BUILD_BUG ();
88+ return NULL ;
89+ }
10590}
10691
107- static inline bool guest_cpuid_has_pcid (struct kvm_vcpu * vcpu )
92+ static __always_inline bool guest_cpuid_has (struct kvm_vcpu * vcpu , unsigned x86_feature )
10893{
109- struct kvm_cpuid_entry2 * best ;
94+ int * reg ;
11095
111- best = kvm_find_cpuid_entry ( vcpu , 1 , 0 );
112- return best && ( best -> ecx & bit ( X86_FEATURE_PCID ));
113- }
96+ if ( x86_feature == X86_FEATURE_XSAVE &&
97+ ! static_cpu_has ( X86_FEATURE_XSAVE ))
98+ return false;
11499
115- static inline bool guest_cpuid_has_x2apic ( struct kvm_vcpu * vcpu )
116- {
117- struct kvm_cpuid_entry2 * best ;
100+ reg = guest_cpuid_get_register ( vcpu , x86_feature );
101+ if (! reg )
102+ return false ;
118103
119- best = kvm_find_cpuid_entry (vcpu , 1 , 0 );
120- return best && (best -> ecx & bit (X86_FEATURE_X2APIC ));
104+ return * reg & bit (x86_feature );
121105}
122106
123107static inline bool guest_cpuid_is_amd (struct kvm_vcpu * vcpu )
@@ -128,46 +112,6 @@ static inline bool guest_cpuid_is_amd(struct kvm_vcpu *vcpu)
128112 return best && best -> ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx ;
129113}
130114
131- static inline bool guest_cpuid_has_gbpages (struct kvm_vcpu * vcpu )
132- {
133- struct kvm_cpuid_entry2 * best ;
134-
135- best = kvm_find_cpuid_entry (vcpu , 0x80000001 , 0 );
136- return best && (best -> edx & bit (X86_FEATURE_GBPAGES ));
137- }
138-
139- static inline bool guest_cpuid_has_rtm (struct kvm_vcpu * vcpu )
140- {
141- struct kvm_cpuid_entry2 * best ;
142-
143- best = kvm_find_cpuid_entry (vcpu , 7 , 0 );
144- return best && (best -> ebx & bit (X86_FEATURE_RTM ));
145- }
146-
147- static inline bool guest_cpuid_has_mpx (struct kvm_vcpu * vcpu )
148- {
149- struct kvm_cpuid_entry2 * best ;
150-
151- best = kvm_find_cpuid_entry (vcpu , 7 , 0 );
152- return best && (best -> ebx & bit (X86_FEATURE_MPX ));
153- }
154-
155- static inline bool guest_cpuid_has_rdtscp (struct kvm_vcpu * vcpu )
156- {
157- struct kvm_cpuid_entry2 * best ;
158-
159- best = kvm_find_cpuid_entry (vcpu , 0x80000001 , 0 );
160- return best && (best -> edx & bit (X86_FEATURE_RDTSCP ));
161- }
162-
163- static inline bool guest_cpuid_has_nrips (struct kvm_vcpu * vcpu )
164- {
165- struct kvm_cpuid_entry2 * best ;
166-
167- best = kvm_find_cpuid_entry (vcpu , 0x8000000a , 0 );
168- return best && (best -> edx & bit (X86_FEATURE_NRIPS ));
169- }
170-
171115static inline int guest_cpuid_family (struct kvm_vcpu * vcpu )
172116{
173117 struct kvm_cpuid_entry2 * best ;
0 commit comments