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