xref: /dragonfly/sys/dev/virtual/nvmm/x86/nvmm_x86.c (revision 42862644e8ee2665cba60cb87a8169a3292cda97)
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