1 /*
2 * Copyright (c) 2018-2021 Maxime Villard, m00nbsd.net
3 * All rights reserved.
4 *
5 * This code is part of the NVMM hypervisor.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include "../nvmm.h"
30 #include "../nvmm_internal.h"
31 #include "nvmm_x86.h"
32
33 /*
34 * Code shared between x86-SVM and x86-VMX.
35 */
36
37 const struct nvmm_x64_state nvmm_x86_reset_state = {
38 .segs = {
39 [NVMM_X64_SEG_ES] = {
40 .selector = 0x0000,
41 .base = 0x00000000,
42 .limit = 0xFFFF,
43 .attrib = {
44 .type = 3,
45 .s = 1,
46 .p = 1,
47 }
48 },
49 [NVMM_X64_SEG_CS] = {
50 .selector = 0xF000,
51 .base = 0xFFFF0000,
52 .limit = 0xFFFF,
53 .attrib = {
54 .type = 3,
55 .s = 1,
56 .p = 1,
57 }
58 },
59 [NVMM_X64_SEG_SS] = {
60 .selector = 0x0000,
61 .base = 0x00000000,
62 .limit = 0xFFFF,
63 .attrib = {
64 .type = 3,
65 .s = 1,
66 .p = 1,
67 }
68 },
69 [NVMM_X64_SEG_DS] = {
70 .selector = 0x0000,
71 .base = 0x00000000,
72 .limit = 0xFFFF,
73 .attrib = {
74 .type = 3,
75 .s = 1,
76 .p = 1,
77 }
78 },
79 [NVMM_X64_SEG_FS] = {
80 .selector = 0x0000,
81 .base = 0x00000000,
82 .limit = 0xFFFF,
83 .attrib = {
84 .type = 3,
85 .s = 1,
86 .p = 1,
87 }
88 },
89 [NVMM_X64_SEG_GS] = {
90 .selector = 0x0000,
91 .base = 0x00000000,
92 .limit = 0xFFFF,
93 .attrib = {
94 .type = 3,
95 .s = 1,
96 .p = 1,
97 }
98 },
99 [NVMM_X64_SEG_GDT] = {
100 .selector = 0x0000,
101 .base = 0x00000000,
102 .limit = 0xFFFF,
103 .attrib = {
104 .type = 2,
105 .s = 1,
106 .p = 1,
107 }
108 },
109 [NVMM_X64_SEG_IDT] = {
110 .selector = 0x0000,
111 .base = 0x00000000,
112 .limit = 0xFFFF,
113 .attrib = {
114 .type = 2,
115 .s = 1,
116 .p = 1,
117 }
118 },
119 [NVMM_X64_SEG_LDT] = {
120 .selector = 0x0000,
121 .base = 0x00000000,
122 .limit = 0xFFFF,
123 .attrib = {
124 .type = 2,
125 .s = 0,
126 .p = 1,
127 }
128 },
129 [NVMM_X64_SEG_TR] = {
130 .selector = 0x0000,
131 .base = 0x00000000,
132 .limit = 0xFFFF,
133 .attrib = {
134 .type = 3,
135 .s = 0,
136 .p = 1,
137 }
138 },
139 },
140
141 .gprs = {
142 [NVMM_X64_GPR_RAX] = 0x00000000,
143 [NVMM_X64_GPR_RCX] = 0x00000000,
144 [NVMM_X64_GPR_RDX] = 0x00000600,
145 [NVMM_X64_GPR_RBX] = 0x00000000,
146 [NVMM_X64_GPR_RSP] = 0x00000000,
147 [NVMM_X64_GPR_RBP] = 0x00000000,
148 [NVMM_X64_GPR_RSI] = 0x00000000,
149 [NVMM_X64_GPR_RDI] = 0x00000000,
150 [NVMM_X64_GPR_R8] = 0x00000000,
151 [NVMM_X64_GPR_R9] = 0x00000000,
152 [NVMM_X64_GPR_R10] = 0x00000000,
153 [NVMM_X64_GPR_R11] = 0x00000000,
154 [NVMM_X64_GPR_R12] = 0x00000000,
155 [NVMM_X64_GPR_R13] = 0x00000000,
156 [NVMM_X64_GPR_R14] = 0x00000000,
157 [NVMM_X64_GPR_R15] = 0x00000000,
158 [NVMM_X64_GPR_RIP] = 0x0000FFF0,
159 [NVMM_X64_GPR_RFLAGS] = 0x00000002,
160 },
161
162 .crs = {
163 [NVMM_X64_CR_CR0] = 0x60000010,
164 [NVMM_X64_CR_CR2] = 0x00000000,
165 [NVMM_X64_CR_CR3] = 0x00000000,
166 [NVMM_X64_CR_CR4] = 0x00000000,
167 [NVMM_X64_CR_CR8] = 0x00000000,
168 [NVMM_X64_CR_XCR0] = 0x00000001,
169 },
170
171 .drs = {
172 [NVMM_X64_DR_DR0] = 0x00000000,
173 [NVMM_X64_DR_DR1] = 0x00000000,
174 [NVMM_X64_DR_DR2] = 0x00000000,
175 [NVMM_X64_DR_DR3] = 0x00000000,
176 [NVMM_X64_DR_DR6] = 0xFFFF0FF0,
177 [NVMM_X64_DR_DR7] = 0x00000400,
178 },
179
180 .msrs = {
181 [NVMM_X64_MSR_EFER] = 0x00000000,
182 [NVMM_X64_MSR_STAR] = 0x00000000,
183 [NVMM_X64_MSR_LSTAR] = 0x00000000,
184 [NVMM_X64_MSR_CSTAR] = 0x00000000,
185 [NVMM_X64_MSR_SFMASK] = 0x00000000,
186 [NVMM_X64_MSR_KERNELGSBASE] = 0x00000000,
187 [NVMM_X64_MSR_SYSENTER_CS] = 0x00000000,
188 [NVMM_X64_MSR_SYSENTER_ESP] = 0x00000000,
189 [NVMM_X64_MSR_SYSENTER_EIP] = 0x00000000,
190 [NVMM_X64_MSR_PAT] = 0x0007040600070406,
191 [NVMM_X64_MSR_TSC] = 0,
192 },
193
194 .intr = {
195 .int_shadow = 0,
196 .int_window_exiting = 0,
197 .nmi_window_exiting = 0,
198 .evt_pending = 0,
199 },
200
201 .fpu = {
202 .fx_cw = 0x0040,
203 .fx_sw = 0x0000,
204 .fx_tw = 0x55,
205 .fx_zero = 0x55,
206 .fx_mxcsr = 0x1F80,
207 }
208 };
209
210 const struct nvmm_x86_cpuid_mask nvmm_cpuid_00000001 = {
211 .eax = ~0,
212 .ebx = ~0,
213 .ecx =
214 CPUID_0_01_ECX_SSE3 |
215 CPUID_0_01_ECX_PCLMULQDQ |
216 /* CPUID_0_01_ECX_DTES64 excluded */
217 /* CPUID_0_01_ECX_MONITOR excluded */
218 /* CPUID_0_01_ECX_DS_CPL excluded */
219 /* CPUID_0_01_ECX_VMX excluded */
220 /* CPUID_0_01_ECX_SMX excluded */
221 /* CPUID_0_01_ECX_EIST excluded */
222 /* CPUID_0_01_ECX_TM2 excluded */
223 CPUID_0_01_ECX_SSSE3 |
224 /* CPUID_0_01_ECX_CNXTID excluded */
225 /* CPUID_0_01_ECX_SDBG excluded */
226 CPUID_0_01_ECX_FMA |
227 CPUID_0_01_ECX_CX16 |
228 /* CPUID_0_01_ECX_XTPR excluded */
229 /* CPUID_0_01_ECX_PDCM excluded */
230 /* CPUID_0_01_ECX_PCID excluded, but re-included in VMX */
231 /* CPUID_0_01_ECX_DCA excluded */
232 CPUID_0_01_ECX_SSE41 |
233 CPUID_0_01_ECX_SSE42 |
234 /* CPUID_0_01_ECX_X2APIC excluded */
235 CPUID_0_01_ECX_MOVBE |
236 CPUID_0_01_ECX_POPCNT |
237 /* CPUID_0_01_ECX_TSC_DEADLINE excluded */
238 CPUID_0_01_ECX_AESNI |
239 CPUID_0_01_ECX_XSAVE |
240 CPUID_0_01_ECX_OSXSAVE |
241 /* CPUID_0_01_ECX_AVX excluded */
242 CPUID_0_01_ECX_F16C |
243 CPUID_0_01_ECX_RDRAND,
244 /* CPUID_0_01_ECX_RAZ excluded */
245 .edx =
246 CPUID_0_01_EDX_FPU |
247 CPUID_0_01_EDX_VME |
248 CPUID_0_01_EDX_DE |
249 CPUID_0_01_EDX_PSE |
250 CPUID_0_01_EDX_TSC |
251 CPUID_0_01_EDX_MSR |
252 CPUID_0_01_EDX_PAE |
253 /* CPUID_0_01_EDX_MCE excluded */
254 CPUID_0_01_EDX_CX8 |
255 CPUID_0_01_EDX_APIC |
256 CPUID_0_01_EDX_SEP |
257 /* CPUID_0_01_EDX_MTRR excluded */
258 CPUID_0_01_EDX_PGE |
259 /* CPUID_0_01_EDX_MCA excluded */
260 CPUID_0_01_EDX_CMOV |
261 CPUID_0_01_EDX_PAT |
262 CPUID_0_01_EDX_PSE36 |
263 /* CPUID_0_01_EDX_PSN excluded */
264 CPUID_0_01_EDX_CLFSH |
265 /* CPUID_0_01_EDX_DS excluded */
266 /* CPUID_0_01_EDX_ACPI excluded */
267 CPUID_0_01_EDX_MMX |
268 CPUID_0_01_EDX_FXSR |
269 CPUID_0_01_EDX_SSE |
270 CPUID_0_01_EDX_SSE2 |
271 CPUID_0_01_EDX_SS |
272 CPUID_0_01_EDX_HTT |
273 /* CPUID_0_01_EDX_TM excluded */
274 CPUID_0_01_EDX_PBE
275 };
276
277 const struct nvmm_x86_cpuid_mask nvmm_cpuid_00000007 = {
278 .eax = ~0,
279 .ebx =
280 CPUID_0_07_EBX_FSGSBASE |
281 /* CPUID_0_07_EBX_TSC_ADJUST excluded */
282 /* CPUID_0_07_EBX_SGX excluded */
283 CPUID_0_07_EBX_BMI1 |
284 /* CPUID_0_07_EBX_HLE excluded */
285 /* CPUID_0_07_EBX_AVX2 excluded */
286 CPUID_0_07_EBX_FDPEXONLY |
287 CPUID_0_07_EBX_SMEP |
288 CPUID_0_07_EBX_BMI2 |
289 CPUID_0_07_EBX_ERMS |
290 /* CPUID_0_07_EBX_INVPCID excluded, but re-included in VMX */
291 /* CPUID_0_07_EBX_RTM excluded */
292 /* CPUID_0_07_EBX_QM excluded */
293 CPUID_0_07_EBX_FPUCSDS |
294 /* CPUID_0_07_EBX_MPX excluded */
295 /* CPUID_0_07_EBX_PQE excluded */
296 /* CPUID_0_07_EBX_AVX512F excluded */
297 /* CPUID_0_07_EBX_AVX512DQ excluded */
298 CPUID_0_07_EBX_RDSEED |
299 CPUID_0_07_EBX_ADX |
300 CPUID_0_07_EBX_SMAP |
301 /* CPUID_0_07_EBX_AVX512_IFMA excluded */
302 CPUID_0_07_EBX_CLFLUSHOPT |
303 CPUID_0_07_EBX_CLWB,
304 /* CPUID_0_07_EBX_PT excluded */
305 /* CPUID_0_07_EBX_AVX512PF excluded */
306 /* CPUID_0_07_EBX_AVX512ER excluded */
307 /* CPUID_0_07_EBX_AVX512CD excluded */
308 /* CPUID_0_07_EBX_SHA excluded */
309 /* CPUID_0_07_EBX_AVX512BW excluded */
310 /* CPUID_0_07_EBX_AVX512VL excluded */
311 .ecx =
312 CPUID_0_07_ECX_PREFETCHWT1 |
313 /* CPUID_0_07_ECX_AVX512_VBMI excluded */
314 CPUID_0_07_ECX_UMIP |
315 /* CPUID_0_07_ECX_PKU excluded */
316 /* CPUID_0_07_ECX_OSPKE excluded */
317 /* CPUID_0_07_ECX_WAITPKG excluded */
318 /* CPUID_0_07_ECX_AVX512_VBMI2 excluded */
319 /* CPUID_0_07_ECX_CET_SS excluded */
320 CPUID_0_07_ECX_GFNI |
321 CPUID_0_07_ECX_VAES |
322 CPUID_0_07_ECX_VPCLMULQDQ |
323 /* CPUID_0_07_ECX_AVX512_VNNI excluded */
324 /* CPUID_0_07_ECX_AVX512_BITALG excluded */
325 /* CPUID_0_07_ECX_AVX512_VPOPCNTDQ excluded */
326 /* CPUID_0_07_ECX_LA57 excluded */
327 /* CPUID_0_07_ECX_MAWAU excluded */
328 /* CPUID_0_07_ECX_RDPID excluded */
329 CPUID_0_07_ECX_CLDEMOTE |
330 CPUID_0_07_ECX_MOVDIRI |
331 CPUID_0_07_ECX_MOVDIR64B,
332 /* CPUID_0_07_ECX_SGXLC excluded */
333 /* CPUID_0_07_ECX_PKS excluded */
334 .edx =
335 /* CPUID_0_07_EDX_AVX512_4VNNIW excluded */
336 /* CPUID_0_07_EDX_AVX512_4FMAPS excluded */
337 CPUID_0_07_EDX_FSREP_MOV |
338 /* CPUID_0_07_EDX_AVX512_VP2INTERSECT excluded */
339 /* CPUID_0_07_EDX_SRBDS_CTRL excluded */
340 CPUID_0_07_EDX_MD_CLEAR |
341 /* CPUID_0_07_EDX_TSX_FORCE_ABORT excluded */
342 CPUID_0_07_EDX_SERIALIZE |
343 /* CPUID_0_07_EDX_HYBRID excluded */
344 /* CPUID_0_07_EDX_TSXLDTRK excluded */
345 /* CPUID_0_07_EDX_CET_IBT excluded */
346 /* CPUID_0_07_EDX_IBRS excluded */
347 /* CPUID_0_07_EDX_STIBP excluded */
348 /* CPUID_0_07_EDX_L1D_FLUSH excluded */
349 CPUID_0_07_EDX_ARCH_CAP
350 /* CPUID_0_07_EDX_CORE_CAP excluded */
351 /* CPUID_0_07_EDX_SSBD excluded */
352 };
353
354 const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000001 = {
355 .eax = ~0,
356 .ebx = ~0,
357 .ecx =
358 CPUID_8_01_ECX_LAHF |
359 CPUID_8_01_ECX_CMPLEGACY |
360 /* CPUID_8_01_ECX_SVM excluded */
361 /* CPUID_8_01_ECX_EAPIC excluded */
362 CPUID_8_01_ECX_ALTMOVCR8 |
363 CPUID_8_01_ECX_ABM |
364 CPUID_8_01_ECX_SSE4A |
365 CPUID_8_01_ECX_MISALIGNSSE |
366 CPUID_8_01_ECX_3DNOWPF |
367 /* CPUID_8_01_ECX_OSVW excluded */
368 /* CPUID_8_01_ECX_IBS excluded */
369 CPUID_8_01_ECX_XOP |
370 /* CPUID_8_01_ECX_SKINIT excluded */
371 /* CPUID_8_01_ECX_WDT excluded */
372 /* CPUID_8_01_ECX_LWP excluded */
373 CPUID_8_01_ECX_FMA4 |
374 CPUID_8_01_ECX_TCE |
375 /* CPUID_8_01_ECX_NODEID excluded */
376 CPUID_8_01_ECX_TBM |
377 CPUID_8_01_ECX_TOPOEXT,
378 /* CPUID_8_01_ECX_PCEC excluded */
379 /* CPUID_8_01_ECX_PCENB excluded */
380 /* CPUID_8_01_ECX_DBE excluded */
381 /* CPUID_8_01_ECX_PERFTSC excluded */
382 /* CPUID_8_01_ECX_PERFEXTLLC excluded */
383 /* CPUID_8_01_ECX_MWAITX excluded */
384 .edx =
385 CPUID_8_01_EDX_FPU |
386 CPUID_8_01_EDX_VME |
387 CPUID_8_01_EDX_DE |
388 CPUID_8_01_EDX_PSE |
389 CPUID_8_01_EDX_TSC |
390 CPUID_8_01_EDX_MSR |
391 CPUID_8_01_EDX_PAE |
392 /* CPUID_8_01_EDX_MCE excluded */
393 CPUID_8_01_EDX_CX8 |
394 CPUID_8_01_EDX_APIC |
395 CPUID_8_01_EDX_SYSCALL |
396 /* CPUID_8_01_EDX_MTRR excluded */
397 CPUID_8_01_EDX_PGE |
398 /* CPUID_8_01_EDX_MCA excluded */
399 CPUID_8_01_EDX_CMOV |
400 CPUID_8_01_EDX_PAT |
401 CPUID_8_01_EDX_PSE36 |
402 CPUID_8_01_EDX_XD |
403 CPUID_8_01_EDX_MMXEXT |
404 CPUID_8_01_EDX_MMX |
405 CPUID_8_01_EDX_FXSR |
406 CPUID_8_01_EDX_FFXSR |
407 CPUID_8_01_EDX_PAGE1GB |
408 /* CPUID_8_01_EDX_RDTSCP excluded */
409 CPUID_8_01_EDX_LM |
410 CPUID_8_01_EDX_3DNOWEXT |
411 CPUID_8_01_EDX_3DNOW
412 };
413
414 const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000007 = {
415 .eax = 0,
416 .ebx = 0,
417 .ecx = 0,
418 .edx =
419 /* CPUID_8_07_EDX_TS excluded */
420 /* CPUID_8_07_EDX_FID excluded */
421 /* CPUID_8_07_EDX_VID excluded */
422 /* CPUID_8_07_EDX_TTP excluded */
423 /* CPUID_8_07_EDX_TM excluded */
424 /* CPUID_8_07_EDX_100MHzSteps excluded */
425 /* CPUID_8_07_EDX_HwPstate excluded */
426 CPUID_8_07_EDX_TscInvariant,
427 /* CPUID_8_07_EDX_CPB excluded */
428 /* CPUID_8_07_EDX_EffFreqRO excluded */
429 /* CPUID_8_07_EDX_ProcFeedbackIntf excluded */
430 /* CPUID_8_07_EDX_ProcPowerReport excluded */
431 };
432
433 const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000008 = {
434 .eax = ~0,
435 .ebx =
436 CPUID_8_08_EBX_CLZERO |
437 /* CPUID_8_08_EBX_InstRetCntMsr excluded */
438 CPUID_8_08_EBX_RstrFpErrPtrs |
439 /* CPUID_8_08_EBX_INVLPGB excluded */
440 /* CPUID_8_08_EBX_RDPRU excluded */
441 /* CPUID_8_08_EBX_MCOMMIT excluded */
442 CPUID_8_08_EBX_WBNOINVD,
443 /* CPUID_8_08_EBX_IBPB excluded */
444 /* CPUID_8_08_EBX_INT_WBINVD excluded */
445 /* CPUID_8_08_EBX_IBRS excluded */
446 /* CPUID_8_08_EBX_EferLmsleUnsupp excluded */
447 /* CPUID_8_08_EBX_INVLPGBnestedPg excluded */
448 /* CPUID_8_08_EBX_STIBP excluded */
449 /* CPUID_8_08_EBX_IBRS_ALWAYSON excluded */
450 /* CPUID_8_08_EBX_STIBP_ALWAYSON excluded */
451 /* CPUID_8_08_EBX_PREFER_IBRS excluded */
452 /* CPUID_8_08_EBX_SSBD excluded */
453 /* CPUID_8_08_EBX_VIRT_SSBD excluded */
454 /* CPUID_8_08_EBX_SSB_NO excluded */
455 .ecx = 0,
456 .edx = 0
457 };
458
459 bool
nvmm_x86_pat_validate(uint64_t val)460 nvmm_x86_pat_validate(uint64_t val)
461 {
462 uint8_t *pat = (uint8_t *)&val;
463 size_t i;
464
465 for (i = 0; i < 8; i++) {
466 if (__predict_false(pat[i] & ~__BITS(2,0)))
467 return false;
468 if (__predict_false(pat[i] == 2 || pat[i] == 3))
469 return false;
470 }
471
472 return true;
473 }
474
475 uint32_t
nvmm_x86_xsave_size(uint64_t xcr0)476 nvmm_x86_xsave_size(uint64_t xcr0)
477 {
478 uint32_t size;
479
480 if (xcr0 & XCR0_SSE) {
481 size = 512; /* x87 + SSE */
482 } else {
483 size = 108; /* x87 */
484 }
485 size += 64; /* XSAVE header */
486
487 return size;
488 }
489