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