]>
Commit | Line | Data |
---|---|---|
3077c191 SC |
1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef __KVM_X86_VMX_CAPS_H | |
3 | #define __KVM_X86_VMX_CAPS_H | |
4 | ||
19e38336 SC |
5 | #include <asm/vmx.h> |
6 | ||
3077c191 SC |
7 | #include "lapic.h" |
8 | ||
2c4fd91d SC |
9 | extern bool __read_mostly enable_vpid; |
10 | extern bool __read_mostly flexpriority_enabled; | |
11 | extern bool __read_mostly enable_ept; | |
12 | extern bool __read_mostly enable_unrestricted_guest; | |
13 | extern bool __read_mostly enable_ept_ad_bits; | |
14 | extern bool __read_mostly enable_pml; | |
f99e3daf CP |
15 | extern int __read_mostly pt_mode; |
16 | ||
17 | #define PT_MODE_SYSTEM 0 | |
18 | #define PT_MODE_HOST_GUEST 1 | |
2c4fd91d | 19 | |
27461da3 | 20 | #define PMU_CAP_FW_WRITES (1ULL << 13) |
9c9520ce | 21 | #define PMU_CAP_LBR_FMT 0x3f |
27461da3 | 22 | |
e6209a3b LX |
23 | #define DEBUGCTLMSR_LBR_MASK (DEBUGCTLMSR_LBR | DEBUGCTLMSR_FREEZE_LBRS_ON_PMI) |
24 | ||
3077c191 SC |
25 | struct nested_vmx_msrs { |
26 | /* | |
27 | * We only store the "true" versions of the VMX capability MSRs. We | |
28 | * generate the "non-true" versions by setting the must-be-1 bits | |
29 | * according to the SDM. | |
30 | */ | |
31 | u32 procbased_ctls_low; | |
32 | u32 procbased_ctls_high; | |
33 | u32 secondary_ctls_low; | |
34 | u32 secondary_ctls_high; | |
35 | u32 pinbased_ctls_low; | |
36 | u32 pinbased_ctls_high; | |
37 | u32 exit_ctls_low; | |
38 | u32 exit_ctls_high; | |
39 | u32 entry_ctls_low; | |
40 | u32 entry_ctls_high; | |
41 | u32 misc_low; | |
42 | u32 misc_high; | |
43 | u32 ept_caps; | |
44 | u32 vpid_caps; | |
45 | u64 basic; | |
46 | u64 cr0_fixed0; | |
47 | u64 cr0_fixed1; | |
48 | u64 cr4_fixed0; | |
49 | u64 cr4_fixed1; | |
50 | u64 vmcs_enum; | |
51 | u64 vmfunc_controls; | |
52 | }; | |
53 | ||
54 | struct vmcs_config { | |
55 | int size; | |
56 | int order; | |
57 | u32 basic_cap; | |
58 | u32 revision_id; | |
59 | u32 pin_based_exec_ctrl; | |
60 | u32 cpu_based_exec_ctrl; | |
61 | u32 cpu_based_2nd_exec_ctrl; | |
62 | u32 vmexit_ctrl; | |
63 | u32 vmentry_ctrl; | |
64 | struct nested_vmx_msrs nested; | |
65 | }; | |
66 | extern struct vmcs_config vmcs_config; | |
67 | ||
68 | struct vmx_capability { | |
69 | u32 ept; | |
70 | u32 vpid; | |
71 | }; | |
72 | extern struct vmx_capability vmx_capability; | |
73 | ||
74 | static inline bool cpu_has_vmx_basic_inout(void) | |
75 | { | |
76 | return (((u64)vmcs_config.basic_cap << 32) & VMX_BASIC_INOUT); | |
77 | } | |
78 | ||
79 | static inline bool cpu_has_virtual_nmis(void) | |
80 | { | |
81 | return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS; | |
82 | } | |
83 | ||
84 | static inline bool cpu_has_vmx_preemption_timer(void) | |
85 | { | |
86 | return vmcs_config.pin_based_exec_ctrl & | |
87 | PIN_BASED_VMX_PREEMPTION_TIMER; | |
88 | } | |
89 | ||
90 | static inline bool cpu_has_vmx_posted_intr(void) | |
91 | { | |
377872b3 | 92 | return vmcs_config.pin_based_exec_ctrl & PIN_BASED_POSTED_INTR; |
3077c191 SC |
93 | } |
94 | ||
95 | static inline bool cpu_has_load_ia32_efer(void) | |
96 | { | |
97 | return (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_EFER) && | |
98 | (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_EFER); | |
99 | } | |
100 | ||
101 | static inline bool cpu_has_load_perf_global_ctrl(void) | |
102 | { | |
103 | return (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) && | |
104 | (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL); | |
105 | } | |
106 | ||
7f5581f5 | 107 | static inline bool cpu_has_vmx_mpx(void) |
3077c191 SC |
108 | { |
109 | return (vmcs_config.vmexit_ctrl & VM_EXIT_CLEAR_BNDCFGS) && | |
110 | (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_BNDCFGS); | |
111 | } | |
112 | ||
113 | static inline bool cpu_has_vmx_tpr_shadow(void) | |
114 | { | |
115 | return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW; | |
116 | } | |
117 | ||
118 | static inline bool cpu_need_tpr_shadow(struct kvm_vcpu *vcpu) | |
119 | { | |
120 | return cpu_has_vmx_tpr_shadow() && lapic_in_kernel(vcpu); | |
121 | } | |
122 | ||
123 | static inline bool cpu_has_vmx_msr_bitmap(void) | |
124 | { | |
125 | return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS; | |
126 | } | |
127 | ||
128 | static inline bool cpu_has_secondary_exec_ctrls(void) | |
129 | { | |
130 | return vmcs_config.cpu_based_exec_ctrl & | |
131 | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS; | |
132 | } | |
133 | ||
134 | static inline bool cpu_has_vmx_virtualize_apic_accesses(void) | |
135 | { | |
136 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
137 | SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; | |
138 | } | |
139 | ||
140 | static inline bool cpu_has_vmx_ept(void) | |
141 | { | |
142 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
143 | SECONDARY_EXEC_ENABLE_EPT; | |
144 | } | |
145 | ||
146 | static inline bool vmx_umip_emulated(void) | |
147 | { | |
148 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
149 | SECONDARY_EXEC_DESC; | |
150 | } | |
151 | ||
152 | static inline bool cpu_has_vmx_rdtscp(void) | |
153 | { | |
154 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
7f3603b6 | 155 | SECONDARY_EXEC_ENABLE_RDTSCP; |
3077c191 SC |
156 | } |
157 | ||
158 | static inline bool cpu_has_vmx_virtualize_x2apic_mode(void) | |
159 | { | |
160 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
161 | SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE; | |
162 | } | |
163 | ||
164 | static inline bool cpu_has_vmx_vpid(void) | |
165 | { | |
166 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
167 | SECONDARY_EXEC_ENABLE_VPID; | |
168 | } | |
169 | ||
170 | static inline bool cpu_has_vmx_wbinvd_exit(void) | |
171 | { | |
172 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
173 | SECONDARY_EXEC_WBINVD_EXITING; | |
174 | } | |
175 | ||
176 | static inline bool cpu_has_vmx_unrestricted_guest(void) | |
177 | { | |
178 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
179 | SECONDARY_EXEC_UNRESTRICTED_GUEST; | |
180 | } | |
181 | ||
182 | static inline bool cpu_has_vmx_apic_register_virt(void) | |
183 | { | |
184 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
185 | SECONDARY_EXEC_APIC_REGISTER_VIRT; | |
186 | } | |
187 | ||
188 | static inline bool cpu_has_vmx_virtual_intr_delivery(void) | |
189 | { | |
190 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
191 | SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY; | |
192 | } | |
193 | ||
194 | static inline bool cpu_has_vmx_ple(void) | |
195 | { | |
196 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
197 | SECONDARY_EXEC_PAUSE_LOOP_EXITING; | |
198 | } | |
199 | ||
becdad85 | 200 | static inline bool cpu_has_vmx_rdrand(void) |
3077c191 SC |
201 | { |
202 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
203 | SECONDARY_EXEC_RDRAND_EXITING; | |
204 | } | |
205 | ||
206 | static inline bool cpu_has_vmx_invpcid(void) | |
207 | { | |
208 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
209 | SECONDARY_EXEC_ENABLE_INVPCID; | |
210 | } | |
211 | ||
212 | static inline bool cpu_has_vmx_vmfunc(void) | |
213 | { | |
214 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
215 | SECONDARY_EXEC_ENABLE_VMFUNC; | |
216 | } | |
217 | ||
218 | static inline bool cpu_has_vmx_shadow_vmcs(void) | |
219 | { | |
220 | u64 vmx_msr; | |
221 | ||
222 | /* check if the cpu supports writing r/o exit information fields */ | |
223 | rdmsrl(MSR_IA32_VMX_MISC, vmx_msr); | |
224 | if (!(vmx_msr & MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS)) | |
225 | return false; | |
226 | ||
227 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
228 | SECONDARY_EXEC_SHADOW_VMCS; | |
229 | } | |
230 | ||
231 | static inline bool cpu_has_vmx_encls_vmexit(void) | |
232 | { | |
233 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
234 | SECONDARY_EXEC_ENCLS_EXITING; | |
235 | } | |
236 | ||
becdad85 | 237 | static inline bool cpu_has_vmx_rdseed(void) |
3077c191 SC |
238 | { |
239 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
240 | SECONDARY_EXEC_RDSEED_EXITING; | |
241 | } | |
242 | ||
243 | static inline bool cpu_has_vmx_pml(void) | |
244 | { | |
245 | return vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_ENABLE_PML; | |
246 | } | |
247 | ||
becdad85 | 248 | static inline bool cpu_has_vmx_xsaves(void) |
3077c191 SC |
249 | { |
250 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
251 | SECONDARY_EXEC_XSAVES; | |
252 | } | |
253 | ||
becdad85 | 254 | static inline bool cpu_has_vmx_waitpkg(void) |
e69e72fa TX |
255 | { |
256 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
257 | SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE; | |
258 | } | |
259 | ||
3077c191 SC |
260 | static inline bool cpu_has_vmx_tsc_scaling(void) |
261 | { | |
262 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
263 | SECONDARY_EXEC_TSC_SCALING; | |
264 | } | |
265 | ||
fe6b6bc8 CQ |
266 | static inline bool cpu_has_vmx_bus_lock_detection(void) |
267 | { | |
268 | return vmcs_config.cpu_based_2nd_exec_ctrl & | |
269 | SECONDARY_EXEC_BUS_LOCK_DETECTION; | |
270 | } | |
271 | ||
3077c191 SC |
272 | static inline bool cpu_has_vmx_apicv(void) |
273 | { | |
274 | return cpu_has_vmx_apic_register_virt() && | |
275 | cpu_has_vmx_virtual_intr_delivery() && | |
276 | cpu_has_vmx_posted_intr(); | |
277 | } | |
278 | ||
279 | static inline bool cpu_has_vmx_flexpriority(void) | |
280 | { | |
281 | return cpu_has_vmx_tpr_shadow() && | |
282 | cpu_has_vmx_virtualize_apic_accesses(); | |
283 | } | |
284 | ||
285 | static inline bool cpu_has_vmx_ept_execute_only(void) | |
286 | { | |
287 | return vmx_capability.ept & VMX_EPT_EXECUTE_ONLY_BIT; | |
288 | } | |
289 | ||
290 | static inline bool cpu_has_vmx_ept_4levels(void) | |
291 | { | |
292 | return vmx_capability.ept & VMX_EPT_PAGE_WALK_4_BIT; | |
293 | } | |
294 | ||
295 | static inline bool cpu_has_vmx_ept_5levels(void) | |
296 | { | |
297 | return vmx_capability.ept & VMX_EPT_PAGE_WALK_5_BIT; | |
298 | } | |
299 | ||
300 | static inline bool cpu_has_vmx_ept_mt_wb(void) | |
301 | { | |
302 | return vmx_capability.ept & VMX_EPTP_WB_BIT; | |
303 | } | |
304 | ||
305 | static inline bool cpu_has_vmx_ept_2m_page(void) | |
306 | { | |
307 | return vmx_capability.ept & VMX_EPT_2MB_PAGE_BIT; | |
308 | } | |
309 | ||
310 | static inline bool cpu_has_vmx_ept_1g_page(void) | |
311 | { | |
312 | return vmx_capability.ept & VMX_EPT_1GB_PAGE_BIT; | |
313 | } | |
314 | ||
315 | static inline bool cpu_has_vmx_ept_ad_bits(void) | |
316 | { | |
317 | return vmx_capability.ept & VMX_EPT_AD_BIT; | |
318 | } | |
319 | ||
320 | static inline bool cpu_has_vmx_invept_context(void) | |
321 | { | |
322 | return vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT; | |
323 | } | |
324 | ||
325 | static inline bool cpu_has_vmx_invept_global(void) | |
326 | { | |
327 | return vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT; | |
328 | } | |
329 | ||
330 | static inline bool cpu_has_vmx_invvpid(void) | |
331 | { | |
332 | return vmx_capability.vpid & VMX_VPID_INVVPID_BIT; | |
333 | } | |
334 | ||
335 | static inline bool cpu_has_vmx_invvpid_individual_addr(void) | |
336 | { | |
337 | return vmx_capability.vpid & VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT; | |
338 | } | |
339 | ||
340 | static inline bool cpu_has_vmx_invvpid_single(void) | |
341 | { | |
342 | return vmx_capability.vpid & VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT; | |
343 | } | |
344 | ||
345 | static inline bool cpu_has_vmx_invvpid_global(void) | |
346 | { | |
347 | return vmx_capability.vpid & VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT; | |
348 | } | |
349 | ||
f99e3daf CP |
350 | static inline bool cpu_has_vmx_intel_pt(void) |
351 | { | |
352 | u64 vmx_msr; | |
353 | ||
354 | rdmsrl(MSR_IA32_VMX_MISC, vmx_msr); | |
355 | return (vmx_msr & MSR_IA32_VMX_MISC_INTEL_PT) && | |
356 | (vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_PT_USE_GPA) && | |
357 | (vmcs_config.vmexit_ctrl & VM_EXIT_CLEAR_IA32_RTIT_CTL) && | |
358 | (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_RTIT_CTL); | |
359 | } | |
360 | ||
2ef7619d SC |
361 | /* |
362 | * Processor Trace can operate in one of three modes: | |
363 | * a. system-wide: trace both host/guest and output to host buffer | |
364 | * b. host-only: only trace host and output to host buffer | |
365 | * c. host-guest: trace host and guest simultaneously and output to their | |
366 | * respective buffer | |
367 | * | |
368 | * KVM currently only supports (a) and (c). | |
369 | */ | |
370 | static inline bool vmx_pt_mode_is_system(void) | |
371 | { | |
372 | return pt_mode == PT_MODE_SYSTEM; | |
373 | } | |
374 | static inline bool vmx_pt_mode_is_host_guest(void) | |
375 | { | |
376 | return pt_mode == PT_MODE_HOST_GUEST; | |
377 | } | |
378 | ||
27461da3 LX |
379 | static inline u64 vmx_get_perf_capabilities(void) |
380 | { | |
be635e34 LX |
381 | u64 perf_cap = 0; |
382 | ||
383 | if (boot_cpu_has(X86_FEATURE_PDCM)) | |
384 | rdmsrl(MSR_IA32_PERF_CAPABILITIES, perf_cap); | |
385 | ||
386 | perf_cap &= PMU_CAP_LBR_FMT; | |
387 | ||
27461da3 LX |
388 | /* |
389 | * Since counters are virtualized, KVM would support full | |
390 | * width counting unconditionally, even if the host lacks it. | |
391 | */ | |
be635e34 | 392 | return PMU_CAP_FW_WRITES | perf_cap; |
27461da3 LX |
393 | } |
394 | ||
d855066f LX |
395 | static inline u64 vmx_supported_debugctl(void) |
396 | { | |
c6462363 LX |
397 | u64 debugctl = 0; |
398 | ||
76ea438b PB |
399 | if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT)) |
400 | debugctl |= DEBUGCTLMSR_BUS_LOCK_DETECT; | |
401 | ||
c6462363 | 402 | if (vmx_get_perf_capabilities() & PMU_CAP_LBR_FMT) |
e6209a3b | 403 | debugctl |= DEBUGCTLMSR_LBR_MASK; |
c6462363 LX |
404 | |
405 | return debugctl; | |
d855066f LX |
406 | } |
407 | ||
3077c191 | 408 | #endif /* __KVM_X86_VMX_CAPS_H */ |