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