xref: /linux/arch/x86/kvm/vmx/capabilities.h (revision 9fb628b4cd3488a36e3fc9b22bb840048aa1a9d2)
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_cet;
18 extern bool __read_mostly enable_pml;
19 extern bool __read_mostly enable_mbec;
20 extern int __read_mostly pt_mode;
21 
22 #define PT_MODE_SYSTEM		0
23 #define PT_MODE_HOST_GUEST	1
24 
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 	u64 basic;
56 	u32 pin_based_exec_ctrl;
57 	u32 cpu_based_exec_ctrl;
58 	u32 cpu_based_2nd_exec_ctrl;
59 	u64 cpu_based_3rd_exec_ctrl;
60 	u32 vmexit_ctrl;
61 	u32 vmentry_ctrl;
62 	u64 misc;
63 	struct nested_vmx_msrs nested;
64 };
65 extern struct vmcs_config vmcs_config __ro_after_init;
66 
67 struct vmx_capability {
68 	u32 ept;
69 	u32 vpid;
70 };
71 extern struct vmx_capability vmx_capability __ro_after_init;
72 
73 static inline bool cpu_has_vmx_basic_inout(void)
74 {
75 	return	vmcs_config.basic & VMX_BASIC_INOUT;
76 }
77 
78 static inline bool cpu_has_vmx_basic_no_hw_errcode_cc(void)
79 {
80 	return	vmcs_config.basic & VMX_BASIC_NO_HW_ERROR_CODE_CC;
81 }
82 
83 static inline bool cpu_has_virtual_nmis(void)
84 {
85 	return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS &&
86 	       vmcs_config.cpu_based_exec_ctrl & CPU_BASED_NMI_WINDOW_EXITING;
87 }
88 
89 static inline bool cpu_has_vmx_preemption_timer(void)
90 {
91 	return vmcs_config.pin_based_exec_ctrl &
92 		PIN_BASED_VMX_PREEMPTION_TIMER;
93 }
94 
95 static inline bool cpu_has_vmx_posted_intr(void)
96 {
97 	return vmcs_config.pin_based_exec_ctrl & PIN_BASED_POSTED_INTR;
98 }
99 
100 static inline bool cpu_has_load_ia32_efer(void)
101 {
102 	return vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_EFER;
103 }
104 
105 static inline bool cpu_has_load_perf_global_ctrl(void)
106 {
107 	return vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
108 }
109 
110 static inline bool cpu_has_load_cet_ctrl(void)
111 {
112 	return vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_CET_STATE;
113 }
114 
115 static inline bool cpu_has_save_perf_global_ctrl(void)
116 {
117 	return vmcs_config.vmexit_ctrl & VM_EXIT_SAVE_IA32_PERF_GLOBAL_CTRL;
118 }
119 
120 static inline bool cpu_has_vmx_mpx(void)
121 {
122 	return vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_BNDCFGS;
123 }
124 
125 static inline bool cpu_has_vmx_tpr_shadow(void)
126 {
127 	return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW;
128 }
129 
130 static inline bool cpu_need_tpr_shadow(struct kvm_vcpu *vcpu)
131 {
132 	return cpu_has_vmx_tpr_shadow() && lapic_in_kernel(vcpu);
133 }
134 
135 static inline bool cpu_has_vmx_msr_bitmap(void)
136 {
137 	return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS;
138 }
139 
140 static inline bool cpu_has_secondary_exec_ctrls(void)
141 {
142 	return vmcs_config.cpu_based_exec_ctrl &
143 		CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
144 }
145 
146 static inline bool cpu_has_tertiary_exec_ctrls(void)
147 {
148 	return vmcs_config.cpu_based_exec_ctrl &
149 		CPU_BASED_ACTIVATE_TERTIARY_CONTROLS;
150 }
151 
152 static inline bool cpu_has_vmx_virtualize_apic_accesses(void)
153 {
154 	return vmcs_config.cpu_based_2nd_exec_ctrl &
155 		SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
156 }
157 
158 static inline bool cpu_has_vmx_ept(void)
159 {
160 	return vmcs_config.cpu_based_2nd_exec_ctrl &
161 		SECONDARY_EXEC_ENABLE_EPT;
162 }
163 
164 static inline bool vmx_umip_emulated(void)
165 {
166 	return !boot_cpu_has(X86_FEATURE_UMIP) &&
167 	       (vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_DESC);
168 }
169 
170 static inline bool cpu_has_vmx_rdtscp(void)
171 {
172 	return vmcs_config.cpu_based_2nd_exec_ctrl &
173 		SECONDARY_EXEC_ENABLE_RDTSCP;
174 }
175 
176 static inline bool cpu_has_vmx_virtualize_x2apic_mode(void)
177 {
178 	return vmcs_config.cpu_based_2nd_exec_ctrl &
179 		SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
180 }
181 
182 static inline bool cpu_has_vmx_vpid(void)
183 {
184 	return vmcs_config.cpu_based_2nd_exec_ctrl &
185 		SECONDARY_EXEC_ENABLE_VPID;
186 }
187 
188 static inline bool cpu_has_vmx_wbinvd_exit(void)
189 {
190 	return vmcs_config.cpu_based_2nd_exec_ctrl &
191 		SECONDARY_EXEC_WBINVD_EXITING;
192 }
193 
194 static inline bool cpu_has_vmx_unrestricted_guest(void)
195 {
196 	return vmcs_config.cpu_based_2nd_exec_ctrl &
197 		SECONDARY_EXEC_UNRESTRICTED_GUEST;
198 }
199 
200 static inline bool cpu_has_vmx_apic_register_virt(void)
201 {
202 	return vmcs_config.cpu_based_2nd_exec_ctrl &
203 		SECONDARY_EXEC_APIC_REGISTER_VIRT;
204 }
205 
206 static inline bool cpu_has_vmx_virtual_intr_delivery(void)
207 {
208 	return vmcs_config.cpu_based_2nd_exec_ctrl &
209 		SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY;
210 }
211 
212 static inline bool cpu_has_vmx_ple(void)
213 {
214 	return vmcs_config.cpu_based_2nd_exec_ctrl &
215 		SECONDARY_EXEC_PAUSE_LOOP_EXITING;
216 }
217 
218 static inline bool cpu_has_vmx_rdrand(void)
219 {
220 	return vmcs_config.cpu_based_2nd_exec_ctrl &
221 		SECONDARY_EXEC_RDRAND_EXITING;
222 }
223 
224 static inline bool cpu_has_vmx_invpcid(void)
225 {
226 	return vmcs_config.cpu_based_2nd_exec_ctrl &
227 		SECONDARY_EXEC_ENABLE_INVPCID;
228 }
229 
230 static inline bool cpu_has_vmx_vmfunc(void)
231 {
232 	return vmcs_config.cpu_based_2nd_exec_ctrl &
233 		SECONDARY_EXEC_ENABLE_VMFUNC;
234 }
235 
236 static inline bool cpu_has_vmx_shadow_vmcs(void)
237 {
238 	/* check if the cpu supports writing r/o exit information fields */
239 	if (!(vmcs_config.misc & VMX_MISC_VMWRITE_SHADOW_RO_FIELDS))
240 		return false;
241 
242 	return vmcs_config.cpu_based_2nd_exec_ctrl &
243 		SECONDARY_EXEC_SHADOW_VMCS;
244 }
245 
246 static inline bool cpu_has_vmx_encls_vmexit(void)
247 {
248 	return vmcs_config.cpu_based_2nd_exec_ctrl &
249 		SECONDARY_EXEC_ENCLS_EXITING;
250 }
251 
252 static inline bool cpu_has_vmx_rdseed(void)
253 {
254 	return vmcs_config.cpu_based_2nd_exec_ctrl &
255 		SECONDARY_EXEC_RDSEED_EXITING;
256 }
257 
258 static inline bool cpu_has_vmx_pml(void)
259 {
260 	return vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_ENABLE_PML;
261 }
262 
263 static inline bool cpu_has_vmx_xsaves(void)
264 {
265 	return vmcs_config.cpu_based_2nd_exec_ctrl &
266 		SECONDARY_EXEC_ENABLE_XSAVES;
267 }
268 
269 static inline bool cpu_has_vmx_waitpkg(void)
270 {
271 	return vmcs_config.cpu_based_2nd_exec_ctrl &
272 		SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE;
273 }
274 
275 static inline bool cpu_has_vmx_tsc_scaling(void)
276 {
277 	return vmcs_config.cpu_based_2nd_exec_ctrl &
278 		SECONDARY_EXEC_TSC_SCALING;
279 }
280 
281 static inline bool cpu_has_vmx_bus_lock_detection(void)
282 {
283 	return vmcs_config.cpu_based_2nd_exec_ctrl &
284 	    SECONDARY_EXEC_BUS_LOCK_DETECTION;
285 }
286 
287 static inline bool cpu_has_vmx_apicv(void)
288 {
289 	return cpu_has_vmx_apic_register_virt() &&
290 		cpu_has_vmx_virtual_intr_delivery() &&
291 		cpu_has_vmx_posted_intr();
292 }
293 
294 static inline bool cpu_has_vmx_ipiv(void)
295 {
296 	return vmcs_config.cpu_based_3rd_exec_ctrl & TERTIARY_EXEC_IPI_VIRT;
297 }
298 
299 static inline bool cpu_has_vmx_flexpriority(void)
300 {
301 	return cpu_has_vmx_tpr_shadow() &&
302 		cpu_has_vmx_virtualize_apic_accesses();
303 }
304 
305 static inline bool cpu_has_vmx_ept_4levels(void)
306 {
307 	return vmx_capability.ept & VMX_EPT_PAGE_WALK_4_BIT;
308 }
309 
310 static inline bool cpu_has_vmx_ept_5levels(void)
311 {
312 	return vmx_capability.ept & VMX_EPT_PAGE_WALK_5_BIT;
313 }
314 
315 static inline bool cpu_has_vmx_ept_mt_wb(void)
316 {
317 	return vmx_capability.ept & VMX_EPTP_WB_BIT;
318 }
319 
320 static inline bool cpu_has_vmx_ept_2m_page(void)
321 {
322 	return vmx_capability.ept & VMX_EPT_2MB_PAGE_BIT;
323 }
324 
325 static inline bool cpu_has_vmx_ept_1g_page(void)
326 {
327 	return vmx_capability.ept & VMX_EPT_1GB_PAGE_BIT;
328 }
329 
330 static inline int ept_caps_to_lpage_level(u32 ept_caps)
331 {
332 	if (ept_caps & VMX_EPT_1GB_PAGE_BIT)
333 		return PG_LEVEL_1G;
334 	if (ept_caps & VMX_EPT_2MB_PAGE_BIT)
335 		return PG_LEVEL_2M;
336 	return PG_LEVEL_4K;
337 }
338 
339 static inline bool cpu_has_vmx_ept_ad_bits(void)
340 {
341 	return vmx_capability.ept & VMX_EPT_AD_BIT;
342 }
343 
344 static inline bool cpu_has_vmx_invept_context(void)
345 {
346 	return vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT;
347 }
348 
349 static inline bool cpu_has_vmx_invept_global(void)
350 {
351 	return vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT;
352 }
353 
354 static inline bool cpu_has_vmx_invvpid(void)
355 {
356 	return vmx_capability.vpid & VMX_VPID_INVVPID_BIT;
357 }
358 
359 static inline bool cpu_has_vmx_invvpid_individual_addr(void)
360 {
361 	return vmx_capability.vpid & VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT;
362 }
363 
364 static inline bool cpu_has_vmx_invvpid_single(void)
365 {
366 	return vmx_capability.vpid & VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT;
367 }
368 
369 static inline bool cpu_has_vmx_invvpid_global(void)
370 {
371 	return vmx_capability.vpid & VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT;
372 }
373 
374 static inline bool cpu_has_vmx_intel_pt(void)
375 {
376 	return (vmcs_config.misc & VMX_MISC_INTEL_PT) &&
377 		(vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_PT_USE_GPA) &&
378 		(vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_RTIT_CTL);
379 }
380 
381 /*
382  * Processor Trace can operate in one of three modes:
383  *  a. system-wide: trace both host/guest and output to host buffer
384  *  b. host-only:   only trace host and output to host buffer
385  *  c. host-guest:  trace host and guest simultaneously and output to their
386  *                  respective buffer
387  *
388  * KVM currently only supports (a) and (c).
389  */
390 static inline bool vmx_pt_mode_is_system(void)
391 {
392 	return pt_mode == PT_MODE_SYSTEM;
393 }
394 static inline bool vmx_pt_mode_is_host_guest(void)
395 {
396 	return pt_mode == PT_MODE_HOST_GUEST;
397 }
398 
399 static inline bool vmx_pebs_supported(void)
400 {
401 	return boot_cpu_has(X86_FEATURE_PEBS) && kvm_pmu_cap.pebs_ept &&
402 	       !enable_mediated_pmu;
403 }
404 
405 static inline bool cpu_has_notify_vmexit(void)
406 {
407 	return vmcs_config.cpu_based_2nd_exec_ctrl &
408 		SECONDARY_EXEC_NOTIFY_VM_EXITING;
409 }
410 
411 static inline bool cpu_has_ept_mbec(void)
412 {
413 	return vmcs_config.cpu_based_2nd_exec_ctrl &
414 		SECONDARY_EXEC_MODE_BASED_EPT_EXEC;
415 }
416 
417 #endif /* __KVM_X86_VMX_CAPS_H */
418