1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2011 NetApp, Inc. 5 * All rights reserved. 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 NETAPP, INC ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, 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 * $FreeBSD$ 29 */ 30 31 #include "opt_ddb.h" 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include <sys/param.h> 37 #include <sys/sysctl.h> 38 #include <sys/systm.h> 39 #include <sys/pcpu.h> 40 41 #include <vm/vm.h> 42 #include <vm/pmap.h> 43 44 #include <machine/segments.h> 45 #include <machine/vmm.h> 46 #include "vmm_host.h" 47 #include "vmx_cpufunc.h" 48 #include "vmcs.h" 49 #include "ept.h" 50 #include "vmx.h" 51 52 #ifdef DDB 53 #include <ddb/ddb.h> 54 #endif 55 56 SYSCTL_DECL(_hw_vmm_vmx); 57 58 static int no_flush_rsb; 59 SYSCTL_INT(_hw_vmm_vmx, OID_AUTO, no_flush_rsb, CTLFLAG_RW, 60 &no_flush_rsb, 0, "Do not flush RSB upon vmexit"); 61 62 static uint64_t 63 vmcs_fix_regval(uint32_t encoding, uint64_t val) 64 { 65 66 switch (encoding) { 67 case VMCS_GUEST_CR0: 68 val = vmx_fix_cr0(val); 69 break; 70 case VMCS_GUEST_CR4: 71 val = vmx_fix_cr4(val); 72 break; 73 default: 74 break; 75 } 76 return (val); 77 } 78 79 static uint32_t 80 vmcs_field_encoding(int ident) 81 { 82 switch (ident) { 83 case VM_REG_GUEST_CR0: 84 return (VMCS_GUEST_CR0); 85 case VM_REG_GUEST_CR3: 86 return (VMCS_GUEST_CR3); 87 case VM_REG_GUEST_CR4: 88 return (VMCS_GUEST_CR4); 89 case VM_REG_GUEST_DR7: 90 return (VMCS_GUEST_DR7); 91 case VM_REG_GUEST_RSP: 92 return (VMCS_GUEST_RSP); 93 case VM_REG_GUEST_RIP: 94 return (VMCS_GUEST_RIP); 95 case VM_REG_GUEST_RFLAGS: 96 return (VMCS_GUEST_RFLAGS); 97 case VM_REG_GUEST_ES: 98 return (VMCS_GUEST_ES_SELECTOR); 99 case VM_REG_GUEST_CS: 100 return (VMCS_GUEST_CS_SELECTOR); 101 case VM_REG_GUEST_SS: 102 return (VMCS_GUEST_SS_SELECTOR); 103 case VM_REG_GUEST_DS: 104 return (VMCS_GUEST_DS_SELECTOR); 105 case VM_REG_GUEST_FS: 106 return (VMCS_GUEST_FS_SELECTOR); 107 case VM_REG_GUEST_GS: 108 return (VMCS_GUEST_GS_SELECTOR); 109 case VM_REG_GUEST_TR: 110 return (VMCS_GUEST_TR_SELECTOR); 111 case VM_REG_GUEST_LDTR: 112 return (VMCS_GUEST_LDTR_SELECTOR); 113 case VM_REG_GUEST_EFER: 114 return (VMCS_GUEST_IA32_EFER); 115 case VM_REG_GUEST_PDPTE0: 116 return (VMCS_GUEST_PDPTE0); 117 case VM_REG_GUEST_PDPTE1: 118 return (VMCS_GUEST_PDPTE1); 119 case VM_REG_GUEST_PDPTE2: 120 return (VMCS_GUEST_PDPTE2); 121 case VM_REG_GUEST_PDPTE3: 122 return (VMCS_GUEST_PDPTE3); 123 case VM_REG_GUEST_ENTRY_INST_LENGTH: 124 return (VMCS_ENTRY_INST_LENGTH); 125 default: 126 return (-1); 127 } 128 129 } 130 131 static int 132 vmcs_seg_desc_encoding(int seg, uint32_t *base, uint32_t *lim, uint32_t *acc) 133 { 134 135 switch (seg) { 136 case VM_REG_GUEST_ES: 137 *base = VMCS_GUEST_ES_BASE; 138 *lim = VMCS_GUEST_ES_LIMIT; 139 *acc = VMCS_GUEST_ES_ACCESS_RIGHTS; 140 break; 141 case VM_REG_GUEST_CS: 142 *base = VMCS_GUEST_CS_BASE; 143 *lim = VMCS_GUEST_CS_LIMIT; 144 *acc = VMCS_GUEST_CS_ACCESS_RIGHTS; 145 break; 146 case VM_REG_GUEST_SS: 147 *base = VMCS_GUEST_SS_BASE; 148 *lim = VMCS_GUEST_SS_LIMIT; 149 *acc = VMCS_GUEST_SS_ACCESS_RIGHTS; 150 break; 151 case VM_REG_GUEST_DS: 152 *base = VMCS_GUEST_DS_BASE; 153 *lim = VMCS_GUEST_DS_LIMIT; 154 *acc = VMCS_GUEST_DS_ACCESS_RIGHTS; 155 break; 156 case VM_REG_GUEST_FS: 157 *base = VMCS_GUEST_FS_BASE; 158 *lim = VMCS_GUEST_FS_LIMIT; 159 *acc = VMCS_GUEST_FS_ACCESS_RIGHTS; 160 break; 161 case VM_REG_GUEST_GS: 162 *base = VMCS_GUEST_GS_BASE; 163 *lim = VMCS_GUEST_GS_LIMIT; 164 *acc = VMCS_GUEST_GS_ACCESS_RIGHTS; 165 break; 166 case VM_REG_GUEST_TR: 167 *base = VMCS_GUEST_TR_BASE; 168 *lim = VMCS_GUEST_TR_LIMIT; 169 *acc = VMCS_GUEST_TR_ACCESS_RIGHTS; 170 break; 171 case VM_REG_GUEST_LDTR: 172 *base = VMCS_GUEST_LDTR_BASE; 173 *lim = VMCS_GUEST_LDTR_LIMIT; 174 *acc = VMCS_GUEST_LDTR_ACCESS_RIGHTS; 175 break; 176 case VM_REG_GUEST_IDTR: 177 *base = VMCS_GUEST_IDTR_BASE; 178 *lim = VMCS_GUEST_IDTR_LIMIT; 179 *acc = VMCS_INVALID_ENCODING; 180 break; 181 case VM_REG_GUEST_GDTR: 182 *base = VMCS_GUEST_GDTR_BASE; 183 *lim = VMCS_GUEST_GDTR_LIMIT; 184 *acc = VMCS_INVALID_ENCODING; 185 break; 186 default: 187 return (EINVAL); 188 } 189 190 return (0); 191 } 192 193 int 194 vmcs_getreg(struct vmcs *vmcs, int running, int ident, uint64_t *retval) 195 { 196 int error; 197 uint32_t encoding; 198 199 /* 200 * If we need to get at vmx-specific state in the VMCS we can bypass 201 * the translation of 'ident' to 'encoding' by simply setting the 202 * sign bit. As it so happens the upper 16 bits are reserved (i.e 203 * set to 0) in the encodings for the VMCS so we are free to use the 204 * sign bit. 205 */ 206 if (ident < 0) 207 encoding = ident & 0x7fffffff; 208 else 209 encoding = vmcs_field_encoding(ident); 210 211 if (encoding == (uint32_t)-1) 212 return (EINVAL); 213 214 if (!running) 215 VMPTRLD(vmcs); 216 217 error = vmread(encoding, retval); 218 219 if (!running) 220 VMCLEAR(vmcs); 221 222 return (error); 223 } 224 225 int 226 vmcs_setreg(struct vmcs *vmcs, int running, int ident, uint64_t val) 227 { 228 int error; 229 uint32_t encoding; 230 231 if (ident < 0) 232 encoding = ident & 0x7fffffff; 233 else 234 encoding = vmcs_field_encoding(ident); 235 236 if (encoding == (uint32_t)-1) 237 return (EINVAL); 238 239 val = vmcs_fix_regval(encoding, val); 240 241 if (!running) 242 VMPTRLD(vmcs); 243 244 error = vmwrite(encoding, val); 245 246 if (!running) 247 VMCLEAR(vmcs); 248 249 return (error); 250 } 251 252 int 253 vmcs_setdesc(struct vmcs *vmcs, int running, int seg, struct seg_desc *desc) 254 { 255 int error; 256 uint32_t base, limit, access; 257 258 error = vmcs_seg_desc_encoding(seg, &base, &limit, &access); 259 if (error != 0) 260 panic("vmcs_setdesc: invalid segment register %d", seg); 261 262 if (!running) 263 VMPTRLD(vmcs); 264 if ((error = vmwrite(base, desc->base)) != 0) 265 goto done; 266 267 if ((error = vmwrite(limit, desc->limit)) != 0) 268 goto done; 269 270 if (access != VMCS_INVALID_ENCODING) { 271 if ((error = vmwrite(access, desc->access)) != 0) 272 goto done; 273 } 274 done: 275 if (!running) 276 VMCLEAR(vmcs); 277 return (error); 278 } 279 280 int 281 vmcs_getdesc(struct vmcs *vmcs, int running, int seg, struct seg_desc *desc) 282 { 283 int error; 284 uint32_t base, limit, access; 285 uint64_t u64; 286 287 error = vmcs_seg_desc_encoding(seg, &base, &limit, &access); 288 if (error != 0) 289 panic("vmcs_getdesc: invalid segment register %d", seg); 290 291 if (!running) 292 VMPTRLD(vmcs); 293 if ((error = vmread(base, &u64)) != 0) 294 goto done; 295 desc->base = u64; 296 297 if ((error = vmread(limit, &u64)) != 0) 298 goto done; 299 desc->limit = u64; 300 301 if (access != VMCS_INVALID_ENCODING) { 302 if ((error = vmread(access, &u64)) != 0) 303 goto done; 304 desc->access = u64; 305 } 306 done: 307 if (!running) 308 VMCLEAR(vmcs); 309 return (error); 310 } 311 312 int 313 vmcs_set_msr_save(struct vmcs *vmcs, u_long g_area, u_int g_count) 314 { 315 int error; 316 317 VMPTRLD(vmcs); 318 319 /* 320 * Guest MSRs are saved in the VM-exit MSR-store area. 321 * Guest MSRs are loaded from the VM-entry MSR-load area. 322 * Both areas point to the same location in memory. 323 */ 324 if ((error = vmwrite(VMCS_EXIT_MSR_STORE, g_area)) != 0) 325 goto done; 326 if ((error = vmwrite(VMCS_EXIT_MSR_STORE_COUNT, g_count)) != 0) 327 goto done; 328 329 if ((error = vmwrite(VMCS_ENTRY_MSR_LOAD, g_area)) != 0) 330 goto done; 331 if ((error = vmwrite(VMCS_ENTRY_MSR_LOAD_COUNT, g_count)) != 0) 332 goto done; 333 334 error = 0; 335 done: 336 VMCLEAR(vmcs); 337 return (error); 338 } 339 340 int 341 vmcs_init(struct vmcs *vmcs) 342 { 343 int error, codesel, datasel, tsssel; 344 u_long cr0, cr4, efer; 345 uint64_t pat, fsbase, idtrbase; 346 347 codesel = vmm_get_host_codesel(); 348 datasel = vmm_get_host_datasel(); 349 tsssel = vmm_get_host_tsssel(); 350 351 /* 352 * Make sure we have a "current" VMCS to work with. 353 */ 354 VMPTRLD(vmcs); 355 356 /* Host state */ 357 358 /* Initialize host IA32_PAT MSR */ 359 pat = vmm_get_host_pat(); 360 if ((error = vmwrite(VMCS_HOST_IA32_PAT, pat)) != 0) 361 goto done; 362 363 /* Load the IA32_EFER MSR */ 364 efer = vmm_get_host_efer(); 365 if ((error = vmwrite(VMCS_HOST_IA32_EFER, efer)) != 0) 366 goto done; 367 368 /* Load the control registers */ 369 370 cr0 = vmm_get_host_cr0(); 371 if ((error = vmwrite(VMCS_HOST_CR0, cr0)) != 0) 372 goto done; 373 374 cr4 = vmm_get_host_cr4() | CR4_VMXE; 375 if ((error = vmwrite(VMCS_HOST_CR4, cr4)) != 0) 376 goto done; 377 378 /* Load the segment selectors */ 379 if ((error = vmwrite(VMCS_HOST_ES_SELECTOR, datasel)) != 0) 380 goto done; 381 382 if ((error = vmwrite(VMCS_HOST_CS_SELECTOR, codesel)) != 0) 383 goto done; 384 385 if ((error = vmwrite(VMCS_HOST_SS_SELECTOR, datasel)) != 0) 386 goto done; 387 388 if ((error = vmwrite(VMCS_HOST_DS_SELECTOR, datasel)) != 0) 389 goto done; 390 391 if ((error = vmwrite(VMCS_HOST_FS_SELECTOR, datasel)) != 0) 392 goto done; 393 394 if ((error = vmwrite(VMCS_HOST_GS_SELECTOR, datasel)) != 0) 395 goto done; 396 397 if ((error = vmwrite(VMCS_HOST_TR_SELECTOR, tsssel)) != 0) 398 goto done; 399 400 /* 401 * Load the Base-Address for %fs and idtr. 402 * 403 * Note that we exclude %gs, tss and gdtr here because their base 404 * address is pcpu specific. 405 */ 406 fsbase = vmm_get_host_fsbase(); 407 if ((error = vmwrite(VMCS_HOST_FS_BASE, fsbase)) != 0) 408 goto done; 409 410 idtrbase = vmm_get_host_idtrbase(); 411 if ((error = vmwrite(VMCS_HOST_IDTR_BASE, idtrbase)) != 0) 412 goto done; 413 414 /* instruction pointer */ 415 if (no_flush_rsb) { 416 if ((error = vmwrite(VMCS_HOST_RIP, 417 (u_long)vmx_exit_guest)) != 0) 418 goto done; 419 } else { 420 if ((error = vmwrite(VMCS_HOST_RIP, 421 (u_long)vmx_exit_guest_flush_rsb)) != 0) 422 goto done; 423 } 424 425 /* link pointer */ 426 if ((error = vmwrite(VMCS_LINK_POINTER, ~0)) != 0) 427 goto done; 428 done: 429 VMCLEAR(vmcs); 430 return (error); 431 } 432 433 #ifdef DDB 434 extern int vmxon_enabled[]; 435 436 DB_SHOW_COMMAND(vmcs, db_show_vmcs) 437 { 438 uint64_t cur_vmcs, val; 439 uint32_t exit; 440 441 if (!vmxon_enabled[curcpu]) { 442 db_printf("VMX not enabled\n"); 443 return; 444 } 445 446 if (have_addr) { 447 db_printf("Only current VMCS supported\n"); 448 return; 449 } 450 451 vmptrst(&cur_vmcs); 452 if (cur_vmcs == VMCS_INITIAL) { 453 db_printf("No current VM context\n"); 454 return; 455 } 456 db_printf("VMCS: %jx\n", cur_vmcs); 457 db_printf("VPID: %lu\n", vmcs_read(VMCS_VPID)); 458 db_printf("Activity: "); 459 val = vmcs_read(VMCS_GUEST_ACTIVITY); 460 switch (val) { 461 case 0: 462 db_printf("Active"); 463 break; 464 case 1: 465 db_printf("HLT"); 466 break; 467 case 2: 468 db_printf("Shutdown"); 469 break; 470 case 3: 471 db_printf("Wait for SIPI"); 472 break; 473 default: 474 db_printf("Unknown: %#lx", val); 475 } 476 db_printf("\n"); 477 exit = vmcs_read(VMCS_EXIT_REASON); 478 if (exit & 0x80000000) 479 db_printf("Entry Failure Reason: %u\n", exit & 0xffff); 480 else 481 db_printf("Exit Reason: %u\n", exit & 0xffff); 482 db_printf("Qualification: %#lx\n", vmcs_exit_qualification()); 483 db_printf("Guest Linear Address: %#lx\n", 484 vmcs_read(VMCS_GUEST_LINEAR_ADDRESS)); 485 switch (exit & 0x8000ffff) { 486 case EXIT_REASON_EXCEPTION: 487 case EXIT_REASON_EXT_INTR: 488 val = vmcs_read(VMCS_EXIT_INTR_INFO); 489 db_printf("Interrupt Type: "); 490 switch (val >> 8 & 0x7) { 491 case 0: 492 db_printf("external"); 493 break; 494 case 2: 495 db_printf("NMI"); 496 break; 497 case 3: 498 db_printf("HW exception"); 499 break; 500 case 4: 501 db_printf("SW exception"); 502 break; 503 default: 504 db_printf("?? %lu", val >> 8 & 0x7); 505 break; 506 } 507 db_printf(" Vector: %lu", val & 0xff); 508 if (val & 0x800) 509 db_printf(" Error Code: %lx", 510 vmcs_read(VMCS_EXIT_INTR_ERRCODE)); 511 db_printf("\n"); 512 break; 513 case EXIT_REASON_EPT_FAULT: 514 case EXIT_REASON_EPT_MISCONFIG: 515 db_printf("Guest Physical Address: %#lx\n", 516 vmcs_read(VMCS_GUEST_PHYSICAL_ADDRESS)); 517 break; 518 } 519 db_printf("VM-instruction error: %#lx\n", vmcs_instruction_error()); 520 } 521 #endif 522