vmcs.c revision 256072
1221828Sgrehan/*- 2221828Sgrehan * Copyright (c) 2011 NetApp, Inc. 3221828Sgrehan * All rights reserved. 4221828Sgrehan * 5221828Sgrehan * Redistribution and use in source and binary forms, with or without 6221828Sgrehan * modification, are permitted provided that the following conditions 7221828Sgrehan * are met: 8221828Sgrehan * 1. Redistributions of source code must retain the above copyright 9221828Sgrehan * notice, this list of conditions and the following disclaimer. 10221828Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 11221828Sgrehan * notice, this list of conditions and the following disclaimer in the 12221828Sgrehan * documentation and/or other materials provided with the distribution. 13221828Sgrehan * 14221828Sgrehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15221828Sgrehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16221828Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17221828Sgrehan * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18221828Sgrehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19221828Sgrehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20221828Sgrehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21221828Sgrehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22221828Sgrehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23221828Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24221828Sgrehan * SUCH DAMAGE. 25221828Sgrehan * 26221828Sgrehan * $FreeBSD: head/sys/amd64/vmm/intel/vmcs.c 256072 2013-10-05 21:22:35Z neel $ 27221828Sgrehan */ 28221828Sgrehan 29222605Sjhb#include "opt_ddb.h" 30222605Sjhb 31221828Sgrehan#include <sys/cdefs.h> 32221828Sgrehan__FBSDID("$FreeBSD: head/sys/amd64/vmm/intel/vmcs.c 256072 2013-10-05 21:22:35Z neel $"); 33221828Sgrehan 34221828Sgrehan#include <sys/param.h> 35221828Sgrehan#include <sys/systm.h> 36221828Sgrehan#include <sys/pcpu.h> 37221828Sgrehan 38221828Sgrehan#include <vm/vm.h> 39221828Sgrehan#include <vm/pmap.h> 40221828Sgrehan 41221828Sgrehan#include <machine/segments.h> 42221828Sgrehan#include <machine/pmap.h> 43221828Sgrehan 44221828Sgrehan#include <machine/vmm.h> 45242275Sneel#include "vmm_host.h" 46221828Sgrehan#include "vmcs.h" 47221828Sgrehan#include "vmx_cpufunc.h" 48221828Sgrehan#include "ept.h" 49221828Sgrehan#include "vmx.h" 50221828Sgrehan 51222605Sjhb#ifdef DDB 52222605Sjhb#include <ddb/ddb.h> 53222605Sjhb#endif 54222605Sjhb 55221828Sgrehanstatic uint64_t 56221828Sgrehanvmcs_fix_regval(uint32_t encoding, uint64_t val) 57221828Sgrehan{ 58221828Sgrehan 59221828Sgrehan switch (encoding) { 60221828Sgrehan case VMCS_GUEST_CR0: 61221828Sgrehan val = vmx_fix_cr0(val); 62221828Sgrehan break; 63221828Sgrehan case VMCS_GUEST_CR4: 64221828Sgrehan val = vmx_fix_cr4(val); 65221828Sgrehan break; 66221828Sgrehan default: 67221828Sgrehan break; 68221828Sgrehan } 69221828Sgrehan return (val); 70221828Sgrehan} 71221828Sgrehan 72221828Sgrehanstatic uint32_t 73221828Sgrehanvmcs_field_encoding(int ident) 74221828Sgrehan{ 75221828Sgrehan switch (ident) { 76221828Sgrehan case VM_REG_GUEST_CR0: 77221828Sgrehan return (VMCS_GUEST_CR0); 78221828Sgrehan case VM_REG_GUEST_CR3: 79221828Sgrehan return (VMCS_GUEST_CR3); 80221828Sgrehan case VM_REG_GUEST_CR4: 81221828Sgrehan return (VMCS_GUEST_CR4); 82221828Sgrehan case VM_REG_GUEST_DR7: 83221828Sgrehan return (VMCS_GUEST_DR7); 84221828Sgrehan case VM_REG_GUEST_RSP: 85221828Sgrehan return (VMCS_GUEST_RSP); 86221828Sgrehan case VM_REG_GUEST_RIP: 87221828Sgrehan return (VMCS_GUEST_RIP); 88221828Sgrehan case VM_REG_GUEST_RFLAGS: 89221828Sgrehan return (VMCS_GUEST_RFLAGS); 90221828Sgrehan case VM_REG_GUEST_ES: 91221828Sgrehan return (VMCS_GUEST_ES_SELECTOR); 92221828Sgrehan case VM_REG_GUEST_CS: 93221828Sgrehan return (VMCS_GUEST_CS_SELECTOR); 94221828Sgrehan case VM_REG_GUEST_SS: 95221828Sgrehan return (VMCS_GUEST_SS_SELECTOR); 96221828Sgrehan case VM_REG_GUEST_DS: 97221828Sgrehan return (VMCS_GUEST_DS_SELECTOR); 98221828Sgrehan case VM_REG_GUEST_FS: 99221828Sgrehan return (VMCS_GUEST_FS_SELECTOR); 100221828Sgrehan case VM_REG_GUEST_GS: 101221828Sgrehan return (VMCS_GUEST_GS_SELECTOR); 102221828Sgrehan case VM_REG_GUEST_TR: 103221828Sgrehan return (VMCS_GUEST_TR_SELECTOR); 104221828Sgrehan case VM_REG_GUEST_LDTR: 105221828Sgrehan return (VMCS_GUEST_LDTR_SELECTOR); 106221828Sgrehan case VM_REG_GUEST_EFER: 107221828Sgrehan return (VMCS_GUEST_IA32_EFER); 108221828Sgrehan default: 109221828Sgrehan return (-1); 110221828Sgrehan } 111221828Sgrehan 112221828Sgrehan} 113221828Sgrehan 114221828Sgrehanstatic int 115221828Sgrehanvmcs_seg_desc_encoding(int seg, uint32_t *base, uint32_t *lim, uint32_t *acc) 116221828Sgrehan{ 117221828Sgrehan 118221828Sgrehan switch (seg) { 119221828Sgrehan case VM_REG_GUEST_ES: 120221828Sgrehan *base = VMCS_GUEST_ES_BASE; 121221828Sgrehan *lim = VMCS_GUEST_ES_LIMIT; 122221828Sgrehan *acc = VMCS_GUEST_ES_ACCESS_RIGHTS; 123221828Sgrehan break; 124221828Sgrehan case VM_REG_GUEST_CS: 125221828Sgrehan *base = VMCS_GUEST_CS_BASE; 126221828Sgrehan *lim = VMCS_GUEST_CS_LIMIT; 127221828Sgrehan *acc = VMCS_GUEST_CS_ACCESS_RIGHTS; 128221828Sgrehan break; 129221828Sgrehan case VM_REG_GUEST_SS: 130221828Sgrehan *base = VMCS_GUEST_SS_BASE; 131221828Sgrehan *lim = VMCS_GUEST_SS_LIMIT; 132221828Sgrehan *acc = VMCS_GUEST_SS_ACCESS_RIGHTS; 133221828Sgrehan break; 134221828Sgrehan case VM_REG_GUEST_DS: 135221828Sgrehan *base = VMCS_GUEST_DS_BASE; 136221828Sgrehan *lim = VMCS_GUEST_DS_LIMIT; 137221828Sgrehan *acc = VMCS_GUEST_DS_ACCESS_RIGHTS; 138221828Sgrehan break; 139221828Sgrehan case VM_REG_GUEST_FS: 140221828Sgrehan *base = VMCS_GUEST_FS_BASE; 141221828Sgrehan *lim = VMCS_GUEST_FS_LIMIT; 142221828Sgrehan *acc = VMCS_GUEST_FS_ACCESS_RIGHTS; 143221828Sgrehan break; 144221828Sgrehan case VM_REG_GUEST_GS: 145221828Sgrehan *base = VMCS_GUEST_GS_BASE; 146221828Sgrehan *lim = VMCS_GUEST_GS_LIMIT; 147221828Sgrehan *acc = VMCS_GUEST_GS_ACCESS_RIGHTS; 148221828Sgrehan break; 149221828Sgrehan case VM_REG_GUEST_TR: 150221828Sgrehan *base = VMCS_GUEST_TR_BASE; 151221828Sgrehan *lim = VMCS_GUEST_TR_LIMIT; 152221828Sgrehan *acc = VMCS_GUEST_TR_ACCESS_RIGHTS; 153221828Sgrehan break; 154221828Sgrehan case VM_REG_GUEST_LDTR: 155221828Sgrehan *base = VMCS_GUEST_LDTR_BASE; 156221828Sgrehan *lim = VMCS_GUEST_LDTR_LIMIT; 157221828Sgrehan *acc = VMCS_GUEST_LDTR_ACCESS_RIGHTS; 158221828Sgrehan break; 159221828Sgrehan case VM_REG_GUEST_IDTR: 160221828Sgrehan *base = VMCS_GUEST_IDTR_BASE; 161221828Sgrehan *lim = VMCS_GUEST_IDTR_LIMIT; 162221828Sgrehan *acc = VMCS_INVALID_ENCODING; 163221828Sgrehan break; 164221828Sgrehan case VM_REG_GUEST_GDTR: 165221828Sgrehan *base = VMCS_GUEST_GDTR_BASE; 166221828Sgrehan *lim = VMCS_GUEST_GDTR_LIMIT; 167221828Sgrehan *acc = VMCS_INVALID_ENCODING; 168221828Sgrehan break; 169221828Sgrehan default: 170221828Sgrehan return (EINVAL); 171221828Sgrehan } 172221828Sgrehan 173221828Sgrehan return (0); 174221828Sgrehan} 175221828Sgrehan 176221828Sgrehanint 177249879Sgrehanvmcs_getreg(struct vmcs *vmcs, int running, int ident, uint64_t *retval) 178221828Sgrehan{ 179221828Sgrehan int error; 180221828Sgrehan uint32_t encoding; 181221828Sgrehan 182221828Sgrehan /* 183221828Sgrehan * If we need to get at vmx-specific state in the VMCS we can bypass 184221828Sgrehan * the translation of 'ident' to 'encoding' by simply setting the 185221828Sgrehan * sign bit. As it so happens the upper 16 bits are reserved (i.e 186221828Sgrehan * set to 0) in the encodings for the VMCS so we are free to use the 187221828Sgrehan * sign bit. 188221828Sgrehan */ 189221828Sgrehan if (ident < 0) 190221828Sgrehan encoding = ident & 0x7fffffff; 191221828Sgrehan else 192221828Sgrehan encoding = vmcs_field_encoding(ident); 193221828Sgrehan 194221828Sgrehan if (encoding == (uint32_t)-1) 195221828Sgrehan return (EINVAL); 196221828Sgrehan 197249879Sgrehan if (!running) 198249879Sgrehan VMPTRLD(vmcs); 199249879Sgrehan 200221828Sgrehan error = vmread(encoding, retval); 201249879Sgrehan 202249879Sgrehan if (!running) 203249879Sgrehan VMCLEAR(vmcs); 204249879Sgrehan 205221828Sgrehan return (error); 206221828Sgrehan} 207221828Sgrehan 208221828Sgrehanint 209249879Sgrehanvmcs_setreg(struct vmcs *vmcs, int running, int ident, uint64_t val) 210221828Sgrehan{ 211221828Sgrehan int error; 212221828Sgrehan uint32_t encoding; 213221828Sgrehan 214221828Sgrehan if (ident < 0) 215221828Sgrehan encoding = ident & 0x7fffffff; 216221828Sgrehan else 217221828Sgrehan encoding = vmcs_field_encoding(ident); 218221828Sgrehan 219221828Sgrehan if (encoding == (uint32_t)-1) 220221828Sgrehan return (EINVAL); 221221828Sgrehan 222221828Sgrehan val = vmcs_fix_regval(encoding, val); 223221828Sgrehan 224249879Sgrehan if (!running) 225249879Sgrehan VMPTRLD(vmcs); 226249879Sgrehan 227221828Sgrehan error = vmwrite(encoding, val); 228249879Sgrehan 229249879Sgrehan if (!running) 230249879Sgrehan VMCLEAR(vmcs); 231249879Sgrehan 232221828Sgrehan return (error); 233221828Sgrehan} 234221828Sgrehan 235221828Sgrehanint 236221828Sgrehanvmcs_setdesc(struct vmcs *vmcs, int seg, struct seg_desc *desc) 237221828Sgrehan{ 238221828Sgrehan int error; 239221828Sgrehan uint32_t base, limit, access; 240221828Sgrehan 241221828Sgrehan error = vmcs_seg_desc_encoding(seg, &base, &limit, &access); 242221828Sgrehan if (error != 0) 243221828Sgrehan panic("vmcs_setdesc: invalid segment register %d", seg); 244221828Sgrehan 245221828Sgrehan VMPTRLD(vmcs); 246221828Sgrehan if ((error = vmwrite(base, desc->base)) != 0) 247221828Sgrehan goto done; 248221828Sgrehan 249221828Sgrehan if ((error = vmwrite(limit, desc->limit)) != 0) 250221828Sgrehan goto done; 251221828Sgrehan 252221828Sgrehan if (access != VMCS_INVALID_ENCODING) { 253221828Sgrehan if ((error = vmwrite(access, desc->access)) != 0) 254221828Sgrehan goto done; 255221828Sgrehan } 256221828Sgrehandone: 257221828Sgrehan VMCLEAR(vmcs); 258221828Sgrehan return (error); 259221828Sgrehan} 260221828Sgrehan 261221828Sgrehanint 262221828Sgrehanvmcs_getdesc(struct vmcs *vmcs, int seg, struct seg_desc *desc) 263221828Sgrehan{ 264221828Sgrehan int error; 265221828Sgrehan uint32_t base, limit, access; 266221828Sgrehan uint64_t u64; 267221828Sgrehan 268221828Sgrehan error = vmcs_seg_desc_encoding(seg, &base, &limit, &access); 269221828Sgrehan if (error != 0) 270221828Sgrehan panic("vmcs_getdesc: invalid segment register %d", seg); 271221828Sgrehan 272221828Sgrehan VMPTRLD(vmcs); 273221828Sgrehan if ((error = vmread(base, &u64)) != 0) 274221828Sgrehan goto done; 275221828Sgrehan desc->base = u64; 276221828Sgrehan 277221828Sgrehan if ((error = vmread(limit, &u64)) != 0) 278221828Sgrehan goto done; 279221828Sgrehan desc->limit = u64; 280221828Sgrehan 281221828Sgrehan if (access != VMCS_INVALID_ENCODING) { 282221828Sgrehan if ((error = vmread(access, &u64)) != 0) 283221828Sgrehan goto done; 284221828Sgrehan desc->access = u64; 285221828Sgrehan } 286221828Sgrehandone: 287221828Sgrehan VMCLEAR(vmcs); 288221828Sgrehan return (error); 289221828Sgrehan} 290221828Sgrehan 291221828Sgrehanint 292221828Sgrehanvmcs_set_msr_save(struct vmcs *vmcs, u_long g_area, u_int g_count) 293221828Sgrehan{ 294221828Sgrehan int error; 295221828Sgrehan 296221828Sgrehan VMPTRLD(vmcs); 297221828Sgrehan 298221828Sgrehan /* 299221828Sgrehan * Guest MSRs are saved in the VM-exit MSR-store area. 300221828Sgrehan * Guest MSRs are loaded from the VM-entry MSR-load area. 301221828Sgrehan * Both areas point to the same location in memory. 302221828Sgrehan */ 303221828Sgrehan if ((error = vmwrite(VMCS_EXIT_MSR_STORE, g_area)) != 0) 304221828Sgrehan goto done; 305221828Sgrehan if ((error = vmwrite(VMCS_EXIT_MSR_STORE_COUNT, g_count)) != 0) 306221828Sgrehan goto done; 307221828Sgrehan 308221828Sgrehan if ((error = vmwrite(VMCS_ENTRY_MSR_LOAD, g_area)) != 0) 309221828Sgrehan goto done; 310221828Sgrehan if ((error = vmwrite(VMCS_ENTRY_MSR_LOAD_COUNT, g_count)) != 0) 311221828Sgrehan goto done; 312221828Sgrehan 313221828Sgrehan error = 0; 314221828Sgrehandone: 315221828Sgrehan VMCLEAR(vmcs); 316221828Sgrehan return (error); 317221828Sgrehan} 318221828Sgrehan 319221828Sgrehanint 320221828Sgrehanvmcs_set_defaults(struct vmcs *vmcs, 321256072Sneel u_long host_rip, u_long host_rsp, uint64_t eptp, 322221828Sgrehan uint32_t pinbased_ctls, uint32_t procbased_ctls, 323221828Sgrehan uint32_t procbased_ctls2, uint32_t exit_ctls, 324221828Sgrehan uint32_t entry_ctls, u_long msr_bitmap, uint16_t vpid) 325221828Sgrehan{ 326221828Sgrehan int error, codesel, datasel, tsssel; 327221828Sgrehan u_long cr0, cr4, efer; 328256072Sneel uint64_t pat, fsbase, idtrbase; 329221828Sgrehan uint32_t exc_bitmap; 330221828Sgrehan 331242275Sneel codesel = vmm_get_host_codesel(); 332242275Sneel datasel = vmm_get_host_datasel(); 333242275Sneel tsssel = vmm_get_host_tsssel(); 334221828Sgrehan 335221828Sgrehan /* 336221828Sgrehan * Make sure we have a "current" VMCS to work with. 337221828Sgrehan */ 338221828Sgrehan VMPTRLD(vmcs); 339221828Sgrehan 340221828Sgrehan /* 341221828Sgrehan * Load the VMX controls 342221828Sgrehan */ 343221828Sgrehan if ((error = vmwrite(VMCS_PIN_BASED_CTLS, pinbased_ctls)) != 0) 344221828Sgrehan goto done; 345221828Sgrehan if ((error = vmwrite(VMCS_PRI_PROC_BASED_CTLS, procbased_ctls)) != 0) 346221828Sgrehan goto done; 347221828Sgrehan if ((error = vmwrite(VMCS_SEC_PROC_BASED_CTLS, procbased_ctls2)) != 0) 348221828Sgrehan goto done; 349221828Sgrehan if ((error = vmwrite(VMCS_EXIT_CTLS, exit_ctls)) != 0) 350221828Sgrehan goto done; 351221828Sgrehan if ((error = vmwrite(VMCS_ENTRY_CTLS, entry_ctls)) != 0) 352221828Sgrehan goto done; 353221828Sgrehan 354221828Sgrehan /* Guest state */ 355221828Sgrehan 356221828Sgrehan /* Initialize guest IA32_PAT MSR with the default value */ 357221828Sgrehan pat = PAT_VALUE(0, PAT_WRITE_BACK) | 358221828Sgrehan PAT_VALUE(1, PAT_WRITE_THROUGH) | 359221828Sgrehan PAT_VALUE(2, PAT_UNCACHED) | 360221828Sgrehan PAT_VALUE(3, PAT_UNCACHEABLE) | 361221828Sgrehan PAT_VALUE(4, PAT_WRITE_BACK) | 362221828Sgrehan PAT_VALUE(5, PAT_WRITE_THROUGH) | 363221828Sgrehan PAT_VALUE(6, PAT_UNCACHED) | 364221828Sgrehan PAT_VALUE(7, PAT_UNCACHEABLE); 365221828Sgrehan if ((error = vmwrite(VMCS_GUEST_IA32_PAT, pat)) != 0) 366221828Sgrehan goto done; 367221828Sgrehan 368221828Sgrehan /* Host state */ 369221828Sgrehan 370221828Sgrehan /* Initialize host IA32_PAT MSR */ 371242275Sneel pat = vmm_get_host_pat(); 372221828Sgrehan if ((error = vmwrite(VMCS_HOST_IA32_PAT, pat)) != 0) 373221828Sgrehan goto done; 374221828Sgrehan 375221828Sgrehan /* Load the IA32_EFER MSR */ 376242275Sneel efer = vmm_get_host_efer(); 377221828Sgrehan if ((error = vmwrite(VMCS_HOST_IA32_EFER, efer)) != 0) 378221828Sgrehan goto done; 379221828Sgrehan 380221828Sgrehan /* Load the control registers */ 381242122Sneel 382242275Sneel cr0 = vmm_get_host_cr0(); 383221828Sgrehan if ((error = vmwrite(VMCS_HOST_CR0, cr0)) != 0) 384221828Sgrehan goto done; 385221828Sgrehan 386242275Sneel cr4 = vmm_get_host_cr4() | CR4_VMXE; 387221828Sgrehan if ((error = vmwrite(VMCS_HOST_CR4, cr4)) != 0) 388221828Sgrehan goto done; 389221828Sgrehan 390221828Sgrehan /* Load the segment selectors */ 391221828Sgrehan if ((error = vmwrite(VMCS_HOST_ES_SELECTOR, datasel)) != 0) 392221828Sgrehan goto done; 393221828Sgrehan 394221828Sgrehan if ((error = vmwrite(VMCS_HOST_CS_SELECTOR, codesel)) != 0) 395221828Sgrehan goto done; 396221828Sgrehan 397221828Sgrehan if ((error = vmwrite(VMCS_HOST_SS_SELECTOR, datasel)) != 0) 398221828Sgrehan goto done; 399221828Sgrehan 400221828Sgrehan if ((error = vmwrite(VMCS_HOST_DS_SELECTOR, datasel)) != 0) 401221828Sgrehan goto done; 402221828Sgrehan 403221828Sgrehan if ((error = vmwrite(VMCS_HOST_FS_SELECTOR, datasel)) != 0) 404221828Sgrehan goto done; 405221828Sgrehan 406221828Sgrehan if ((error = vmwrite(VMCS_HOST_GS_SELECTOR, datasel)) != 0) 407221828Sgrehan goto done; 408221828Sgrehan 409221828Sgrehan if ((error = vmwrite(VMCS_HOST_TR_SELECTOR, tsssel)) != 0) 410221828Sgrehan goto done; 411221828Sgrehan 412221828Sgrehan /* 413221828Sgrehan * Load the Base-Address for %fs and idtr. 414221828Sgrehan * 415221828Sgrehan * Note that we exclude %gs, tss and gdtr here because their base 416221828Sgrehan * address is pcpu specific. 417221828Sgrehan */ 418242275Sneel fsbase = vmm_get_host_fsbase(); 419242275Sneel if ((error = vmwrite(VMCS_HOST_FS_BASE, fsbase)) != 0) 420221828Sgrehan goto done; 421221828Sgrehan 422242275Sneel idtrbase = vmm_get_host_idtrbase(); 423242275Sneel if ((error = vmwrite(VMCS_HOST_IDTR_BASE, idtrbase)) != 0) 424221828Sgrehan goto done; 425221828Sgrehan 426221828Sgrehan /* instruction pointer */ 427221828Sgrehan if ((error = vmwrite(VMCS_HOST_RIP, host_rip)) != 0) 428221828Sgrehan goto done; 429221828Sgrehan 430221828Sgrehan /* stack pointer */ 431221828Sgrehan if ((error = vmwrite(VMCS_HOST_RSP, host_rsp)) != 0) 432221828Sgrehan goto done; 433221828Sgrehan 434221828Sgrehan /* eptp */ 435221828Sgrehan if ((error = vmwrite(VMCS_EPTP, eptp)) != 0) 436221828Sgrehan goto done; 437221828Sgrehan 438221828Sgrehan /* vpid */ 439221828Sgrehan if ((error = vmwrite(VMCS_VPID, vpid)) != 0) 440221828Sgrehan goto done; 441221828Sgrehan 442221828Sgrehan /* msr bitmap */ 443221828Sgrehan if ((error = vmwrite(VMCS_MSR_BITMAP, msr_bitmap)) != 0) 444221828Sgrehan goto done; 445221828Sgrehan 446221828Sgrehan /* exception bitmap */ 447221828Sgrehan exc_bitmap = 1 << IDT_MC; 448221828Sgrehan if ((error = vmwrite(VMCS_EXCEPTION_BITMAP, exc_bitmap)) != 0) 449221828Sgrehan goto done; 450221828Sgrehan 451221828Sgrehan /* link pointer */ 452221828Sgrehan if ((error = vmwrite(VMCS_LINK_POINTER, ~0)) != 0) 453221828Sgrehan goto done; 454221828Sgrehandone: 455221828Sgrehan VMCLEAR(vmcs); 456221828Sgrehan return (error); 457221828Sgrehan} 458221828Sgrehan 459221828Sgrehanuint64_t 460221828Sgrehanvmcs_read(uint32_t encoding) 461221828Sgrehan{ 462221828Sgrehan int error; 463221828Sgrehan uint64_t val; 464221828Sgrehan 465221828Sgrehan error = vmread(encoding, &val); 466221828Sgrehan if (error != 0) 467221828Sgrehan panic("vmcs_read(%u) error %d", encoding, error); 468221828Sgrehan 469221828Sgrehan return (val); 470221828Sgrehan} 471222605Sjhb 472222605Sjhb#ifdef DDB 473222605Sjhbextern int vmxon_enabled[]; 474222605Sjhb 475222605SjhbDB_SHOW_COMMAND(vmcs, db_show_vmcs) 476222605Sjhb{ 477222605Sjhb uint64_t cur_vmcs, val; 478222605Sjhb uint32_t exit; 479222605Sjhb 480222605Sjhb if (!vmxon_enabled[curcpu]) { 481222605Sjhb db_printf("VMX not enabled\n"); 482222605Sjhb return; 483222605Sjhb } 484222605Sjhb 485222605Sjhb if (have_addr) { 486222605Sjhb db_printf("Only current VMCS supported\n"); 487222605Sjhb return; 488222605Sjhb } 489222605Sjhb 490222605Sjhb vmptrst(&cur_vmcs); 491222605Sjhb if (cur_vmcs == VMCS_INITIAL) { 492222605Sjhb db_printf("No current VM context\n"); 493222605Sjhb return; 494222605Sjhb } 495222605Sjhb db_printf("VMCS: %jx\n", cur_vmcs); 496222605Sjhb db_printf("VPID: %lu\n", vmcs_read(VMCS_VPID)); 497222605Sjhb db_printf("Activity: "); 498222605Sjhb val = vmcs_read(VMCS_GUEST_ACTIVITY); 499222605Sjhb switch (val) { 500222605Sjhb case 0: 501222605Sjhb db_printf("Active"); 502222605Sjhb break; 503222605Sjhb case 1: 504222605Sjhb db_printf("HLT"); 505222605Sjhb break; 506222605Sjhb case 2: 507222605Sjhb db_printf("Shutdown"); 508222605Sjhb break; 509222605Sjhb case 3: 510222605Sjhb db_printf("Wait for SIPI"); 511222605Sjhb break; 512222605Sjhb default: 513222605Sjhb db_printf("Unknown: %#lx", val); 514222605Sjhb } 515222605Sjhb db_printf("\n"); 516222605Sjhb exit = vmcs_read(VMCS_EXIT_REASON); 517222605Sjhb if (exit & 0x80000000) 518222605Sjhb db_printf("Entry Failure Reason: %u\n", exit & 0xffff); 519222605Sjhb else 520222605Sjhb db_printf("Exit Reason: %u\n", exit & 0xffff); 521222605Sjhb db_printf("Qualification: %#lx\n", vmcs_exit_qualification()); 522222605Sjhb db_printf("Guest Linear Address: %#lx\n", 523222605Sjhb vmcs_read(VMCS_GUEST_LINEAR_ADDRESS)); 524222605Sjhb switch (exit & 0x8000ffff) { 525222605Sjhb case EXIT_REASON_EXCEPTION: 526222605Sjhb case EXIT_REASON_EXT_INTR: 527222605Sjhb val = vmcs_read(VMCS_EXIT_INTERRUPTION_INFO); 528222605Sjhb db_printf("Interrupt Type: "); 529222605Sjhb switch (val >> 8 & 0x7) { 530222605Sjhb case 0: 531222605Sjhb db_printf("external"); 532222605Sjhb break; 533222605Sjhb case 2: 534222605Sjhb db_printf("NMI"); 535222605Sjhb break; 536222605Sjhb case 3: 537222605Sjhb db_printf("HW exception"); 538222605Sjhb break; 539222605Sjhb case 4: 540222605Sjhb db_printf("SW exception"); 541222605Sjhb break; 542222605Sjhb default: 543222605Sjhb db_printf("?? %lu", val >> 8 & 0x7); 544222605Sjhb break; 545222605Sjhb } 546222605Sjhb db_printf(" Vector: %lu", val & 0xff); 547222605Sjhb if (val & 0x800) 548222605Sjhb db_printf(" Error Code: %lx", 549222605Sjhb vmcs_read(VMCS_EXIT_INTERRUPTION_ERROR)); 550222605Sjhb db_printf("\n"); 551222605Sjhb break; 552222605Sjhb case EXIT_REASON_EPT_FAULT: 553222605Sjhb case EXIT_REASON_EPT_MISCONFIG: 554222605Sjhb db_printf("Guest Physical Address: %#lx\n", 555222605Sjhb vmcs_read(VMCS_GUEST_PHYSICAL_ADDRESS)); 556222605Sjhb break; 557222605Sjhb } 558222605Sjhb db_printf("VM-instruction error: %#lx\n", vmcs_instruction_error()); 559222605Sjhb} 560222605Sjhb#endif 561