1366f6083SPeter Grehan /*- 2366f6083SPeter Grehan * Copyright (c) 2011 NetApp, Inc. 3366f6083SPeter Grehan * All rights reserved. 4366f6083SPeter Grehan * 5366f6083SPeter Grehan * Redistribution and use in source and binary forms, with or without 6366f6083SPeter Grehan * modification, are permitted provided that the following conditions 7366f6083SPeter Grehan * are met: 8366f6083SPeter Grehan * 1. Redistributions of source code must retain the above copyright 9366f6083SPeter Grehan * notice, this list of conditions and the following disclaimer. 10366f6083SPeter Grehan * 2. Redistributions in binary form must reproduce the above copyright 11366f6083SPeter Grehan * notice, this list of conditions and the following disclaimer in the 12366f6083SPeter Grehan * documentation and/or other materials provided with the distribution. 13366f6083SPeter Grehan * 14366f6083SPeter Grehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15366f6083SPeter Grehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16366f6083SPeter Grehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17366f6083SPeter Grehan * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18366f6083SPeter Grehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19366f6083SPeter Grehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20366f6083SPeter Grehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21366f6083SPeter Grehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22366f6083SPeter Grehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23366f6083SPeter Grehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24366f6083SPeter Grehan * SUCH DAMAGE. 25366f6083SPeter Grehan * 26366f6083SPeter Grehan * $FreeBSD$ 27366f6083SPeter Grehan */ 28366f6083SPeter Grehan 29b3996dd4SJohn Baldwin #include "opt_ddb.h" 30b3996dd4SJohn Baldwin 31366f6083SPeter Grehan #include <sys/cdefs.h> 32366f6083SPeter Grehan __FBSDID("$FreeBSD$"); 33366f6083SPeter Grehan 34366f6083SPeter Grehan #include <sys/param.h> 35366f6083SPeter Grehan #include <sys/systm.h> 36366f6083SPeter Grehan #include <sys/pcpu.h> 37366f6083SPeter Grehan 38366f6083SPeter Grehan #include <vm/vm.h> 39366f6083SPeter Grehan #include <vm/pmap.h> 40366f6083SPeter Grehan 41366f6083SPeter Grehan #include <machine/segments.h> 42366f6083SPeter Grehan #include <machine/pmap.h> 43366f6083SPeter Grehan 44366f6083SPeter Grehan #include <machine/vmm.h> 45b01c2033SNeel Natu #include "vmm_host.h" 46366f6083SPeter Grehan #include "vmcs.h" 47366f6083SPeter Grehan #include "vmx_cpufunc.h" 48366f6083SPeter Grehan #include "ept.h" 49366f6083SPeter Grehan #include "vmx.h" 50366f6083SPeter Grehan 51b3996dd4SJohn Baldwin #ifdef DDB 52b3996dd4SJohn Baldwin #include <ddb/ddb.h> 53b3996dd4SJohn Baldwin #endif 54b3996dd4SJohn Baldwin 55366f6083SPeter Grehan static uint64_t 56366f6083SPeter Grehan vmcs_fix_regval(uint32_t encoding, uint64_t val) 57366f6083SPeter Grehan { 58366f6083SPeter Grehan 59366f6083SPeter Grehan switch (encoding) { 60366f6083SPeter Grehan case VMCS_GUEST_CR0: 61366f6083SPeter Grehan val = vmx_fix_cr0(val); 62366f6083SPeter Grehan break; 63366f6083SPeter Grehan case VMCS_GUEST_CR4: 64366f6083SPeter Grehan val = vmx_fix_cr4(val); 65366f6083SPeter Grehan break; 66366f6083SPeter Grehan default: 67366f6083SPeter Grehan break; 68366f6083SPeter Grehan } 69366f6083SPeter Grehan return (val); 70366f6083SPeter Grehan } 71366f6083SPeter Grehan 72366f6083SPeter Grehan static uint32_t 73366f6083SPeter Grehan vmcs_field_encoding(int ident) 74366f6083SPeter Grehan { 75366f6083SPeter Grehan switch (ident) { 76366f6083SPeter Grehan case VM_REG_GUEST_CR0: 77366f6083SPeter Grehan return (VMCS_GUEST_CR0); 78366f6083SPeter Grehan case VM_REG_GUEST_CR3: 79366f6083SPeter Grehan return (VMCS_GUEST_CR3); 80366f6083SPeter Grehan case VM_REG_GUEST_CR4: 81366f6083SPeter Grehan return (VMCS_GUEST_CR4); 82366f6083SPeter Grehan case VM_REG_GUEST_DR7: 83366f6083SPeter Grehan return (VMCS_GUEST_DR7); 84366f6083SPeter Grehan case VM_REG_GUEST_RSP: 85366f6083SPeter Grehan return (VMCS_GUEST_RSP); 86366f6083SPeter Grehan case VM_REG_GUEST_RIP: 87366f6083SPeter Grehan return (VMCS_GUEST_RIP); 88366f6083SPeter Grehan case VM_REG_GUEST_RFLAGS: 89366f6083SPeter Grehan return (VMCS_GUEST_RFLAGS); 90366f6083SPeter Grehan case VM_REG_GUEST_ES: 91366f6083SPeter Grehan return (VMCS_GUEST_ES_SELECTOR); 92366f6083SPeter Grehan case VM_REG_GUEST_CS: 93366f6083SPeter Grehan return (VMCS_GUEST_CS_SELECTOR); 94366f6083SPeter Grehan case VM_REG_GUEST_SS: 95366f6083SPeter Grehan return (VMCS_GUEST_SS_SELECTOR); 96366f6083SPeter Grehan case VM_REG_GUEST_DS: 97366f6083SPeter Grehan return (VMCS_GUEST_DS_SELECTOR); 98366f6083SPeter Grehan case VM_REG_GUEST_FS: 99366f6083SPeter Grehan return (VMCS_GUEST_FS_SELECTOR); 100366f6083SPeter Grehan case VM_REG_GUEST_GS: 101366f6083SPeter Grehan return (VMCS_GUEST_GS_SELECTOR); 102366f6083SPeter Grehan case VM_REG_GUEST_TR: 103366f6083SPeter Grehan return (VMCS_GUEST_TR_SELECTOR); 104366f6083SPeter Grehan case VM_REG_GUEST_LDTR: 105366f6083SPeter Grehan return (VMCS_GUEST_LDTR_SELECTOR); 106366f6083SPeter Grehan case VM_REG_GUEST_EFER: 107366f6083SPeter Grehan return (VMCS_GUEST_IA32_EFER); 108366f6083SPeter Grehan default: 109366f6083SPeter Grehan return (-1); 110366f6083SPeter Grehan } 111366f6083SPeter Grehan 112366f6083SPeter Grehan } 113366f6083SPeter Grehan 114366f6083SPeter Grehan static int 115366f6083SPeter Grehan vmcs_seg_desc_encoding(int seg, uint32_t *base, uint32_t *lim, uint32_t *acc) 116366f6083SPeter Grehan { 117366f6083SPeter Grehan 118366f6083SPeter Grehan switch (seg) { 119366f6083SPeter Grehan case VM_REG_GUEST_ES: 120366f6083SPeter Grehan *base = VMCS_GUEST_ES_BASE; 121366f6083SPeter Grehan *lim = VMCS_GUEST_ES_LIMIT; 122366f6083SPeter Grehan *acc = VMCS_GUEST_ES_ACCESS_RIGHTS; 123366f6083SPeter Grehan break; 124366f6083SPeter Grehan case VM_REG_GUEST_CS: 125366f6083SPeter Grehan *base = VMCS_GUEST_CS_BASE; 126366f6083SPeter Grehan *lim = VMCS_GUEST_CS_LIMIT; 127366f6083SPeter Grehan *acc = VMCS_GUEST_CS_ACCESS_RIGHTS; 128366f6083SPeter Grehan break; 129366f6083SPeter Grehan case VM_REG_GUEST_SS: 130366f6083SPeter Grehan *base = VMCS_GUEST_SS_BASE; 131366f6083SPeter Grehan *lim = VMCS_GUEST_SS_LIMIT; 132366f6083SPeter Grehan *acc = VMCS_GUEST_SS_ACCESS_RIGHTS; 133366f6083SPeter Grehan break; 134366f6083SPeter Grehan case VM_REG_GUEST_DS: 135366f6083SPeter Grehan *base = VMCS_GUEST_DS_BASE; 136366f6083SPeter Grehan *lim = VMCS_GUEST_DS_LIMIT; 137366f6083SPeter Grehan *acc = VMCS_GUEST_DS_ACCESS_RIGHTS; 138366f6083SPeter Grehan break; 139366f6083SPeter Grehan case VM_REG_GUEST_FS: 140366f6083SPeter Grehan *base = VMCS_GUEST_FS_BASE; 141366f6083SPeter Grehan *lim = VMCS_GUEST_FS_LIMIT; 142366f6083SPeter Grehan *acc = VMCS_GUEST_FS_ACCESS_RIGHTS; 143366f6083SPeter Grehan break; 144366f6083SPeter Grehan case VM_REG_GUEST_GS: 145366f6083SPeter Grehan *base = VMCS_GUEST_GS_BASE; 146366f6083SPeter Grehan *lim = VMCS_GUEST_GS_LIMIT; 147366f6083SPeter Grehan *acc = VMCS_GUEST_GS_ACCESS_RIGHTS; 148366f6083SPeter Grehan break; 149366f6083SPeter Grehan case VM_REG_GUEST_TR: 150366f6083SPeter Grehan *base = VMCS_GUEST_TR_BASE; 151366f6083SPeter Grehan *lim = VMCS_GUEST_TR_LIMIT; 152366f6083SPeter Grehan *acc = VMCS_GUEST_TR_ACCESS_RIGHTS; 153366f6083SPeter Grehan break; 154366f6083SPeter Grehan case VM_REG_GUEST_LDTR: 155366f6083SPeter Grehan *base = VMCS_GUEST_LDTR_BASE; 156366f6083SPeter Grehan *lim = VMCS_GUEST_LDTR_LIMIT; 157366f6083SPeter Grehan *acc = VMCS_GUEST_LDTR_ACCESS_RIGHTS; 158366f6083SPeter Grehan break; 159366f6083SPeter Grehan case VM_REG_GUEST_IDTR: 160366f6083SPeter Grehan *base = VMCS_GUEST_IDTR_BASE; 161366f6083SPeter Grehan *lim = VMCS_GUEST_IDTR_LIMIT; 162366f6083SPeter Grehan *acc = VMCS_INVALID_ENCODING; 163366f6083SPeter Grehan break; 164366f6083SPeter Grehan case VM_REG_GUEST_GDTR: 165366f6083SPeter Grehan *base = VMCS_GUEST_GDTR_BASE; 166366f6083SPeter Grehan *lim = VMCS_GUEST_GDTR_LIMIT; 167366f6083SPeter Grehan *acc = VMCS_INVALID_ENCODING; 168366f6083SPeter Grehan break; 169366f6083SPeter Grehan default: 170366f6083SPeter Grehan return (EINVAL); 171366f6083SPeter Grehan } 172366f6083SPeter Grehan 173366f6083SPeter Grehan return (0); 174366f6083SPeter Grehan } 175366f6083SPeter Grehan 176366f6083SPeter Grehan int 177*d3c11f40SPeter Grehan vmcs_getreg(struct vmcs *vmcs, int running, int ident, uint64_t *retval) 178366f6083SPeter Grehan { 179366f6083SPeter Grehan int error; 180366f6083SPeter Grehan uint32_t encoding; 181366f6083SPeter Grehan 182366f6083SPeter Grehan /* 183366f6083SPeter Grehan * If we need to get at vmx-specific state in the VMCS we can bypass 184366f6083SPeter Grehan * the translation of 'ident' to 'encoding' by simply setting the 185366f6083SPeter Grehan * sign bit. As it so happens the upper 16 bits are reserved (i.e 186366f6083SPeter Grehan * set to 0) in the encodings for the VMCS so we are free to use the 187366f6083SPeter Grehan * sign bit. 188366f6083SPeter Grehan */ 189366f6083SPeter Grehan if (ident < 0) 190366f6083SPeter Grehan encoding = ident & 0x7fffffff; 191366f6083SPeter Grehan else 192366f6083SPeter Grehan encoding = vmcs_field_encoding(ident); 193366f6083SPeter Grehan 194366f6083SPeter Grehan if (encoding == (uint32_t)-1) 195366f6083SPeter Grehan return (EINVAL); 196366f6083SPeter Grehan 197*d3c11f40SPeter Grehan if (!running) 198366f6083SPeter Grehan VMPTRLD(vmcs); 199*d3c11f40SPeter Grehan 200366f6083SPeter Grehan error = vmread(encoding, retval); 201*d3c11f40SPeter Grehan 202*d3c11f40SPeter Grehan if (!running) 203366f6083SPeter Grehan VMCLEAR(vmcs); 204*d3c11f40SPeter Grehan 205366f6083SPeter Grehan return (error); 206366f6083SPeter Grehan } 207366f6083SPeter Grehan 208366f6083SPeter Grehan int 209*d3c11f40SPeter Grehan vmcs_setreg(struct vmcs *vmcs, int running, int ident, uint64_t val) 210366f6083SPeter Grehan { 211366f6083SPeter Grehan int error; 212366f6083SPeter Grehan uint32_t encoding; 213366f6083SPeter Grehan 214366f6083SPeter Grehan if (ident < 0) 215366f6083SPeter Grehan encoding = ident & 0x7fffffff; 216366f6083SPeter Grehan else 217366f6083SPeter Grehan encoding = vmcs_field_encoding(ident); 218366f6083SPeter Grehan 219366f6083SPeter Grehan if (encoding == (uint32_t)-1) 220366f6083SPeter Grehan return (EINVAL); 221366f6083SPeter Grehan 222366f6083SPeter Grehan val = vmcs_fix_regval(encoding, val); 223366f6083SPeter Grehan 224*d3c11f40SPeter Grehan if (!running) 225366f6083SPeter Grehan VMPTRLD(vmcs); 226*d3c11f40SPeter Grehan 227366f6083SPeter Grehan error = vmwrite(encoding, val); 228*d3c11f40SPeter Grehan 229*d3c11f40SPeter Grehan if (!running) 230366f6083SPeter Grehan VMCLEAR(vmcs); 231*d3c11f40SPeter Grehan 232366f6083SPeter Grehan return (error); 233366f6083SPeter Grehan } 234366f6083SPeter Grehan 235366f6083SPeter Grehan int 236366f6083SPeter Grehan vmcs_setdesc(struct vmcs *vmcs, int seg, struct seg_desc *desc) 237366f6083SPeter Grehan { 238366f6083SPeter Grehan int error; 239366f6083SPeter Grehan uint32_t base, limit, access; 240366f6083SPeter Grehan 241366f6083SPeter Grehan error = vmcs_seg_desc_encoding(seg, &base, &limit, &access); 242366f6083SPeter Grehan if (error != 0) 243366f6083SPeter Grehan panic("vmcs_setdesc: invalid segment register %d", seg); 244366f6083SPeter Grehan 245366f6083SPeter Grehan VMPTRLD(vmcs); 246366f6083SPeter Grehan if ((error = vmwrite(base, desc->base)) != 0) 247366f6083SPeter Grehan goto done; 248366f6083SPeter Grehan 249366f6083SPeter Grehan if ((error = vmwrite(limit, desc->limit)) != 0) 250366f6083SPeter Grehan goto done; 251366f6083SPeter Grehan 252366f6083SPeter Grehan if (access != VMCS_INVALID_ENCODING) { 253366f6083SPeter Grehan if ((error = vmwrite(access, desc->access)) != 0) 254366f6083SPeter Grehan goto done; 255366f6083SPeter Grehan } 256366f6083SPeter Grehan done: 257366f6083SPeter Grehan VMCLEAR(vmcs); 258366f6083SPeter Grehan return (error); 259366f6083SPeter Grehan } 260366f6083SPeter Grehan 261366f6083SPeter Grehan int 262366f6083SPeter Grehan vmcs_getdesc(struct vmcs *vmcs, int seg, struct seg_desc *desc) 263366f6083SPeter Grehan { 264366f6083SPeter Grehan int error; 265366f6083SPeter Grehan uint32_t base, limit, access; 266366f6083SPeter Grehan uint64_t u64; 267366f6083SPeter Grehan 268366f6083SPeter Grehan error = vmcs_seg_desc_encoding(seg, &base, &limit, &access); 269366f6083SPeter Grehan if (error != 0) 270366f6083SPeter Grehan panic("vmcs_getdesc: invalid segment register %d", seg); 271366f6083SPeter Grehan 272366f6083SPeter Grehan VMPTRLD(vmcs); 273366f6083SPeter Grehan if ((error = vmread(base, &u64)) != 0) 274366f6083SPeter Grehan goto done; 275366f6083SPeter Grehan desc->base = u64; 276366f6083SPeter Grehan 277366f6083SPeter Grehan if ((error = vmread(limit, &u64)) != 0) 278366f6083SPeter Grehan goto done; 279366f6083SPeter Grehan desc->limit = u64; 280366f6083SPeter Grehan 281366f6083SPeter Grehan if (access != VMCS_INVALID_ENCODING) { 282366f6083SPeter Grehan if ((error = vmread(access, &u64)) != 0) 283366f6083SPeter Grehan goto done; 284366f6083SPeter Grehan desc->access = u64; 285366f6083SPeter Grehan } 286366f6083SPeter Grehan done: 287366f6083SPeter Grehan VMCLEAR(vmcs); 288366f6083SPeter Grehan return (error); 289366f6083SPeter Grehan } 290366f6083SPeter Grehan 291366f6083SPeter Grehan int 292366f6083SPeter Grehan vmcs_set_msr_save(struct vmcs *vmcs, u_long g_area, u_int g_count) 293366f6083SPeter Grehan { 294366f6083SPeter Grehan int error; 295366f6083SPeter Grehan 296366f6083SPeter Grehan VMPTRLD(vmcs); 297366f6083SPeter Grehan 298366f6083SPeter Grehan /* 299366f6083SPeter Grehan * Guest MSRs are saved in the VM-exit MSR-store area. 300366f6083SPeter Grehan * Guest MSRs are loaded from the VM-entry MSR-load area. 301366f6083SPeter Grehan * Both areas point to the same location in memory. 302366f6083SPeter Grehan */ 303366f6083SPeter Grehan if ((error = vmwrite(VMCS_EXIT_MSR_STORE, g_area)) != 0) 304366f6083SPeter Grehan goto done; 305366f6083SPeter Grehan if ((error = vmwrite(VMCS_EXIT_MSR_STORE_COUNT, g_count)) != 0) 306366f6083SPeter Grehan goto done; 307366f6083SPeter Grehan 308366f6083SPeter Grehan if ((error = vmwrite(VMCS_ENTRY_MSR_LOAD, g_area)) != 0) 309366f6083SPeter Grehan goto done; 310366f6083SPeter Grehan if ((error = vmwrite(VMCS_ENTRY_MSR_LOAD_COUNT, g_count)) != 0) 311366f6083SPeter Grehan goto done; 312366f6083SPeter Grehan 313366f6083SPeter Grehan error = 0; 314366f6083SPeter Grehan done: 315366f6083SPeter Grehan VMCLEAR(vmcs); 316366f6083SPeter Grehan return (error); 317366f6083SPeter Grehan } 318366f6083SPeter Grehan 319366f6083SPeter Grehan int 320366f6083SPeter Grehan vmcs_set_defaults(struct vmcs *vmcs, 321366f6083SPeter Grehan u_long host_rip, u_long host_rsp, u_long ept_pml4, 322366f6083SPeter Grehan uint32_t pinbased_ctls, uint32_t procbased_ctls, 323366f6083SPeter Grehan uint32_t procbased_ctls2, uint32_t exit_ctls, 324366f6083SPeter Grehan uint32_t entry_ctls, u_long msr_bitmap, uint16_t vpid) 325366f6083SPeter Grehan { 326366f6083SPeter Grehan int error, codesel, datasel, tsssel; 327366f6083SPeter Grehan u_long cr0, cr4, efer; 328b01c2033SNeel Natu uint64_t eptp, pat, fsbase, idtrbase; 329366f6083SPeter Grehan uint32_t exc_bitmap; 330366f6083SPeter Grehan 331b01c2033SNeel Natu codesel = vmm_get_host_codesel(); 332b01c2033SNeel Natu datasel = vmm_get_host_datasel(); 333b01c2033SNeel Natu tsssel = vmm_get_host_tsssel(); 334366f6083SPeter Grehan 335366f6083SPeter Grehan /* 336366f6083SPeter Grehan * Make sure we have a "current" VMCS to work with. 337366f6083SPeter Grehan */ 338366f6083SPeter Grehan VMPTRLD(vmcs); 339366f6083SPeter Grehan 340366f6083SPeter Grehan /* 341366f6083SPeter Grehan * Load the VMX controls 342366f6083SPeter Grehan */ 343366f6083SPeter Grehan if ((error = vmwrite(VMCS_PIN_BASED_CTLS, pinbased_ctls)) != 0) 344366f6083SPeter Grehan goto done; 345366f6083SPeter Grehan if ((error = vmwrite(VMCS_PRI_PROC_BASED_CTLS, procbased_ctls)) != 0) 346366f6083SPeter Grehan goto done; 347366f6083SPeter Grehan if ((error = vmwrite(VMCS_SEC_PROC_BASED_CTLS, procbased_ctls2)) != 0) 348366f6083SPeter Grehan goto done; 349366f6083SPeter Grehan if ((error = vmwrite(VMCS_EXIT_CTLS, exit_ctls)) != 0) 350366f6083SPeter Grehan goto done; 351366f6083SPeter Grehan if ((error = vmwrite(VMCS_ENTRY_CTLS, entry_ctls)) != 0) 352366f6083SPeter Grehan goto done; 353366f6083SPeter Grehan 354366f6083SPeter Grehan /* Guest state */ 355366f6083SPeter Grehan 356366f6083SPeter Grehan /* Initialize guest IA32_PAT MSR with the default value */ 357366f6083SPeter Grehan pat = PAT_VALUE(0, PAT_WRITE_BACK) | 358366f6083SPeter Grehan PAT_VALUE(1, PAT_WRITE_THROUGH) | 359366f6083SPeter Grehan PAT_VALUE(2, PAT_UNCACHED) | 360366f6083SPeter Grehan PAT_VALUE(3, PAT_UNCACHEABLE) | 361366f6083SPeter Grehan PAT_VALUE(4, PAT_WRITE_BACK) | 362366f6083SPeter Grehan PAT_VALUE(5, PAT_WRITE_THROUGH) | 363366f6083SPeter Grehan PAT_VALUE(6, PAT_UNCACHED) | 364366f6083SPeter Grehan PAT_VALUE(7, PAT_UNCACHEABLE); 365366f6083SPeter Grehan if ((error = vmwrite(VMCS_GUEST_IA32_PAT, pat)) != 0) 366366f6083SPeter Grehan goto done; 367366f6083SPeter Grehan 368366f6083SPeter Grehan /* Host state */ 369366f6083SPeter Grehan 370366f6083SPeter Grehan /* Initialize host IA32_PAT MSR */ 371b01c2033SNeel Natu pat = vmm_get_host_pat(); 372366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_IA32_PAT, pat)) != 0) 373366f6083SPeter Grehan goto done; 374366f6083SPeter Grehan 375366f6083SPeter Grehan /* Load the IA32_EFER MSR */ 376b01c2033SNeel Natu efer = vmm_get_host_efer(); 377366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_IA32_EFER, efer)) != 0) 378366f6083SPeter Grehan goto done; 379366f6083SPeter Grehan 380366f6083SPeter Grehan /* Load the control registers */ 381bd8572e0SNeel Natu 382b01c2033SNeel Natu cr0 = vmm_get_host_cr0(); 383366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_CR0, cr0)) != 0) 384366f6083SPeter Grehan goto done; 385366f6083SPeter Grehan 386b01c2033SNeel Natu cr4 = vmm_get_host_cr4() | CR4_VMXE; 387366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_CR4, cr4)) != 0) 388366f6083SPeter Grehan goto done; 389366f6083SPeter Grehan 390366f6083SPeter Grehan /* Load the segment selectors */ 391366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_ES_SELECTOR, datasel)) != 0) 392366f6083SPeter Grehan goto done; 393366f6083SPeter Grehan 394366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_CS_SELECTOR, codesel)) != 0) 395366f6083SPeter Grehan goto done; 396366f6083SPeter Grehan 397366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_SS_SELECTOR, datasel)) != 0) 398366f6083SPeter Grehan goto done; 399366f6083SPeter Grehan 400366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_DS_SELECTOR, datasel)) != 0) 401366f6083SPeter Grehan goto done; 402366f6083SPeter Grehan 403366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_FS_SELECTOR, datasel)) != 0) 404366f6083SPeter Grehan goto done; 405366f6083SPeter Grehan 406366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_GS_SELECTOR, datasel)) != 0) 407366f6083SPeter Grehan goto done; 408366f6083SPeter Grehan 409366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_TR_SELECTOR, tsssel)) != 0) 410366f6083SPeter Grehan goto done; 411366f6083SPeter Grehan 412366f6083SPeter Grehan /* 413366f6083SPeter Grehan * Load the Base-Address for %fs and idtr. 414366f6083SPeter Grehan * 415366f6083SPeter Grehan * Note that we exclude %gs, tss and gdtr here because their base 416366f6083SPeter Grehan * address is pcpu specific. 417366f6083SPeter Grehan */ 418b01c2033SNeel Natu fsbase = vmm_get_host_fsbase(); 419b01c2033SNeel Natu if ((error = vmwrite(VMCS_HOST_FS_BASE, fsbase)) != 0) 420366f6083SPeter Grehan goto done; 421366f6083SPeter Grehan 422b01c2033SNeel Natu idtrbase = vmm_get_host_idtrbase(); 423b01c2033SNeel Natu if ((error = vmwrite(VMCS_HOST_IDTR_BASE, idtrbase)) != 0) 424366f6083SPeter Grehan goto done; 425366f6083SPeter Grehan 426366f6083SPeter Grehan /* instruction pointer */ 427366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_RIP, host_rip)) != 0) 428366f6083SPeter Grehan goto done; 429366f6083SPeter Grehan 430366f6083SPeter Grehan /* stack pointer */ 431366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_RSP, host_rsp)) != 0) 432366f6083SPeter Grehan goto done; 433366f6083SPeter Grehan 434366f6083SPeter Grehan /* eptp */ 435366f6083SPeter Grehan eptp = EPTP(ept_pml4); 436366f6083SPeter Grehan if ((error = vmwrite(VMCS_EPTP, eptp)) != 0) 437366f6083SPeter Grehan goto done; 438366f6083SPeter Grehan 439366f6083SPeter Grehan /* vpid */ 440366f6083SPeter Grehan if ((error = vmwrite(VMCS_VPID, vpid)) != 0) 441366f6083SPeter Grehan goto done; 442366f6083SPeter Grehan 443366f6083SPeter Grehan /* msr bitmap */ 444366f6083SPeter Grehan if ((error = vmwrite(VMCS_MSR_BITMAP, msr_bitmap)) != 0) 445366f6083SPeter Grehan goto done; 446366f6083SPeter Grehan 447366f6083SPeter Grehan /* exception bitmap */ 448366f6083SPeter Grehan exc_bitmap = 1 << IDT_MC; 449366f6083SPeter Grehan if ((error = vmwrite(VMCS_EXCEPTION_BITMAP, exc_bitmap)) != 0) 450366f6083SPeter Grehan goto done; 451366f6083SPeter Grehan 452366f6083SPeter Grehan /* link pointer */ 453366f6083SPeter Grehan if ((error = vmwrite(VMCS_LINK_POINTER, ~0)) != 0) 454366f6083SPeter Grehan goto done; 455366f6083SPeter Grehan done: 456366f6083SPeter Grehan VMCLEAR(vmcs); 457366f6083SPeter Grehan return (error); 458366f6083SPeter Grehan } 459366f6083SPeter Grehan 460366f6083SPeter Grehan uint64_t 461366f6083SPeter Grehan vmcs_read(uint32_t encoding) 462366f6083SPeter Grehan { 463366f6083SPeter Grehan int error; 464366f6083SPeter Grehan uint64_t val; 465366f6083SPeter Grehan 466366f6083SPeter Grehan error = vmread(encoding, &val); 467366f6083SPeter Grehan if (error != 0) 468366f6083SPeter Grehan panic("vmcs_read(%u) error %d", encoding, error); 469366f6083SPeter Grehan 470366f6083SPeter Grehan return (val); 471366f6083SPeter Grehan } 472b3996dd4SJohn Baldwin 473b3996dd4SJohn Baldwin #ifdef DDB 474b3996dd4SJohn Baldwin extern int vmxon_enabled[]; 475b3996dd4SJohn Baldwin 476b3996dd4SJohn Baldwin DB_SHOW_COMMAND(vmcs, db_show_vmcs) 477b3996dd4SJohn Baldwin { 478b3996dd4SJohn Baldwin uint64_t cur_vmcs, val; 479b3996dd4SJohn Baldwin uint32_t exit; 480b3996dd4SJohn Baldwin 481b3996dd4SJohn Baldwin if (!vmxon_enabled[curcpu]) { 482b3996dd4SJohn Baldwin db_printf("VMX not enabled\n"); 483b3996dd4SJohn Baldwin return; 484b3996dd4SJohn Baldwin } 485b3996dd4SJohn Baldwin 486b3996dd4SJohn Baldwin if (have_addr) { 487b3996dd4SJohn Baldwin db_printf("Only current VMCS supported\n"); 488b3996dd4SJohn Baldwin return; 489b3996dd4SJohn Baldwin } 490b3996dd4SJohn Baldwin 491b3996dd4SJohn Baldwin vmptrst(&cur_vmcs); 492b3996dd4SJohn Baldwin if (cur_vmcs == VMCS_INITIAL) { 493b3996dd4SJohn Baldwin db_printf("No current VM context\n"); 494b3996dd4SJohn Baldwin return; 495b3996dd4SJohn Baldwin } 496b3996dd4SJohn Baldwin db_printf("VMCS: %jx\n", cur_vmcs); 497b3996dd4SJohn Baldwin db_printf("VPID: %lu\n", vmcs_read(VMCS_VPID)); 498b3996dd4SJohn Baldwin db_printf("Activity: "); 499b3996dd4SJohn Baldwin val = vmcs_read(VMCS_GUEST_ACTIVITY); 500b3996dd4SJohn Baldwin switch (val) { 501b3996dd4SJohn Baldwin case 0: 502b3996dd4SJohn Baldwin db_printf("Active"); 503b3996dd4SJohn Baldwin break; 504b3996dd4SJohn Baldwin case 1: 505b3996dd4SJohn Baldwin db_printf("HLT"); 506b3996dd4SJohn Baldwin break; 507b3996dd4SJohn Baldwin case 2: 508b3996dd4SJohn Baldwin db_printf("Shutdown"); 509b3996dd4SJohn Baldwin break; 510b3996dd4SJohn Baldwin case 3: 511b3996dd4SJohn Baldwin db_printf("Wait for SIPI"); 512b3996dd4SJohn Baldwin break; 513b3996dd4SJohn Baldwin default: 514b3996dd4SJohn Baldwin db_printf("Unknown: %#lx", val); 515b3996dd4SJohn Baldwin } 516b3996dd4SJohn Baldwin db_printf("\n"); 517b3996dd4SJohn Baldwin exit = vmcs_read(VMCS_EXIT_REASON); 518b3996dd4SJohn Baldwin if (exit & 0x80000000) 519b3996dd4SJohn Baldwin db_printf("Entry Failure Reason: %u\n", exit & 0xffff); 520b3996dd4SJohn Baldwin else 521b3996dd4SJohn Baldwin db_printf("Exit Reason: %u\n", exit & 0xffff); 522b3996dd4SJohn Baldwin db_printf("Qualification: %#lx\n", vmcs_exit_qualification()); 523b3996dd4SJohn Baldwin db_printf("Guest Linear Address: %#lx\n", 524b3996dd4SJohn Baldwin vmcs_read(VMCS_GUEST_LINEAR_ADDRESS)); 525b3996dd4SJohn Baldwin switch (exit & 0x8000ffff) { 526b3996dd4SJohn Baldwin case EXIT_REASON_EXCEPTION: 527b3996dd4SJohn Baldwin case EXIT_REASON_EXT_INTR: 528b3996dd4SJohn Baldwin val = vmcs_read(VMCS_EXIT_INTERRUPTION_INFO); 529b3996dd4SJohn Baldwin db_printf("Interrupt Type: "); 530b3996dd4SJohn Baldwin switch (val >> 8 & 0x7) { 531b3996dd4SJohn Baldwin case 0: 532b3996dd4SJohn Baldwin db_printf("external"); 533b3996dd4SJohn Baldwin break; 534b3996dd4SJohn Baldwin case 2: 535b3996dd4SJohn Baldwin db_printf("NMI"); 536b3996dd4SJohn Baldwin break; 537b3996dd4SJohn Baldwin case 3: 538b3996dd4SJohn Baldwin db_printf("HW exception"); 539b3996dd4SJohn Baldwin break; 540b3996dd4SJohn Baldwin case 4: 541b3996dd4SJohn Baldwin db_printf("SW exception"); 542b3996dd4SJohn Baldwin break; 543b3996dd4SJohn Baldwin default: 544b3996dd4SJohn Baldwin db_printf("?? %lu", val >> 8 & 0x7); 545b3996dd4SJohn Baldwin break; 546b3996dd4SJohn Baldwin } 547b3996dd4SJohn Baldwin db_printf(" Vector: %lu", val & 0xff); 548b3996dd4SJohn Baldwin if (val & 0x800) 549b3996dd4SJohn Baldwin db_printf(" Error Code: %lx", 550b3996dd4SJohn Baldwin vmcs_read(VMCS_EXIT_INTERRUPTION_ERROR)); 551b3996dd4SJohn Baldwin db_printf("\n"); 552b3996dd4SJohn Baldwin break; 553b3996dd4SJohn Baldwin case EXIT_REASON_EPT_FAULT: 554b3996dd4SJohn Baldwin case EXIT_REASON_EPT_MISCONFIG: 555b3996dd4SJohn Baldwin db_printf("Guest Physical Address: %#lx\n", 556b3996dd4SJohn Baldwin vmcs_read(VMCS_GUEST_PHYSICAL_ADDRESS)); 557b3996dd4SJohn Baldwin break; 558b3996dd4SJohn Baldwin } 559b3996dd4SJohn Baldwin db_printf("VM-instruction error: %#lx\n", vmcs_instruction_error()); 560b3996dd4SJohn Baldwin } 561b3996dd4SJohn Baldwin #endif 562