vmcs.c revision 268777
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 268777 2014-07-16 21:26:26Z neel $ 27221828Sgrehan */ 28221828Sgrehan 29222605Sjhb#include "opt_ddb.h" 30222605Sjhb 31221828Sgrehan#include <sys/cdefs.h> 32221828Sgrehan__FBSDID("$FreeBSD: head/sys/amd64/vmm/intel/vmcs.c 268777 2014-07-16 21:26:26Z 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/vmm.h> 43242275Sneel#include "vmm_host.h" 44259542Sneel#include "vmx_cpufunc.h" 45221828Sgrehan#include "vmcs.h" 46221828Sgrehan#include "ept.h" 47221828Sgrehan#include "vmx.h" 48221828Sgrehan 49222605Sjhb#ifdef DDB 50222605Sjhb#include <ddb/ddb.h> 51222605Sjhb#endif 52222605Sjhb 53221828Sgrehanstatic uint64_t 54221828Sgrehanvmcs_fix_regval(uint32_t encoding, uint64_t val) 55221828Sgrehan{ 56221828Sgrehan 57221828Sgrehan switch (encoding) { 58221828Sgrehan case VMCS_GUEST_CR0: 59221828Sgrehan val = vmx_fix_cr0(val); 60221828Sgrehan break; 61221828Sgrehan case VMCS_GUEST_CR4: 62221828Sgrehan val = vmx_fix_cr4(val); 63221828Sgrehan break; 64221828Sgrehan default: 65221828Sgrehan break; 66221828Sgrehan } 67221828Sgrehan return (val); 68221828Sgrehan} 69221828Sgrehan 70221828Sgrehanstatic uint32_t 71221828Sgrehanvmcs_field_encoding(int ident) 72221828Sgrehan{ 73221828Sgrehan switch (ident) { 74221828Sgrehan case VM_REG_GUEST_CR0: 75221828Sgrehan return (VMCS_GUEST_CR0); 76221828Sgrehan case VM_REG_GUEST_CR3: 77221828Sgrehan return (VMCS_GUEST_CR3); 78221828Sgrehan case VM_REG_GUEST_CR4: 79221828Sgrehan return (VMCS_GUEST_CR4); 80221828Sgrehan case VM_REG_GUEST_DR7: 81221828Sgrehan return (VMCS_GUEST_DR7); 82221828Sgrehan case VM_REG_GUEST_RSP: 83221828Sgrehan return (VMCS_GUEST_RSP); 84221828Sgrehan case VM_REG_GUEST_RIP: 85221828Sgrehan return (VMCS_GUEST_RIP); 86221828Sgrehan case VM_REG_GUEST_RFLAGS: 87221828Sgrehan return (VMCS_GUEST_RFLAGS); 88221828Sgrehan case VM_REG_GUEST_ES: 89221828Sgrehan return (VMCS_GUEST_ES_SELECTOR); 90221828Sgrehan case VM_REG_GUEST_CS: 91221828Sgrehan return (VMCS_GUEST_CS_SELECTOR); 92221828Sgrehan case VM_REG_GUEST_SS: 93221828Sgrehan return (VMCS_GUEST_SS_SELECTOR); 94221828Sgrehan case VM_REG_GUEST_DS: 95221828Sgrehan return (VMCS_GUEST_DS_SELECTOR); 96221828Sgrehan case VM_REG_GUEST_FS: 97221828Sgrehan return (VMCS_GUEST_FS_SELECTOR); 98221828Sgrehan case VM_REG_GUEST_GS: 99221828Sgrehan return (VMCS_GUEST_GS_SELECTOR); 100221828Sgrehan case VM_REG_GUEST_TR: 101221828Sgrehan return (VMCS_GUEST_TR_SELECTOR); 102221828Sgrehan case VM_REG_GUEST_LDTR: 103221828Sgrehan return (VMCS_GUEST_LDTR_SELECTOR); 104221828Sgrehan case VM_REG_GUEST_EFER: 105221828Sgrehan return (VMCS_GUEST_IA32_EFER); 106268777Sneel case VM_REG_GUEST_PDPTE0: 107268777Sneel return (VMCS_GUEST_PDPTE0); 108268777Sneel case VM_REG_GUEST_PDPTE1: 109268777Sneel return (VMCS_GUEST_PDPTE1); 110268777Sneel case VM_REG_GUEST_PDPTE2: 111268777Sneel return (VMCS_GUEST_PDPTE2); 112268777Sneel case VM_REG_GUEST_PDPTE3: 113268777Sneel return (VMCS_GUEST_PDPTE3); 114221828Sgrehan default: 115221828Sgrehan return (-1); 116221828Sgrehan } 117221828Sgrehan 118221828Sgrehan} 119221828Sgrehan 120221828Sgrehanstatic int 121221828Sgrehanvmcs_seg_desc_encoding(int seg, uint32_t *base, uint32_t *lim, uint32_t *acc) 122221828Sgrehan{ 123221828Sgrehan 124221828Sgrehan switch (seg) { 125221828Sgrehan case VM_REG_GUEST_ES: 126221828Sgrehan *base = VMCS_GUEST_ES_BASE; 127221828Sgrehan *lim = VMCS_GUEST_ES_LIMIT; 128221828Sgrehan *acc = VMCS_GUEST_ES_ACCESS_RIGHTS; 129221828Sgrehan break; 130221828Sgrehan case VM_REG_GUEST_CS: 131221828Sgrehan *base = VMCS_GUEST_CS_BASE; 132221828Sgrehan *lim = VMCS_GUEST_CS_LIMIT; 133221828Sgrehan *acc = VMCS_GUEST_CS_ACCESS_RIGHTS; 134221828Sgrehan break; 135221828Sgrehan case VM_REG_GUEST_SS: 136221828Sgrehan *base = VMCS_GUEST_SS_BASE; 137221828Sgrehan *lim = VMCS_GUEST_SS_LIMIT; 138221828Sgrehan *acc = VMCS_GUEST_SS_ACCESS_RIGHTS; 139221828Sgrehan break; 140221828Sgrehan case VM_REG_GUEST_DS: 141221828Sgrehan *base = VMCS_GUEST_DS_BASE; 142221828Sgrehan *lim = VMCS_GUEST_DS_LIMIT; 143221828Sgrehan *acc = VMCS_GUEST_DS_ACCESS_RIGHTS; 144221828Sgrehan break; 145221828Sgrehan case VM_REG_GUEST_FS: 146221828Sgrehan *base = VMCS_GUEST_FS_BASE; 147221828Sgrehan *lim = VMCS_GUEST_FS_LIMIT; 148221828Sgrehan *acc = VMCS_GUEST_FS_ACCESS_RIGHTS; 149221828Sgrehan break; 150221828Sgrehan case VM_REG_GUEST_GS: 151221828Sgrehan *base = VMCS_GUEST_GS_BASE; 152221828Sgrehan *lim = VMCS_GUEST_GS_LIMIT; 153221828Sgrehan *acc = VMCS_GUEST_GS_ACCESS_RIGHTS; 154221828Sgrehan break; 155221828Sgrehan case VM_REG_GUEST_TR: 156221828Sgrehan *base = VMCS_GUEST_TR_BASE; 157221828Sgrehan *lim = VMCS_GUEST_TR_LIMIT; 158221828Sgrehan *acc = VMCS_GUEST_TR_ACCESS_RIGHTS; 159221828Sgrehan break; 160221828Sgrehan case VM_REG_GUEST_LDTR: 161221828Sgrehan *base = VMCS_GUEST_LDTR_BASE; 162221828Sgrehan *lim = VMCS_GUEST_LDTR_LIMIT; 163221828Sgrehan *acc = VMCS_GUEST_LDTR_ACCESS_RIGHTS; 164221828Sgrehan break; 165221828Sgrehan case VM_REG_GUEST_IDTR: 166221828Sgrehan *base = VMCS_GUEST_IDTR_BASE; 167221828Sgrehan *lim = VMCS_GUEST_IDTR_LIMIT; 168221828Sgrehan *acc = VMCS_INVALID_ENCODING; 169221828Sgrehan break; 170221828Sgrehan case VM_REG_GUEST_GDTR: 171221828Sgrehan *base = VMCS_GUEST_GDTR_BASE; 172221828Sgrehan *lim = VMCS_GUEST_GDTR_LIMIT; 173221828Sgrehan *acc = VMCS_INVALID_ENCODING; 174221828Sgrehan break; 175221828Sgrehan default: 176221828Sgrehan return (EINVAL); 177221828Sgrehan } 178221828Sgrehan 179221828Sgrehan return (0); 180221828Sgrehan} 181221828Sgrehan 182221828Sgrehanint 183249879Sgrehanvmcs_getreg(struct vmcs *vmcs, int running, int ident, uint64_t *retval) 184221828Sgrehan{ 185221828Sgrehan int error; 186221828Sgrehan uint32_t encoding; 187221828Sgrehan 188221828Sgrehan /* 189221828Sgrehan * If we need to get at vmx-specific state in the VMCS we can bypass 190221828Sgrehan * the translation of 'ident' to 'encoding' by simply setting the 191221828Sgrehan * sign bit. As it so happens the upper 16 bits are reserved (i.e 192221828Sgrehan * set to 0) in the encodings for the VMCS so we are free to use the 193221828Sgrehan * sign bit. 194221828Sgrehan */ 195221828Sgrehan if (ident < 0) 196221828Sgrehan encoding = ident & 0x7fffffff; 197221828Sgrehan else 198221828Sgrehan encoding = vmcs_field_encoding(ident); 199221828Sgrehan 200221828Sgrehan if (encoding == (uint32_t)-1) 201221828Sgrehan return (EINVAL); 202221828Sgrehan 203249879Sgrehan if (!running) 204249879Sgrehan VMPTRLD(vmcs); 205249879Sgrehan 206221828Sgrehan error = vmread(encoding, retval); 207249879Sgrehan 208249879Sgrehan if (!running) 209249879Sgrehan VMCLEAR(vmcs); 210249879Sgrehan 211221828Sgrehan return (error); 212221828Sgrehan} 213221828Sgrehan 214221828Sgrehanint 215249879Sgrehanvmcs_setreg(struct vmcs *vmcs, int running, int ident, uint64_t val) 216221828Sgrehan{ 217221828Sgrehan int error; 218221828Sgrehan uint32_t encoding; 219221828Sgrehan 220221828Sgrehan if (ident < 0) 221221828Sgrehan encoding = ident & 0x7fffffff; 222221828Sgrehan else 223221828Sgrehan encoding = vmcs_field_encoding(ident); 224221828Sgrehan 225221828Sgrehan if (encoding == (uint32_t)-1) 226221828Sgrehan return (EINVAL); 227221828Sgrehan 228221828Sgrehan val = vmcs_fix_regval(encoding, val); 229221828Sgrehan 230249879Sgrehan if (!running) 231249879Sgrehan VMPTRLD(vmcs); 232249879Sgrehan 233221828Sgrehan error = vmwrite(encoding, val); 234249879Sgrehan 235249879Sgrehan if (!running) 236249879Sgrehan VMCLEAR(vmcs); 237249879Sgrehan 238221828Sgrehan return (error); 239221828Sgrehan} 240221828Sgrehan 241221828Sgrehanint 242266550Sneelvmcs_setdesc(struct vmcs *vmcs, int running, int seg, struct seg_desc *desc) 243221828Sgrehan{ 244221828Sgrehan int error; 245221828Sgrehan uint32_t base, limit, access; 246221828Sgrehan 247221828Sgrehan error = vmcs_seg_desc_encoding(seg, &base, &limit, &access); 248221828Sgrehan if (error != 0) 249221828Sgrehan panic("vmcs_setdesc: invalid segment register %d", seg); 250221828Sgrehan 251266550Sneel if (!running) 252266550Sneel VMPTRLD(vmcs); 253221828Sgrehan if ((error = vmwrite(base, desc->base)) != 0) 254221828Sgrehan goto done; 255221828Sgrehan 256221828Sgrehan if ((error = vmwrite(limit, desc->limit)) != 0) 257221828Sgrehan goto done; 258221828Sgrehan 259221828Sgrehan if (access != VMCS_INVALID_ENCODING) { 260221828Sgrehan if ((error = vmwrite(access, desc->access)) != 0) 261221828Sgrehan goto done; 262221828Sgrehan } 263221828Sgrehandone: 264266550Sneel if (!running) 265266550Sneel VMCLEAR(vmcs); 266221828Sgrehan return (error); 267221828Sgrehan} 268221828Sgrehan 269221828Sgrehanint 270266550Sneelvmcs_getdesc(struct vmcs *vmcs, int running, int seg, struct seg_desc *desc) 271221828Sgrehan{ 272221828Sgrehan int error; 273221828Sgrehan uint32_t base, limit, access; 274221828Sgrehan uint64_t u64; 275221828Sgrehan 276221828Sgrehan error = vmcs_seg_desc_encoding(seg, &base, &limit, &access); 277221828Sgrehan if (error != 0) 278221828Sgrehan panic("vmcs_getdesc: invalid segment register %d", seg); 279221828Sgrehan 280266550Sneel if (!running) 281266550Sneel VMPTRLD(vmcs); 282221828Sgrehan if ((error = vmread(base, &u64)) != 0) 283221828Sgrehan goto done; 284221828Sgrehan desc->base = u64; 285221828Sgrehan 286221828Sgrehan if ((error = vmread(limit, &u64)) != 0) 287221828Sgrehan goto done; 288221828Sgrehan desc->limit = u64; 289221828Sgrehan 290221828Sgrehan if (access != VMCS_INVALID_ENCODING) { 291221828Sgrehan if ((error = vmread(access, &u64)) != 0) 292221828Sgrehan goto done; 293221828Sgrehan desc->access = u64; 294221828Sgrehan } 295221828Sgrehandone: 296266550Sneel if (!running) 297266550Sneel VMCLEAR(vmcs); 298221828Sgrehan return (error); 299221828Sgrehan} 300221828Sgrehan 301221828Sgrehanint 302221828Sgrehanvmcs_set_msr_save(struct vmcs *vmcs, u_long g_area, u_int g_count) 303221828Sgrehan{ 304221828Sgrehan int error; 305221828Sgrehan 306221828Sgrehan VMPTRLD(vmcs); 307221828Sgrehan 308221828Sgrehan /* 309221828Sgrehan * Guest MSRs are saved in the VM-exit MSR-store area. 310221828Sgrehan * Guest MSRs are loaded from the VM-entry MSR-load area. 311221828Sgrehan * Both areas point to the same location in memory. 312221828Sgrehan */ 313221828Sgrehan if ((error = vmwrite(VMCS_EXIT_MSR_STORE, g_area)) != 0) 314221828Sgrehan goto done; 315221828Sgrehan if ((error = vmwrite(VMCS_EXIT_MSR_STORE_COUNT, g_count)) != 0) 316221828Sgrehan goto done; 317221828Sgrehan 318221828Sgrehan if ((error = vmwrite(VMCS_ENTRY_MSR_LOAD, g_area)) != 0) 319221828Sgrehan goto done; 320221828Sgrehan if ((error = vmwrite(VMCS_ENTRY_MSR_LOAD_COUNT, g_count)) != 0) 321221828Sgrehan goto done; 322221828Sgrehan 323221828Sgrehan error = 0; 324221828Sgrehandone: 325221828Sgrehan VMCLEAR(vmcs); 326221828Sgrehan return (error); 327221828Sgrehan} 328221828Sgrehan 329221828Sgrehanint 330260380Sneelvmcs_init(struct vmcs *vmcs) 331221828Sgrehan{ 332221828Sgrehan int error, codesel, datasel, tsssel; 333221828Sgrehan u_long cr0, cr4, efer; 334256072Sneel uint64_t pat, fsbase, idtrbase; 335221828Sgrehan uint32_t exc_bitmap; 336221828Sgrehan 337242275Sneel codesel = vmm_get_host_codesel(); 338242275Sneel datasel = vmm_get_host_datasel(); 339242275Sneel tsssel = vmm_get_host_tsssel(); 340221828Sgrehan 341221828Sgrehan /* 342221828Sgrehan * Make sure we have a "current" VMCS to work with. 343221828Sgrehan */ 344221828Sgrehan VMPTRLD(vmcs); 345221828Sgrehan 346221828Sgrehan /* Initialize guest IA32_PAT MSR with the default value */ 347221828Sgrehan pat = PAT_VALUE(0, PAT_WRITE_BACK) | 348221828Sgrehan PAT_VALUE(1, PAT_WRITE_THROUGH) | 349221828Sgrehan PAT_VALUE(2, PAT_UNCACHED) | 350221828Sgrehan PAT_VALUE(3, PAT_UNCACHEABLE) | 351221828Sgrehan PAT_VALUE(4, PAT_WRITE_BACK) | 352221828Sgrehan PAT_VALUE(5, PAT_WRITE_THROUGH) | 353221828Sgrehan PAT_VALUE(6, PAT_UNCACHED) | 354221828Sgrehan PAT_VALUE(7, PAT_UNCACHEABLE); 355221828Sgrehan if ((error = vmwrite(VMCS_GUEST_IA32_PAT, pat)) != 0) 356221828Sgrehan goto done; 357221828Sgrehan 358221828Sgrehan /* Host state */ 359221828Sgrehan 360221828Sgrehan /* Initialize host IA32_PAT MSR */ 361242275Sneel pat = vmm_get_host_pat(); 362221828Sgrehan if ((error = vmwrite(VMCS_HOST_IA32_PAT, pat)) != 0) 363221828Sgrehan goto done; 364221828Sgrehan 365221828Sgrehan /* Load the IA32_EFER MSR */ 366242275Sneel efer = vmm_get_host_efer(); 367221828Sgrehan if ((error = vmwrite(VMCS_HOST_IA32_EFER, efer)) != 0) 368221828Sgrehan goto done; 369221828Sgrehan 370221828Sgrehan /* Load the control registers */ 371242122Sneel 372242275Sneel cr0 = vmm_get_host_cr0(); 373221828Sgrehan if ((error = vmwrite(VMCS_HOST_CR0, cr0)) != 0) 374221828Sgrehan goto done; 375221828Sgrehan 376242275Sneel cr4 = vmm_get_host_cr4() | CR4_VMXE; 377221828Sgrehan if ((error = vmwrite(VMCS_HOST_CR4, cr4)) != 0) 378221828Sgrehan goto done; 379221828Sgrehan 380221828Sgrehan /* Load the segment selectors */ 381221828Sgrehan if ((error = vmwrite(VMCS_HOST_ES_SELECTOR, datasel)) != 0) 382221828Sgrehan goto done; 383221828Sgrehan 384221828Sgrehan if ((error = vmwrite(VMCS_HOST_CS_SELECTOR, codesel)) != 0) 385221828Sgrehan goto done; 386221828Sgrehan 387221828Sgrehan if ((error = vmwrite(VMCS_HOST_SS_SELECTOR, datasel)) != 0) 388221828Sgrehan goto done; 389221828Sgrehan 390221828Sgrehan if ((error = vmwrite(VMCS_HOST_DS_SELECTOR, datasel)) != 0) 391221828Sgrehan goto done; 392221828Sgrehan 393221828Sgrehan if ((error = vmwrite(VMCS_HOST_FS_SELECTOR, datasel)) != 0) 394221828Sgrehan goto done; 395221828Sgrehan 396221828Sgrehan if ((error = vmwrite(VMCS_HOST_GS_SELECTOR, datasel)) != 0) 397221828Sgrehan goto done; 398221828Sgrehan 399221828Sgrehan if ((error = vmwrite(VMCS_HOST_TR_SELECTOR, tsssel)) != 0) 400221828Sgrehan goto done; 401221828Sgrehan 402221828Sgrehan /* 403221828Sgrehan * Load the Base-Address for %fs and idtr. 404221828Sgrehan * 405221828Sgrehan * Note that we exclude %gs, tss and gdtr here because their base 406221828Sgrehan * address is pcpu specific. 407221828Sgrehan */ 408242275Sneel fsbase = vmm_get_host_fsbase(); 409242275Sneel if ((error = vmwrite(VMCS_HOST_FS_BASE, fsbase)) != 0) 410221828Sgrehan goto done; 411221828Sgrehan 412242275Sneel idtrbase = vmm_get_host_idtrbase(); 413242275Sneel if ((error = vmwrite(VMCS_HOST_IDTR_BASE, idtrbase)) != 0) 414221828Sgrehan goto done; 415221828Sgrehan 416221828Sgrehan /* instruction pointer */ 417260380Sneel if ((error = vmwrite(VMCS_HOST_RIP, (u_long)vmx_exit_guest)) != 0) 418221828Sgrehan goto done; 419221828Sgrehan 420221828Sgrehan /* exception bitmap */ 421221828Sgrehan exc_bitmap = 1 << IDT_MC; 422221828Sgrehan if ((error = vmwrite(VMCS_EXCEPTION_BITMAP, exc_bitmap)) != 0) 423221828Sgrehan goto done; 424221828Sgrehan 425221828Sgrehan /* link pointer */ 426221828Sgrehan if ((error = vmwrite(VMCS_LINK_POINTER, ~0)) != 0) 427221828Sgrehan goto done; 428221828Sgrehandone: 429221828Sgrehan VMCLEAR(vmcs); 430221828Sgrehan return (error); 431221828Sgrehan} 432221828Sgrehan 433222605Sjhb#ifdef DDB 434222605Sjhbextern int vmxon_enabled[]; 435222605Sjhb 436222605SjhbDB_SHOW_COMMAND(vmcs, db_show_vmcs) 437222605Sjhb{ 438222605Sjhb uint64_t cur_vmcs, val; 439222605Sjhb uint32_t exit; 440222605Sjhb 441222605Sjhb if (!vmxon_enabled[curcpu]) { 442222605Sjhb db_printf("VMX not enabled\n"); 443222605Sjhb return; 444222605Sjhb } 445222605Sjhb 446222605Sjhb if (have_addr) { 447222605Sjhb db_printf("Only current VMCS supported\n"); 448222605Sjhb return; 449222605Sjhb } 450222605Sjhb 451222605Sjhb vmptrst(&cur_vmcs); 452222605Sjhb if (cur_vmcs == VMCS_INITIAL) { 453222605Sjhb db_printf("No current VM context\n"); 454222605Sjhb return; 455222605Sjhb } 456222605Sjhb db_printf("VMCS: %jx\n", cur_vmcs); 457222605Sjhb db_printf("VPID: %lu\n", vmcs_read(VMCS_VPID)); 458222605Sjhb db_printf("Activity: "); 459222605Sjhb val = vmcs_read(VMCS_GUEST_ACTIVITY); 460222605Sjhb switch (val) { 461222605Sjhb case 0: 462222605Sjhb db_printf("Active"); 463222605Sjhb break; 464222605Sjhb case 1: 465222605Sjhb db_printf("HLT"); 466222605Sjhb break; 467222605Sjhb case 2: 468222605Sjhb db_printf("Shutdown"); 469222605Sjhb break; 470222605Sjhb case 3: 471222605Sjhb db_printf("Wait for SIPI"); 472222605Sjhb break; 473222605Sjhb default: 474222605Sjhb db_printf("Unknown: %#lx", val); 475222605Sjhb } 476222605Sjhb db_printf("\n"); 477222605Sjhb exit = vmcs_read(VMCS_EXIT_REASON); 478222605Sjhb if (exit & 0x80000000) 479222605Sjhb db_printf("Entry Failure Reason: %u\n", exit & 0xffff); 480222605Sjhb else 481222605Sjhb db_printf("Exit Reason: %u\n", exit & 0xffff); 482222605Sjhb db_printf("Qualification: %#lx\n", vmcs_exit_qualification()); 483222605Sjhb db_printf("Guest Linear Address: %#lx\n", 484222605Sjhb vmcs_read(VMCS_GUEST_LINEAR_ADDRESS)); 485222605Sjhb switch (exit & 0x8000ffff) { 486222605Sjhb case EXIT_REASON_EXCEPTION: 487222605Sjhb case EXIT_REASON_EXT_INTR: 488260531Sneel val = vmcs_read(VMCS_EXIT_INTR_INFO); 489222605Sjhb db_printf("Interrupt Type: "); 490222605Sjhb switch (val >> 8 & 0x7) { 491222605Sjhb case 0: 492222605Sjhb db_printf("external"); 493222605Sjhb break; 494222605Sjhb case 2: 495222605Sjhb db_printf("NMI"); 496222605Sjhb break; 497222605Sjhb case 3: 498222605Sjhb db_printf("HW exception"); 499222605Sjhb break; 500222605Sjhb case 4: 501222605Sjhb db_printf("SW exception"); 502222605Sjhb break; 503222605Sjhb default: 504222605Sjhb db_printf("?? %lu", val >> 8 & 0x7); 505222605Sjhb break; 506222605Sjhb } 507222605Sjhb db_printf(" Vector: %lu", val & 0xff); 508222605Sjhb if (val & 0x800) 509222605Sjhb db_printf(" Error Code: %lx", 510260531Sneel vmcs_read(VMCS_EXIT_INTR_ERRCODE)); 511222605Sjhb db_printf("\n"); 512222605Sjhb break; 513222605Sjhb case EXIT_REASON_EPT_FAULT: 514222605Sjhb case EXIT_REASON_EPT_MISCONFIG: 515222605Sjhb db_printf("Guest Physical Address: %#lx\n", 516222605Sjhb vmcs_read(VMCS_GUEST_PHYSICAL_ADDRESS)); 517222605Sjhb break; 518222605Sjhb } 519222605Sjhb db_printf("VM-instruction error: %#lx\n", vmcs_instruction_error()); 520222605Sjhb} 521222605Sjhb#endif 522