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