1 /* $NetBSD: nvmm_x86.c,v 1.17 2020/09/05 07:22:26 maxv Exp $ */ 2 3 /* 4 * Copyright (c) 2018-2020 Maxime Villard, m00nbsd.net 5 * All rights reserved. 6 * 7 * This code is part of the NVMM hypervisor. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: nvmm_x86.c,v 1.17 2020/09/05 07:22:26 maxv Exp $"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/cpu.h> 38 39 #include <uvm/uvm.h> 40 #include <uvm/uvm_page.h> 41 42 #include <x86/cputypes.h> 43 #include <x86/specialreg.h> 44 #include <x86/pmap.h> 45 46 #include <dev/nvmm/nvmm.h> 47 #include <dev/nvmm/nvmm_internal.h> 48 #include <dev/nvmm/x86/nvmm_x86.h> 49 50 /* 51 * Code shared between x86-SVM and x86-VMX. 52 */ 53 54 const struct nvmm_x64_state nvmm_x86_reset_state = { 55 .segs = { 56 [NVMM_X64_SEG_ES] = { 57 .selector = 0x0000, 58 .base = 0x00000000, 59 .limit = 0xFFFF, 60 .attrib = { 61 .type = 3, 62 .s = 1, 63 .p = 1, 64 } 65 }, 66 [NVMM_X64_SEG_CS] = { 67 .selector = 0xF000, 68 .base = 0xFFFF0000, 69 .limit = 0xFFFF, 70 .attrib = { 71 .type = 3, 72 .s = 1, 73 .p = 1, 74 } 75 }, 76 [NVMM_X64_SEG_SS] = { 77 .selector = 0x0000, 78 .base = 0x00000000, 79 .limit = 0xFFFF, 80 .attrib = { 81 .type = 3, 82 .s = 1, 83 .p = 1, 84 } 85 }, 86 [NVMM_X64_SEG_DS] = { 87 .selector = 0x0000, 88 .base = 0x00000000, 89 .limit = 0xFFFF, 90 .attrib = { 91 .type = 3, 92 .s = 1, 93 .p = 1, 94 } 95 }, 96 [NVMM_X64_SEG_FS] = { 97 .selector = 0x0000, 98 .base = 0x00000000, 99 .limit = 0xFFFF, 100 .attrib = { 101 .type = 3, 102 .s = 1, 103 .p = 1, 104 } 105 }, 106 [NVMM_X64_SEG_GS] = { 107 .selector = 0x0000, 108 .base = 0x00000000, 109 .limit = 0xFFFF, 110 .attrib = { 111 .type = 3, 112 .s = 1, 113 .p = 1, 114 } 115 }, 116 [NVMM_X64_SEG_GDT] = { 117 .selector = 0x0000, 118 .base = 0x00000000, 119 .limit = 0xFFFF, 120 .attrib = { 121 .type = 2, 122 .s = 1, 123 .p = 1, 124 } 125 }, 126 [NVMM_X64_SEG_IDT] = { 127 .selector = 0x0000, 128 .base = 0x00000000, 129 .limit = 0xFFFF, 130 .attrib = { 131 .type = 2, 132 .s = 1, 133 .p = 1, 134 } 135 }, 136 [NVMM_X64_SEG_LDT] = { 137 .selector = 0x0000, 138 .base = 0x00000000, 139 .limit = 0xFFFF, 140 .attrib = { 141 .type = SDT_SYSLDT, 142 .s = 0, 143 .p = 1, 144 } 145 }, 146 [NVMM_X64_SEG_TR] = { 147 .selector = 0x0000, 148 .base = 0x00000000, 149 .limit = 0xFFFF, 150 .attrib = { 151 .type = SDT_SYS286BSY, 152 .s = 0, 153 .p = 1, 154 } 155 }, 156 }, 157 158 .gprs = { 159 [NVMM_X64_GPR_RAX] = 0x00000000, 160 [NVMM_X64_GPR_RCX] = 0x00000000, 161 [NVMM_X64_GPR_RDX] = 0x00000600, 162 [NVMM_X64_GPR_RBX] = 0x00000000, 163 [NVMM_X64_GPR_RSP] = 0x00000000, 164 [NVMM_X64_GPR_RBP] = 0x00000000, 165 [NVMM_X64_GPR_RSI] = 0x00000000, 166 [NVMM_X64_GPR_RDI] = 0x00000000, 167 [NVMM_X64_GPR_R8] = 0x00000000, 168 [NVMM_X64_GPR_R9] = 0x00000000, 169 [NVMM_X64_GPR_R10] = 0x00000000, 170 [NVMM_X64_GPR_R11] = 0x00000000, 171 [NVMM_X64_GPR_R12] = 0x00000000, 172 [NVMM_X64_GPR_R13] = 0x00000000, 173 [NVMM_X64_GPR_R14] = 0x00000000, 174 [NVMM_X64_GPR_R15] = 0x00000000, 175 [NVMM_X64_GPR_RIP] = 0x0000FFF0, 176 [NVMM_X64_GPR_RFLAGS] = 0x00000002, 177 }, 178 179 .crs = { 180 [NVMM_X64_CR_CR0] = 0x60000010, 181 [NVMM_X64_CR_CR2] = 0x00000000, 182 [NVMM_X64_CR_CR3] = 0x00000000, 183 [NVMM_X64_CR_CR4] = 0x00000000, 184 [NVMM_X64_CR_CR8] = 0x00000000, 185 [NVMM_X64_CR_XCR0] = 0x00000001, 186 }, 187 188 .drs = { 189 [NVMM_X64_DR_DR0] = 0x00000000, 190 [NVMM_X64_DR_DR1] = 0x00000000, 191 [NVMM_X64_DR_DR2] = 0x00000000, 192 [NVMM_X64_DR_DR3] = 0x00000000, 193 [NVMM_X64_DR_DR6] = 0xFFFF0FF0, 194 [NVMM_X64_DR_DR7] = 0x00000400, 195 }, 196 197 .msrs = { 198 [NVMM_X64_MSR_EFER] = 0x00000000, 199 [NVMM_X64_MSR_STAR] = 0x00000000, 200 [NVMM_X64_MSR_LSTAR] = 0x00000000, 201 [NVMM_X64_MSR_CSTAR] = 0x00000000, 202 [NVMM_X64_MSR_SFMASK] = 0x00000000, 203 [NVMM_X64_MSR_KERNELGSBASE] = 0x00000000, 204 [NVMM_X64_MSR_SYSENTER_CS] = 0x00000000, 205 [NVMM_X64_MSR_SYSENTER_ESP] = 0x00000000, 206 [NVMM_X64_MSR_SYSENTER_EIP] = 0x00000000, 207 [NVMM_X64_MSR_PAT] = 208 PATENTRY(0, PAT_WB) | PATENTRY(1, PAT_WT) | 209 PATENTRY(2, PAT_UCMINUS) | PATENTRY(3, PAT_UC) | 210 PATENTRY(4, PAT_WB) | PATENTRY(5, PAT_WT) | 211 PATENTRY(6, PAT_UCMINUS) | PATENTRY(7, PAT_UC), 212 [NVMM_X64_MSR_TSC] = 0, 213 }, 214 215 .intr = { 216 .int_shadow = 0, 217 .int_window_exiting = 0, 218 .nmi_window_exiting = 0, 219 .evt_pending = 0, 220 }, 221 222 .fpu = { 223 .fx_cw = 0x0040, 224 .fx_sw = 0x0000, 225 .fx_tw = 0x55, 226 .fx_zero = 0x55, 227 .fx_mxcsr = 0x1F80, 228 } 229 }; 230 231 const struct nvmm_x86_cpuid_mask nvmm_cpuid_00000001 = { 232 .eax = ~0, 233 .ebx = ~0, 234 .ecx = 235 CPUID2_SSE3 | 236 CPUID2_PCLMUL | 237 /* CPUID2_DTES64 excluded */ 238 /* CPUID2_MONITOR excluded */ 239 /* CPUID2_DS_CPL excluded */ 240 /* CPUID2_VMX excluded */ 241 /* CPUID2_SMX excluded */ 242 /* CPUID2_EST excluded */ 243 /* CPUID2_TM2 excluded */ 244 CPUID2_SSSE3 | 245 /* CPUID2_CID excluded */ 246 /* CPUID2_SDBG excluded */ 247 CPUID2_FMA | 248 CPUID2_CX16 | 249 /* CPUID2_xTPR excluded */ 250 /* CPUID2_PDCM excluded */ 251 /* CPUID2_PCID excluded, but re-included in VMX */ 252 /* CPUID2_DCA excluded */ 253 CPUID2_SSE41 | 254 CPUID2_SSE42 | 255 /* CPUID2_X2APIC excluded */ 256 CPUID2_MOVBE | 257 CPUID2_POPCNT | 258 /* CPUID2_DEADLINE excluded */ 259 CPUID2_AES | 260 CPUID2_XSAVE | 261 CPUID2_OSXSAVE | 262 /* CPUID2_AVX excluded */ 263 CPUID2_F16C | 264 CPUID2_RDRAND, 265 /* CPUID2_RAZ excluded */ 266 .edx = 267 CPUID_FPU | 268 CPUID_VME | 269 CPUID_DE | 270 CPUID_PSE | 271 CPUID_TSC | 272 CPUID_MSR | 273 CPUID_PAE | 274 /* CPUID_MCE excluded */ 275 CPUID_CX8 | 276 CPUID_APIC | 277 CPUID_SEP | 278 /* CPUID_MTRR excluded */ 279 CPUID_PGE | 280 /* CPUID_MCA excluded */ 281 CPUID_CMOV | 282 CPUID_PAT | 283 CPUID_PSE36 | 284 /* CPUID_PN excluded */ 285 CPUID_CFLUSH | 286 /* CPUID_DS excluded */ 287 /* CPUID_ACPI excluded */ 288 CPUID_MMX | 289 CPUID_FXSR | 290 CPUID_SSE | 291 CPUID_SSE2 | 292 CPUID_SS | 293 CPUID_HTT | 294 /* CPUID_TM excluded */ 295 CPUID_SBF 296 }; 297 298 const struct nvmm_x86_cpuid_mask nvmm_cpuid_00000007 = { 299 .eax = ~0, 300 .ebx = 301 CPUID_SEF_FSGSBASE | 302 /* CPUID_SEF_TSC_ADJUST excluded */ 303 /* CPUID_SEF_SGX excluded */ 304 CPUID_SEF_BMI1 | 305 /* CPUID_SEF_HLE excluded */ 306 /* CPUID_SEF_AVX2 excluded */ 307 CPUID_SEF_FDPEXONLY | 308 CPUID_SEF_SMEP | 309 CPUID_SEF_BMI2 | 310 CPUID_SEF_ERMS | 311 /* CPUID_SEF_INVPCID excluded, but re-included in VMX */ 312 /* CPUID_SEF_RTM excluded */ 313 /* CPUID_SEF_QM excluded */ 314 CPUID_SEF_FPUCSDS | 315 /* CPUID_SEF_MPX excluded */ 316 CPUID_SEF_PQE | 317 /* CPUID_SEF_AVX512F excluded */ 318 /* CPUID_SEF_AVX512DQ excluded */ 319 CPUID_SEF_RDSEED | 320 CPUID_SEF_ADX | 321 CPUID_SEF_SMAP | 322 /* CPUID_SEF_AVX512_IFMA excluded */ 323 CPUID_SEF_CLFLUSHOPT | 324 CPUID_SEF_CLWB, 325 /* CPUID_SEF_PT excluded */ 326 /* CPUID_SEF_AVX512PF excluded */ 327 /* CPUID_SEF_AVX512ER excluded */ 328 /* CPUID_SEF_AVX512CD excluded */ 329 /* CPUID_SEF_SHA excluded */ 330 /* CPUID_SEF_AVX512BW excluded */ 331 /* CPUID_SEF_AVX512VL excluded */ 332 .ecx = 333 CPUID_SEF_PREFETCHWT1 | 334 /* CPUID_SEF_AVX512_VBMI excluded */ 335 CPUID_SEF_UMIP | 336 /* CPUID_SEF_PKU excluded */ 337 /* CPUID_SEF_OSPKE excluded */ 338 /* CPUID_SEF_WAITPKG excluded */ 339 /* CPUID_SEF_AVX512_VBMI2 excluded */ 340 /* CPUID_SEF_CET_SS excluded */ 341 CPUID_SEF_GFNI | 342 CPUID_SEF_VAES | 343 CPUID_SEF_VPCLMULQDQ | 344 /* CPUID_SEF_AVX512_VNNI excluded */ 345 /* CPUID_SEF_AVX512_BITALG excluded */ 346 /* CPUID_SEF_AVX512_VPOPCNTDQ excluded */ 347 /* CPUID_SEF_MAWAU excluded */ 348 /* CPUID_SEF_RDPID excluded */ 349 CPUID_SEF_CLDEMOTE | 350 CPUID_SEF_MOVDIRI | 351 CPUID_SEF_MOVDIR64B, 352 /* CPUID_SEF_SGXLC excluded */ 353 /* CPUID_SEF_PKS excluded */ 354 .edx = 355 /* CPUID_SEF_AVX512_4VNNIW excluded */ 356 /* CPUID_SEF_AVX512_4FMAPS excluded */ 357 CPUID_SEF_FSREP_MOV | 358 /* CPUID_SEF_AVX512_VP2INTERSECT excluded */ 359 /* CPUID_SEF_SRBDS_CTRL excluded */ 360 CPUID_SEF_MD_CLEAR | 361 /* CPUID_SEF_TSX_FORCE_ABORT excluded */ 362 CPUID_SEF_SERIALIZE | 363 /* CPUID_SEF_HYBRID excluded */ 364 /* CPUID_SEF_TSXLDTRK excluded */ 365 /* CPUID_SEF_CET_IBT excluded */ 366 /* CPUID_SEF_IBRS excluded */ 367 /* CPUID_SEF_STIBP excluded */ 368 /* CPUID_SEF_L1D_FLUSH excluded */ 369 CPUID_SEF_ARCH_CAP 370 /* CPUID_SEF_CORE_CAP excluded */ 371 /* CPUID_SEF_SSBD excluded */ 372 }; 373 374 const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000001 = { 375 .eax = ~0, 376 .ebx = ~0, 377 .ecx = 378 CPUID_LAHF | 379 CPUID_CMPLEGACY | 380 /* CPUID_SVM excluded */ 381 /* CPUID_EAPIC excluded */ 382 CPUID_ALTMOVCR0 | 383 CPUID_LZCNT | 384 CPUID_SSE4A | 385 CPUID_MISALIGNSSE | 386 CPUID_3DNOWPF | 387 /* CPUID_OSVW excluded */ 388 /* CPUID_IBS excluded */ 389 CPUID_XOP | 390 /* CPUID_SKINIT excluded */ 391 /* CPUID_WDT excluded */ 392 /* CPUID_LWP excluded */ 393 CPUID_FMA4 | 394 CPUID_TCE | 395 /* CPUID_NODEID excluded */ 396 CPUID_TBM | 397 CPUID_TOPOEXT, 398 /* CPUID_PCEC excluded */ 399 /* CPUID_PCENB excluded */ 400 /* CPUID_SPM excluded */ 401 /* CPUID_DBE excluded */ 402 /* CPUID_PTSC excluded */ 403 /* CPUID_L2IPERFC excluded */ 404 /* CPUID_MWAITX excluded */ 405 .edx = 406 CPUID_SYSCALL | 407 CPUID_MPC | 408 CPUID_XD | 409 CPUID_MMXX | 410 CPUID_MMX | 411 CPUID_FXSR | 412 CPUID_FFXSR | 413 CPUID_P1GB | 414 /* CPUID_RDTSCP excluded */ 415 CPUID_EM64T | 416 CPUID_3DNOW2 | 417 CPUID_3DNOW 418 }; 419 420 const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000007 = { 421 .eax = 0, 422 .ebx = 0, 423 .ecx = 0, 424 .edx = CPUID_APM_ITSC 425 }; 426 427 const struct nvmm_x86_cpuid_mask nvmm_cpuid_80000008 = { 428 .eax = ~0, 429 .ebx = 430 CPUID_CAPEX_CLZERO | 431 /* CPUID_CAPEX_IRPERF excluded */ 432 CPUID_CAPEX_XSAVEERPTR | 433 /* CPUID_CAPEX_RDPRU excluded */ 434 /* CPUID_CAPEX_MCOMMIT excluded */ 435 CPUID_CAPEX_WBNOINVD, 436 .ecx = ~0, /* TODO? */ 437 .edx = 0 438 }; 439 440 bool 441 nvmm_x86_pat_validate(uint64_t val) 442 { 443 uint8_t *pat = (uint8_t *)&val; 444 size_t i; 445 446 for (i = 0; i < 8; i++) { 447 if (__predict_false(pat[i] & ~__BITS(2,0))) 448 return false; 449 if (__predict_false(pat[i] == 2 || pat[i] == 3)) 450 return false; 451 } 452 453 return true; 454 } 455