]> git.ipfire.org Git - thirdparty/linux.git/blob - arch/x86/kvm/vmx/capabilities.h
KVM: VMX: Move capabilities structs and helpers to dedicated file
[thirdparty/linux.git] / arch / x86 / kvm / vmx / capabilities.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __KVM_X86_VMX_CAPS_H
3 #define __KVM_X86_VMX_CAPS_H
4
5 #include "lapic.h"
6
7 struct nested_vmx_msrs {
8 /*
9 * We only store the "true" versions of the VMX capability MSRs. We
10 * generate the "non-true" versions by setting the must-be-1 bits
11 * according to the SDM.
12 */
13 u32 procbased_ctls_low;
14 u32 procbased_ctls_high;
15 u32 secondary_ctls_low;
16 u32 secondary_ctls_high;
17 u32 pinbased_ctls_low;
18 u32 pinbased_ctls_high;
19 u32 exit_ctls_low;
20 u32 exit_ctls_high;
21 u32 entry_ctls_low;
22 u32 entry_ctls_high;
23 u32 misc_low;
24 u32 misc_high;
25 u32 ept_caps;
26 u32 vpid_caps;
27 u64 basic;
28 u64 cr0_fixed0;
29 u64 cr0_fixed1;
30 u64 cr4_fixed0;
31 u64 cr4_fixed1;
32 u64 vmcs_enum;
33 u64 vmfunc_controls;
34 };
35
36 struct vmcs_config {
37 int size;
38 int order;
39 u32 basic_cap;
40 u32 revision_id;
41 u32 pin_based_exec_ctrl;
42 u32 cpu_based_exec_ctrl;
43 u32 cpu_based_2nd_exec_ctrl;
44 u32 vmexit_ctrl;
45 u32 vmentry_ctrl;
46 struct nested_vmx_msrs nested;
47 };
48 extern struct vmcs_config vmcs_config;
49
50 struct vmx_capability {
51 u32 ept;
52 u32 vpid;
53 };
54 extern struct vmx_capability vmx_capability;
55
56 static inline bool cpu_has_vmx_basic_inout(void)
57 {
58 return (((u64)vmcs_config.basic_cap << 32) & VMX_BASIC_INOUT);
59 }
60
61 static inline bool cpu_has_virtual_nmis(void)
62 {
63 return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
64 }
65
66 static inline bool cpu_has_vmx_preemption_timer(void)
67 {
68 return vmcs_config.pin_based_exec_ctrl &
69 PIN_BASED_VMX_PREEMPTION_TIMER;
70 }
71
72 static inline bool cpu_has_vmx_posted_intr(void)
73 {
74 return IS_ENABLED(CONFIG_X86_LOCAL_APIC) &&
75 vmcs_config.pin_based_exec_ctrl & PIN_BASED_POSTED_INTR;
76 }
77
78 static inline bool cpu_has_load_ia32_efer(void)
79 {
80 return (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_EFER) &&
81 (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_EFER);
82 }
83
84 static inline bool cpu_has_load_perf_global_ctrl(void)
85 {
86 return (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) &&
87 (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL);
88 }
89
90 static inline bool vmx_mpx_supported(void)
91 {
92 return (vmcs_config.vmexit_ctrl & VM_EXIT_CLEAR_BNDCFGS) &&
93 (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_BNDCFGS);
94 }
95
96 static inline bool cpu_has_vmx_tpr_shadow(void)
97 {
98 return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW;
99 }
100
101 static inline bool cpu_need_tpr_shadow(struct kvm_vcpu *vcpu)
102 {
103 return cpu_has_vmx_tpr_shadow() && lapic_in_kernel(vcpu);
104 }
105
106 static inline bool cpu_has_vmx_msr_bitmap(void)
107 {
108 return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_USE_MSR_BITMAPS;
109 }
110
111 static inline bool cpu_has_secondary_exec_ctrls(void)
112 {
113 return vmcs_config.cpu_based_exec_ctrl &
114 CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
115 }
116
117 static inline bool cpu_has_vmx_virtualize_apic_accesses(void)
118 {
119 return vmcs_config.cpu_based_2nd_exec_ctrl &
120 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
121 }
122
123 static inline bool cpu_has_vmx_ept(void)
124 {
125 return vmcs_config.cpu_based_2nd_exec_ctrl &
126 SECONDARY_EXEC_ENABLE_EPT;
127 }
128
129 static inline bool vmx_umip_emulated(void)
130 {
131 return vmcs_config.cpu_based_2nd_exec_ctrl &
132 SECONDARY_EXEC_DESC;
133 }
134
135 static inline bool cpu_has_vmx_rdtscp(void)
136 {
137 return vmcs_config.cpu_based_2nd_exec_ctrl &
138 SECONDARY_EXEC_RDTSCP;
139 }
140
141 static inline bool cpu_has_vmx_virtualize_x2apic_mode(void)
142 {
143 return vmcs_config.cpu_based_2nd_exec_ctrl &
144 SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
145 }
146
147 static inline bool cpu_has_vmx_vpid(void)
148 {
149 return vmcs_config.cpu_based_2nd_exec_ctrl &
150 SECONDARY_EXEC_ENABLE_VPID;
151 }
152
153 static inline bool cpu_has_vmx_wbinvd_exit(void)
154 {
155 return vmcs_config.cpu_based_2nd_exec_ctrl &
156 SECONDARY_EXEC_WBINVD_EXITING;
157 }
158
159 static inline bool cpu_has_vmx_unrestricted_guest(void)
160 {
161 return vmcs_config.cpu_based_2nd_exec_ctrl &
162 SECONDARY_EXEC_UNRESTRICTED_GUEST;
163 }
164
165 static inline bool cpu_has_vmx_apic_register_virt(void)
166 {
167 return vmcs_config.cpu_based_2nd_exec_ctrl &
168 SECONDARY_EXEC_APIC_REGISTER_VIRT;
169 }
170
171 static inline bool cpu_has_vmx_virtual_intr_delivery(void)
172 {
173 return vmcs_config.cpu_based_2nd_exec_ctrl &
174 SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY;
175 }
176
177 static inline bool cpu_has_vmx_ple(void)
178 {
179 return vmcs_config.cpu_based_2nd_exec_ctrl &
180 SECONDARY_EXEC_PAUSE_LOOP_EXITING;
181 }
182
183 static inline bool vmx_rdrand_supported(void)
184 {
185 return vmcs_config.cpu_based_2nd_exec_ctrl &
186 SECONDARY_EXEC_RDRAND_EXITING;
187 }
188
189 static inline bool cpu_has_vmx_invpcid(void)
190 {
191 return vmcs_config.cpu_based_2nd_exec_ctrl &
192 SECONDARY_EXEC_ENABLE_INVPCID;
193 }
194
195 static inline bool cpu_has_vmx_vmfunc(void)
196 {
197 return vmcs_config.cpu_based_2nd_exec_ctrl &
198 SECONDARY_EXEC_ENABLE_VMFUNC;
199 }
200
201 static inline bool cpu_has_vmx_shadow_vmcs(void)
202 {
203 u64 vmx_msr;
204
205 /* check if the cpu supports writing r/o exit information fields */
206 rdmsrl(MSR_IA32_VMX_MISC, vmx_msr);
207 if (!(vmx_msr & MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS))
208 return false;
209
210 return vmcs_config.cpu_based_2nd_exec_ctrl &
211 SECONDARY_EXEC_SHADOW_VMCS;
212 }
213
214 static inline bool cpu_has_vmx_encls_vmexit(void)
215 {
216 return vmcs_config.cpu_based_2nd_exec_ctrl &
217 SECONDARY_EXEC_ENCLS_EXITING;
218 }
219
220 static inline bool vmx_rdseed_supported(void)
221 {
222 return vmcs_config.cpu_based_2nd_exec_ctrl &
223 SECONDARY_EXEC_RDSEED_EXITING;
224 }
225
226 static inline bool cpu_has_vmx_pml(void)
227 {
228 return vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_ENABLE_PML;
229 }
230
231 static inline bool vmx_xsaves_supported(void)
232 {
233 return vmcs_config.cpu_based_2nd_exec_ctrl &
234 SECONDARY_EXEC_XSAVES;
235 }
236
237 static inline bool cpu_has_vmx_tsc_scaling(void)
238 {
239 return vmcs_config.cpu_based_2nd_exec_ctrl &
240 SECONDARY_EXEC_TSC_SCALING;
241 }
242
243 static inline bool cpu_has_vmx_apicv(void)
244 {
245 return cpu_has_vmx_apic_register_virt() &&
246 cpu_has_vmx_virtual_intr_delivery() &&
247 cpu_has_vmx_posted_intr();
248 }
249
250 static inline bool cpu_has_vmx_flexpriority(void)
251 {
252 return cpu_has_vmx_tpr_shadow() &&
253 cpu_has_vmx_virtualize_apic_accesses();
254 }
255
256 static inline bool cpu_has_vmx_ept_execute_only(void)
257 {
258 return vmx_capability.ept & VMX_EPT_EXECUTE_ONLY_BIT;
259 }
260
261 static inline bool cpu_has_vmx_ept_4levels(void)
262 {
263 return vmx_capability.ept & VMX_EPT_PAGE_WALK_4_BIT;
264 }
265
266 static inline bool cpu_has_vmx_ept_5levels(void)
267 {
268 return vmx_capability.ept & VMX_EPT_PAGE_WALK_5_BIT;
269 }
270
271 static inline bool cpu_has_vmx_ept_mt_wb(void)
272 {
273 return vmx_capability.ept & VMX_EPTP_WB_BIT;
274 }
275
276 static inline bool cpu_has_vmx_ept_2m_page(void)
277 {
278 return vmx_capability.ept & VMX_EPT_2MB_PAGE_BIT;
279 }
280
281 static inline bool cpu_has_vmx_ept_1g_page(void)
282 {
283 return vmx_capability.ept & VMX_EPT_1GB_PAGE_BIT;
284 }
285
286 static inline bool cpu_has_vmx_ept_ad_bits(void)
287 {
288 return vmx_capability.ept & VMX_EPT_AD_BIT;
289 }
290
291 static inline bool cpu_has_vmx_invept_context(void)
292 {
293 return vmx_capability.ept & VMX_EPT_EXTENT_CONTEXT_BIT;
294 }
295
296 static inline bool cpu_has_vmx_invept_global(void)
297 {
298 return vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT;
299 }
300
301 static inline bool cpu_has_vmx_invvpid(void)
302 {
303 return vmx_capability.vpid & VMX_VPID_INVVPID_BIT;
304 }
305
306 static inline bool cpu_has_vmx_invvpid_individual_addr(void)
307 {
308 return vmx_capability.vpid & VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT;
309 }
310
311 static inline bool cpu_has_vmx_invvpid_single(void)
312 {
313 return vmx_capability.vpid & VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT;
314 }
315
316 static inline bool cpu_has_vmx_invvpid_global(void)
317 {
318 return vmx_capability.vpid & VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT;
319 }
320
321 #endif /* __KVM_X86_VMX_CAPS_H */