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