1366f6083SPeter Grehan /*- 2c49761ddSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3c49761ddSPedro F. Giffuni * 4366f6083SPeter Grehan * Copyright (c) 2011 NetApp, Inc. 5366f6083SPeter Grehan * All rights reserved. 6366f6083SPeter Grehan * 7366f6083SPeter Grehan * Redistribution and use in source and binary forms, with or without 8366f6083SPeter Grehan * modification, are permitted provided that the following conditions 9366f6083SPeter Grehan * are met: 10366f6083SPeter Grehan * 1. Redistributions of source code must retain the above copyright 11366f6083SPeter Grehan * notice, this list of conditions and the following disclaimer. 12366f6083SPeter Grehan * 2. Redistributions in binary form must reproduce the above copyright 13366f6083SPeter Grehan * notice, this list of conditions and the following disclaimer in the 14366f6083SPeter Grehan * documentation and/or other materials provided with the distribution. 15366f6083SPeter Grehan * 16366f6083SPeter Grehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 17366f6083SPeter Grehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18366f6083SPeter Grehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19366f6083SPeter Grehan * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 20366f6083SPeter Grehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21366f6083SPeter Grehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22366f6083SPeter Grehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23366f6083SPeter Grehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24366f6083SPeter Grehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25366f6083SPeter Grehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26366f6083SPeter Grehan * SUCH DAMAGE. 27366f6083SPeter Grehan * 28366f6083SPeter Grehan * $FreeBSD$ 29366f6083SPeter Grehan */ 30366f6083SPeter Grehan 31*483d953aSJohn Baldwin #include "opt_bhyve_snapshot.h" 32b3996dd4SJohn Baldwin #include "opt_ddb.h" 33b3996dd4SJohn Baldwin 34366f6083SPeter Grehan #include <sys/cdefs.h> 35366f6083SPeter Grehan __FBSDID("$FreeBSD$"); 36366f6083SPeter Grehan 37366f6083SPeter Grehan #include <sys/param.h> 3858a6aaf7STycho Nightingale #include <sys/sysctl.h> 39366f6083SPeter Grehan #include <sys/systm.h> 40366f6083SPeter Grehan #include <sys/pcpu.h> 41366f6083SPeter Grehan 42366f6083SPeter Grehan #include <vm/vm.h> 43366f6083SPeter Grehan #include <vm/pmap.h> 44366f6083SPeter Grehan 45366f6083SPeter Grehan #include <machine/segments.h> 46366f6083SPeter Grehan #include <machine/vmm.h> 47*483d953aSJohn Baldwin #include <machine/vmm_snapshot.h> 48b01c2033SNeel Natu #include "vmm_host.h" 49366f6083SPeter Grehan #include "vmx_cpufunc.h" 503de83862SNeel Natu #include "vmcs.h" 51366f6083SPeter Grehan #include "ept.h" 52366f6083SPeter Grehan #include "vmx.h" 53366f6083SPeter Grehan 54b3996dd4SJohn Baldwin #ifdef DDB 55b3996dd4SJohn Baldwin #include <ddb/ddb.h> 56b3996dd4SJohn Baldwin #endif 57b3996dd4SJohn Baldwin 5858a6aaf7STycho Nightingale SYSCTL_DECL(_hw_vmm_vmx); 5958a6aaf7STycho Nightingale 6058a6aaf7STycho Nightingale static int no_flush_rsb; 6158a6aaf7STycho Nightingale SYSCTL_INT(_hw_vmm_vmx, OID_AUTO, no_flush_rsb, CTLFLAG_RW, 6258a6aaf7STycho Nightingale &no_flush_rsb, 0, "Do not flush RSB upon vmexit"); 6358a6aaf7STycho Nightingale 64366f6083SPeter Grehan static uint64_t 65366f6083SPeter Grehan vmcs_fix_regval(uint32_t encoding, uint64_t val) 66366f6083SPeter Grehan { 67366f6083SPeter Grehan 68366f6083SPeter Grehan switch (encoding) { 69366f6083SPeter Grehan case VMCS_GUEST_CR0: 70366f6083SPeter Grehan val = vmx_fix_cr0(val); 71366f6083SPeter Grehan break; 72366f6083SPeter Grehan case VMCS_GUEST_CR4: 73366f6083SPeter Grehan val = vmx_fix_cr4(val); 74366f6083SPeter Grehan break; 75366f6083SPeter Grehan default: 76366f6083SPeter Grehan break; 77366f6083SPeter Grehan } 78366f6083SPeter Grehan return (val); 79366f6083SPeter Grehan } 80366f6083SPeter Grehan 81366f6083SPeter Grehan static uint32_t 82366f6083SPeter Grehan vmcs_field_encoding(int ident) 83366f6083SPeter Grehan { 84366f6083SPeter Grehan switch (ident) { 85366f6083SPeter Grehan case VM_REG_GUEST_CR0: 86366f6083SPeter Grehan return (VMCS_GUEST_CR0); 87366f6083SPeter Grehan case VM_REG_GUEST_CR3: 88366f6083SPeter Grehan return (VMCS_GUEST_CR3); 89366f6083SPeter Grehan case VM_REG_GUEST_CR4: 90366f6083SPeter Grehan return (VMCS_GUEST_CR4); 91366f6083SPeter Grehan case VM_REG_GUEST_DR7: 92366f6083SPeter Grehan return (VMCS_GUEST_DR7); 93366f6083SPeter Grehan case VM_REG_GUEST_RSP: 94366f6083SPeter Grehan return (VMCS_GUEST_RSP); 95366f6083SPeter Grehan case VM_REG_GUEST_RIP: 96366f6083SPeter Grehan return (VMCS_GUEST_RIP); 97366f6083SPeter Grehan case VM_REG_GUEST_RFLAGS: 98366f6083SPeter Grehan return (VMCS_GUEST_RFLAGS); 99366f6083SPeter Grehan case VM_REG_GUEST_ES: 100366f6083SPeter Grehan return (VMCS_GUEST_ES_SELECTOR); 101366f6083SPeter Grehan case VM_REG_GUEST_CS: 102366f6083SPeter Grehan return (VMCS_GUEST_CS_SELECTOR); 103366f6083SPeter Grehan case VM_REG_GUEST_SS: 104366f6083SPeter Grehan return (VMCS_GUEST_SS_SELECTOR); 105366f6083SPeter Grehan case VM_REG_GUEST_DS: 106366f6083SPeter Grehan return (VMCS_GUEST_DS_SELECTOR); 107366f6083SPeter Grehan case VM_REG_GUEST_FS: 108366f6083SPeter Grehan return (VMCS_GUEST_FS_SELECTOR); 109366f6083SPeter Grehan case VM_REG_GUEST_GS: 110366f6083SPeter Grehan return (VMCS_GUEST_GS_SELECTOR); 111366f6083SPeter Grehan case VM_REG_GUEST_TR: 112366f6083SPeter Grehan return (VMCS_GUEST_TR_SELECTOR); 113366f6083SPeter Grehan case VM_REG_GUEST_LDTR: 114366f6083SPeter Grehan return (VMCS_GUEST_LDTR_SELECTOR); 115366f6083SPeter Grehan case VM_REG_GUEST_EFER: 116366f6083SPeter Grehan return (VMCS_GUEST_IA32_EFER); 1173d5444c8SNeel Natu case VM_REG_GUEST_PDPTE0: 1183d5444c8SNeel Natu return (VMCS_GUEST_PDPTE0); 1193d5444c8SNeel Natu case VM_REG_GUEST_PDPTE1: 1203d5444c8SNeel Natu return (VMCS_GUEST_PDPTE1); 1213d5444c8SNeel Natu case VM_REG_GUEST_PDPTE2: 1223d5444c8SNeel Natu return (VMCS_GUEST_PDPTE2); 1233d5444c8SNeel Natu case VM_REG_GUEST_PDPTE3: 1243d5444c8SNeel Natu return (VMCS_GUEST_PDPTE3); 125cbd03a9dSJohn Baldwin case VM_REG_GUEST_ENTRY_INST_LENGTH: 126cbd03a9dSJohn Baldwin return (VMCS_ENTRY_INST_LENGTH); 127366f6083SPeter Grehan default: 128366f6083SPeter Grehan return (-1); 129366f6083SPeter Grehan } 130366f6083SPeter Grehan 131366f6083SPeter Grehan } 132366f6083SPeter Grehan 133366f6083SPeter Grehan static int 134366f6083SPeter Grehan vmcs_seg_desc_encoding(int seg, uint32_t *base, uint32_t *lim, uint32_t *acc) 135366f6083SPeter Grehan { 136366f6083SPeter Grehan 137366f6083SPeter Grehan switch (seg) { 138366f6083SPeter Grehan case VM_REG_GUEST_ES: 139366f6083SPeter Grehan *base = VMCS_GUEST_ES_BASE; 140366f6083SPeter Grehan *lim = VMCS_GUEST_ES_LIMIT; 141366f6083SPeter Grehan *acc = VMCS_GUEST_ES_ACCESS_RIGHTS; 142366f6083SPeter Grehan break; 143366f6083SPeter Grehan case VM_REG_GUEST_CS: 144366f6083SPeter Grehan *base = VMCS_GUEST_CS_BASE; 145366f6083SPeter Grehan *lim = VMCS_GUEST_CS_LIMIT; 146366f6083SPeter Grehan *acc = VMCS_GUEST_CS_ACCESS_RIGHTS; 147366f6083SPeter Grehan break; 148366f6083SPeter Grehan case VM_REG_GUEST_SS: 149366f6083SPeter Grehan *base = VMCS_GUEST_SS_BASE; 150366f6083SPeter Grehan *lim = VMCS_GUEST_SS_LIMIT; 151366f6083SPeter Grehan *acc = VMCS_GUEST_SS_ACCESS_RIGHTS; 152366f6083SPeter Grehan break; 153366f6083SPeter Grehan case VM_REG_GUEST_DS: 154366f6083SPeter Grehan *base = VMCS_GUEST_DS_BASE; 155366f6083SPeter Grehan *lim = VMCS_GUEST_DS_LIMIT; 156366f6083SPeter Grehan *acc = VMCS_GUEST_DS_ACCESS_RIGHTS; 157366f6083SPeter Grehan break; 158366f6083SPeter Grehan case VM_REG_GUEST_FS: 159366f6083SPeter Grehan *base = VMCS_GUEST_FS_BASE; 160366f6083SPeter Grehan *lim = VMCS_GUEST_FS_LIMIT; 161366f6083SPeter Grehan *acc = VMCS_GUEST_FS_ACCESS_RIGHTS; 162366f6083SPeter Grehan break; 163366f6083SPeter Grehan case VM_REG_GUEST_GS: 164366f6083SPeter Grehan *base = VMCS_GUEST_GS_BASE; 165366f6083SPeter Grehan *lim = VMCS_GUEST_GS_LIMIT; 166366f6083SPeter Grehan *acc = VMCS_GUEST_GS_ACCESS_RIGHTS; 167366f6083SPeter Grehan break; 168366f6083SPeter Grehan case VM_REG_GUEST_TR: 169366f6083SPeter Grehan *base = VMCS_GUEST_TR_BASE; 170366f6083SPeter Grehan *lim = VMCS_GUEST_TR_LIMIT; 171366f6083SPeter Grehan *acc = VMCS_GUEST_TR_ACCESS_RIGHTS; 172366f6083SPeter Grehan break; 173366f6083SPeter Grehan case VM_REG_GUEST_LDTR: 174366f6083SPeter Grehan *base = VMCS_GUEST_LDTR_BASE; 175366f6083SPeter Grehan *lim = VMCS_GUEST_LDTR_LIMIT; 176366f6083SPeter Grehan *acc = VMCS_GUEST_LDTR_ACCESS_RIGHTS; 177366f6083SPeter Grehan break; 178366f6083SPeter Grehan case VM_REG_GUEST_IDTR: 179366f6083SPeter Grehan *base = VMCS_GUEST_IDTR_BASE; 180366f6083SPeter Grehan *lim = VMCS_GUEST_IDTR_LIMIT; 181366f6083SPeter Grehan *acc = VMCS_INVALID_ENCODING; 182366f6083SPeter Grehan break; 183366f6083SPeter Grehan case VM_REG_GUEST_GDTR: 184366f6083SPeter Grehan *base = VMCS_GUEST_GDTR_BASE; 185366f6083SPeter Grehan *lim = VMCS_GUEST_GDTR_LIMIT; 186366f6083SPeter Grehan *acc = VMCS_INVALID_ENCODING; 187366f6083SPeter Grehan break; 188366f6083SPeter Grehan default: 189366f6083SPeter Grehan return (EINVAL); 190366f6083SPeter Grehan } 191366f6083SPeter Grehan 192366f6083SPeter Grehan return (0); 193366f6083SPeter Grehan } 194366f6083SPeter Grehan 195366f6083SPeter Grehan int 196d3c11f40SPeter Grehan vmcs_getreg(struct vmcs *vmcs, int running, int ident, uint64_t *retval) 197366f6083SPeter Grehan { 198366f6083SPeter Grehan int error; 199366f6083SPeter Grehan uint32_t encoding; 200366f6083SPeter Grehan 201366f6083SPeter Grehan /* 202366f6083SPeter Grehan * If we need to get at vmx-specific state in the VMCS we can bypass 203366f6083SPeter Grehan * the translation of 'ident' to 'encoding' by simply setting the 204366f6083SPeter Grehan * sign bit. As it so happens the upper 16 bits are reserved (i.e 205366f6083SPeter Grehan * set to 0) in the encodings for the VMCS so we are free to use the 206366f6083SPeter Grehan * sign bit. 207366f6083SPeter Grehan */ 208366f6083SPeter Grehan if (ident < 0) 209366f6083SPeter Grehan encoding = ident & 0x7fffffff; 210366f6083SPeter Grehan else 211366f6083SPeter Grehan encoding = vmcs_field_encoding(ident); 212366f6083SPeter Grehan 213366f6083SPeter Grehan if (encoding == (uint32_t)-1) 214366f6083SPeter Grehan return (EINVAL); 215366f6083SPeter Grehan 216d3c11f40SPeter Grehan if (!running) 217366f6083SPeter Grehan VMPTRLD(vmcs); 218d3c11f40SPeter Grehan 219366f6083SPeter Grehan error = vmread(encoding, retval); 220d3c11f40SPeter Grehan 221d3c11f40SPeter Grehan if (!running) 222366f6083SPeter Grehan VMCLEAR(vmcs); 223d3c11f40SPeter Grehan 224366f6083SPeter Grehan return (error); 225366f6083SPeter Grehan } 226366f6083SPeter Grehan 227366f6083SPeter Grehan int 228d3c11f40SPeter Grehan vmcs_setreg(struct vmcs *vmcs, int running, int ident, uint64_t val) 229366f6083SPeter Grehan { 230366f6083SPeter Grehan int error; 231366f6083SPeter Grehan uint32_t encoding; 232366f6083SPeter Grehan 233366f6083SPeter Grehan if (ident < 0) 234366f6083SPeter Grehan encoding = ident & 0x7fffffff; 235366f6083SPeter Grehan else 236366f6083SPeter Grehan encoding = vmcs_field_encoding(ident); 237366f6083SPeter Grehan 238366f6083SPeter Grehan if (encoding == (uint32_t)-1) 239366f6083SPeter Grehan return (EINVAL); 240366f6083SPeter Grehan 241366f6083SPeter Grehan val = vmcs_fix_regval(encoding, val); 242366f6083SPeter Grehan 243d3c11f40SPeter Grehan if (!running) 244366f6083SPeter Grehan VMPTRLD(vmcs); 245d3c11f40SPeter Grehan 246366f6083SPeter Grehan error = vmwrite(encoding, val); 247d3c11f40SPeter Grehan 248d3c11f40SPeter Grehan if (!running) 249366f6083SPeter Grehan VMCLEAR(vmcs); 250d3c11f40SPeter Grehan 251366f6083SPeter Grehan return (error); 252366f6083SPeter Grehan } 253366f6083SPeter Grehan 254366f6083SPeter Grehan int 255ba6f5e23SNeel Natu vmcs_setdesc(struct vmcs *vmcs, int running, int seg, struct seg_desc *desc) 256366f6083SPeter Grehan { 257366f6083SPeter Grehan int error; 258366f6083SPeter Grehan uint32_t base, limit, access; 259366f6083SPeter Grehan 260366f6083SPeter Grehan error = vmcs_seg_desc_encoding(seg, &base, &limit, &access); 261366f6083SPeter Grehan if (error != 0) 262366f6083SPeter Grehan panic("vmcs_setdesc: invalid segment register %d", seg); 263366f6083SPeter Grehan 264ba6f5e23SNeel Natu if (!running) 265366f6083SPeter Grehan VMPTRLD(vmcs); 266366f6083SPeter Grehan if ((error = vmwrite(base, desc->base)) != 0) 267366f6083SPeter Grehan goto done; 268366f6083SPeter Grehan 269366f6083SPeter Grehan if ((error = vmwrite(limit, desc->limit)) != 0) 270366f6083SPeter Grehan goto done; 271366f6083SPeter Grehan 272366f6083SPeter Grehan if (access != VMCS_INVALID_ENCODING) { 273366f6083SPeter Grehan if ((error = vmwrite(access, desc->access)) != 0) 274366f6083SPeter Grehan goto done; 275366f6083SPeter Grehan } 276366f6083SPeter Grehan done: 277ba6f5e23SNeel Natu if (!running) 278366f6083SPeter Grehan VMCLEAR(vmcs); 279366f6083SPeter Grehan return (error); 280366f6083SPeter Grehan } 281366f6083SPeter Grehan 282366f6083SPeter Grehan int 283ba6f5e23SNeel Natu vmcs_getdesc(struct vmcs *vmcs, int running, int seg, struct seg_desc *desc) 284366f6083SPeter Grehan { 285366f6083SPeter Grehan int error; 286366f6083SPeter Grehan uint32_t base, limit, access; 287366f6083SPeter Grehan uint64_t u64; 288366f6083SPeter Grehan 289366f6083SPeter Grehan error = vmcs_seg_desc_encoding(seg, &base, &limit, &access); 290366f6083SPeter Grehan if (error != 0) 291366f6083SPeter Grehan panic("vmcs_getdesc: invalid segment register %d", seg); 292366f6083SPeter Grehan 293ba6f5e23SNeel Natu if (!running) 294366f6083SPeter Grehan VMPTRLD(vmcs); 295366f6083SPeter Grehan if ((error = vmread(base, &u64)) != 0) 296366f6083SPeter Grehan goto done; 297366f6083SPeter Grehan desc->base = u64; 298366f6083SPeter Grehan 299366f6083SPeter Grehan if ((error = vmread(limit, &u64)) != 0) 300366f6083SPeter Grehan goto done; 301366f6083SPeter Grehan desc->limit = u64; 302366f6083SPeter Grehan 303366f6083SPeter Grehan if (access != VMCS_INVALID_ENCODING) { 304366f6083SPeter Grehan if ((error = vmread(access, &u64)) != 0) 305366f6083SPeter Grehan goto done; 306366f6083SPeter Grehan desc->access = u64; 307366f6083SPeter Grehan } 308366f6083SPeter Grehan done: 309ba6f5e23SNeel Natu if (!running) 310366f6083SPeter Grehan VMCLEAR(vmcs); 311366f6083SPeter Grehan return (error); 312366f6083SPeter Grehan } 313366f6083SPeter Grehan 314366f6083SPeter Grehan int 315366f6083SPeter Grehan vmcs_set_msr_save(struct vmcs *vmcs, u_long g_area, u_int g_count) 316366f6083SPeter Grehan { 317366f6083SPeter Grehan int error; 318366f6083SPeter Grehan 319366f6083SPeter Grehan VMPTRLD(vmcs); 320366f6083SPeter Grehan 321366f6083SPeter Grehan /* 322366f6083SPeter Grehan * Guest MSRs are saved in the VM-exit MSR-store area. 323366f6083SPeter Grehan * Guest MSRs are loaded from the VM-entry MSR-load area. 324366f6083SPeter Grehan * Both areas point to the same location in memory. 325366f6083SPeter Grehan */ 326366f6083SPeter Grehan if ((error = vmwrite(VMCS_EXIT_MSR_STORE, g_area)) != 0) 327366f6083SPeter Grehan goto done; 328366f6083SPeter Grehan if ((error = vmwrite(VMCS_EXIT_MSR_STORE_COUNT, g_count)) != 0) 329366f6083SPeter Grehan goto done; 330366f6083SPeter Grehan 331366f6083SPeter Grehan if ((error = vmwrite(VMCS_ENTRY_MSR_LOAD, g_area)) != 0) 332366f6083SPeter Grehan goto done; 333366f6083SPeter Grehan if ((error = vmwrite(VMCS_ENTRY_MSR_LOAD_COUNT, g_count)) != 0) 334366f6083SPeter Grehan goto done; 335366f6083SPeter Grehan 336366f6083SPeter Grehan error = 0; 337366f6083SPeter Grehan done: 338366f6083SPeter Grehan VMCLEAR(vmcs); 339366f6083SPeter Grehan return (error); 340366f6083SPeter Grehan } 341366f6083SPeter Grehan 342366f6083SPeter Grehan int 343c847a506SNeel Natu vmcs_init(struct vmcs *vmcs) 344366f6083SPeter Grehan { 345366f6083SPeter Grehan int error, codesel, datasel, tsssel; 346366f6083SPeter Grehan u_long cr0, cr4, efer; 347318224bbSNeel Natu uint64_t pat, fsbase, idtrbase; 348366f6083SPeter Grehan 349b01c2033SNeel Natu codesel = vmm_get_host_codesel(); 350b01c2033SNeel Natu datasel = vmm_get_host_datasel(); 351b01c2033SNeel Natu tsssel = vmm_get_host_tsssel(); 352366f6083SPeter Grehan 353366f6083SPeter Grehan /* 354366f6083SPeter Grehan * Make sure we have a "current" VMCS to work with. 355366f6083SPeter Grehan */ 356366f6083SPeter Grehan VMPTRLD(vmcs); 357366f6083SPeter Grehan 358366f6083SPeter Grehan /* Host state */ 359366f6083SPeter Grehan 360366f6083SPeter Grehan /* Initialize host IA32_PAT MSR */ 361b01c2033SNeel Natu pat = vmm_get_host_pat(); 362366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_IA32_PAT, pat)) != 0) 363366f6083SPeter Grehan goto done; 364366f6083SPeter Grehan 365366f6083SPeter Grehan /* Load the IA32_EFER MSR */ 366b01c2033SNeel Natu efer = vmm_get_host_efer(); 367366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_IA32_EFER, efer)) != 0) 368366f6083SPeter Grehan goto done; 369366f6083SPeter Grehan 370366f6083SPeter Grehan /* Load the control registers */ 371bd8572e0SNeel Natu 372b01c2033SNeel Natu cr0 = vmm_get_host_cr0(); 373366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_CR0, cr0)) != 0) 374366f6083SPeter Grehan goto done; 375366f6083SPeter Grehan 376b01c2033SNeel Natu cr4 = vmm_get_host_cr4() | CR4_VMXE; 377366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_CR4, cr4)) != 0) 378366f6083SPeter Grehan goto done; 379366f6083SPeter Grehan 380366f6083SPeter Grehan /* Load the segment selectors */ 381366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_ES_SELECTOR, datasel)) != 0) 382366f6083SPeter Grehan goto done; 383366f6083SPeter Grehan 384366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_CS_SELECTOR, codesel)) != 0) 385366f6083SPeter Grehan goto done; 386366f6083SPeter Grehan 387366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_SS_SELECTOR, datasel)) != 0) 388366f6083SPeter Grehan goto done; 389366f6083SPeter Grehan 390366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_DS_SELECTOR, datasel)) != 0) 391366f6083SPeter Grehan goto done; 392366f6083SPeter Grehan 393366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_FS_SELECTOR, datasel)) != 0) 394366f6083SPeter Grehan goto done; 395366f6083SPeter Grehan 396366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_GS_SELECTOR, datasel)) != 0) 397366f6083SPeter Grehan goto done; 398366f6083SPeter Grehan 399366f6083SPeter Grehan if ((error = vmwrite(VMCS_HOST_TR_SELECTOR, tsssel)) != 0) 400366f6083SPeter Grehan goto done; 401366f6083SPeter Grehan 402366f6083SPeter Grehan /* 403366f6083SPeter Grehan * Load the Base-Address for %fs and idtr. 404366f6083SPeter Grehan * 405366f6083SPeter Grehan * Note that we exclude %gs, tss and gdtr here because their base 406366f6083SPeter Grehan * address is pcpu specific. 407366f6083SPeter Grehan */ 408b01c2033SNeel Natu fsbase = vmm_get_host_fsbase(); 409b01c2033SNeel Natu if ((error = vmwrite(VMCS_HOST_FS_BASE, fsbase)) != 0) 410366f6083SPeter Grehan goto done; 411366f6083SPeter Grehan 412b01c2033SNeel Natu idtrbase = vmm_get_host_idtrbase(); 413b01c2033SNeel Natu if ((error = vmwrite(VMCS_HOST_IDTR_BASE, idtrbase)) != 0) 414366f6083SPeter Grehan goto done; 415366f6083SPeter Grehan 416366f6083SPeter Grehan /* instruction pointer */ 41758a6aaf7STycho Nightingale if (no_flush_rsb) { 41858a6aaf7STycho Nightingale if ((error = vmwrite(VMCS_HOST_RIP, 41958a6aaf7STycho Nightingale (u_long)vmx_exit_guest)) != 0) 420366f6083SPeter Grehan goto done; 42158a6aaf7STycho Nightingale } else { 42258a6aaf7STycho Nightingale if ((error = vmwrite(VMCS_HOST_RIP, 42358a6aaf7STycho Nightingale (u_long)vmx_exit_guest_flush_rsb)) != 0) 42458a6aaf7STycho Nightingale goto done; 42558a6aaf7STycho Nightingale } 426366f6083SPeter Grehan 427366f6083SPeter Grehan /* link pointer */ 428366f6083SPeter Grehan if ((error = vmwrite(VMCS_LINK_POINTER, ~0)) != 0) 429366f6083SPeter Grehan goto done; 430366f6083SPeter Grehan done: 431366f6083SPeter Grehan VMCLEAR(vmcs); 432366f6083SPeter Grehan return (error); 433366f6083SPeter Grehan } 434366f6083SPeter Grehan 435*483d953aSJohn Baldwin #ifdef BHYVE_SNAPSHOT 436*483d953aSJohn Baldwin int 437*483d953aSJohn Baldwin vmcs_getany(struct vmcs *vmcs, int running, int ident, uint64_t *val) 438*483d953aSJohn Baldwin { 439*483d953aSJohn Baldwin int error; 440*483d953aSJohn Baldwin 441*483d953aSJohn Baldwin if (!running) 442*483d953aSJohn Baldwin VMPTRLD(vmcs); 443*483d953aSJohn Baldwin 444*483d953aSJohn Baldwin error = vmread(ident, val); 445*483d953aSJohn Baldwin 446*483d953aSJohn Baldwin if (!running) 447*483d953aSJohn Baldwin VMCLEAR(vmcs); 448*483d953aSJohn Baldwin 449*483d953aSJohn Baldwin return (error); 450*483d953aSJohn Baldwin } 451*483d953aSJohn Baldwin 452*483d953aSJohn Baldwin int 453*483d953aSJohn Baldwin vmcs_setany(struct vmcs *vmcs, int running, int ident, uint64_t val) 454*483d953aSJohn Baldwin { 455*483d953aSJohn Baldwin int error; 456*483d953aSJohn Baldwin 457*483d953aSJohn Baldwin if (!running) 458*483d953aSJohn Baldwin VMPTRLD(vmcs); 459*483d953aSJohn Baldwin 460*483d953aSJohn Baldwin error = vmwrite(ident, val); 461*483d953aSJohn Baldwin 462*483d953aSJohn Baldwin if (!running) 463*483d953aSJohn Baldwin VMCLEAR(vmcs); 464*483d953aSJohn Baldwin 465*483d953aSJohn Baldwin return (error); 466*483d953aSJohn Baldwin } 467*483d953aSJohn Baldwin 468*483d953aSJohn Baldwin int 469*483d953aSJohn Baldwin vmcs_snapshot_reg(struct vmcs *vmcs, int running, int ident, 470*483d953aSJohn Baldwin struct vm_snapshot_meta *meta) 471*483d953aSJohn Baldwin { 472*483d953aSJohn Baldwin int ret; 473*483d953aSJohn Baldwin uint64_t val; 474*483d953aSJohn Baldwin 475*483d953aSJohn Baldwin if (meta->op == VM_SNAPSHOT_SAVE) { 476*483d953aSJohn Baldwin ret = vmcs_getreg(vmcs, running, ident, &val); 477*483d953aSJohn Baldwin if (ret != 0) 478*483d953aSJohn Baldwin goto done; 479*483d953aSJohn Baldwin 480*483d953aSJohn Baldwin SNAPSHOT_VAR_OR_LEAVE(val, meta, ret, done); 481*483d953aSJohn Baldwin } else if (meta->op == VM_SNAPSHOT_RESTORE) { 482*483d953aSJohn Baldwin SNAPSHOT_VAR_OR_LEAVE(val, meta, ret, done); 483*483d953aSJohn Baldwin 484*483d953aSJohn Baldwin ret = vmcs_setreg(vmcs, running, ident, val); 485*483d953aSJohn Baldwin if (ret != 0) 486*483d953aSJohn Baldwin goto done; 487*483d953aSJohn Baldwin } else { 488*483d953aSJohn Baldwin ret = EINVAL; 489*483d953aSJohn Baldwin goto done; 490*483d953aSJohn Baldwin } 491*483d953aSJohn Baldwin 492*483d953aSJohn Baldwin done: 493*483d953aSJohn Baldwin return (ret); 494*483d953aSJohn Baldwin } 495*483d953aSJohn Baldwin 496*483d953aSJohn Baldwin int 497*483d953aSJohn Baldwin vmcs_snapshot_desc(struct vmcs *vmcs, int running, int seg, 498*483d953aSJohn Baldwin struct vm_snapshot_meta *meta) 499*483d953aSJohn Baldwin { 500*483d953aSJohn Baldwin int ret; 501*483d953aSJohn Baldwin struct seg_desc desc; 502*483d953aSJohn Baldwin 503*483d953aSJohn Baldwin if (meta->op == VM_SNAPSHOT_SAVE) { 504*483d953aSJohn Baldwin ret = vmcs_getdesc(vmcs, running, seg, &desc); 505*483d953aSJohn Baldwin if (ret != 0) 506*483d953aSJohn Baldwin goto done; 507*483d953aSJohn Baldwin 508*483d953aSJohn Baldwin SNAPSHOT_VAR_OR_LEAVE(desc.base, meta, ret, done); 509*483d953aSJohn Baldwin SNAPSHOT_VAR_OR_LEAVE(desc.limit, meta, ret, done); 510*483d953aSJohn Baldwin SNAPSHOT_VAR_OR_LEAVE(desc.access, meta, ret, done); 511*483d953aSJohn Baldwin } else if (meta->op == VM_SNAPSHOT_RESTORE) { 512*483d953aSJohn Baldwin SNAPSHOT_VAR_OR_LEAVE(desc.base, meta, ret, done); 513*483d953aSJohn Baldwin SNAPSHOT_VAR_OR_LEAVE(desc.limit, meta, ret, done); 514*483d953aSJohn Baldwin SNAPSHOT_VAR_OR_LEAVE(desc.access, meta, ret, done); 515*483d953aSJohn Baldwin 516*483d953aSJohn Baldwin ret = vmcs_setdesc(vmcs, running, seg, &desc); 517*483d953aSJohn Baldwin if (ret != 0) 518*483d953aSJohn Baldwin goto done; 519*483d953aSJohn Baldwin } else { 520*483d953aSJohn Baldwin ret = EINVAL; 521*483d953aSJohn Baldwin goto done; 522*483d953aSJohn Baldwin } 523*483d953aSJohn Baldwin 524*483d953aSJohn Baldwin done: 525*483d953aSJohn Baldwin return (ret); 526*483d953aSJohn Baldwin } 527*483d953aSJohn Baldwin 528*483d953aSJohn Baldwin int 529*483d953aSJohn Baldwin vmcs_snapshot_any(struct vmcs *vmcs, int running, int ident, 530*483d953aSJohn Baldwin struct vm_snapshot_meta *meta) 531*483d953aSJohn Baldwin { 532*483d953aSJohn Baldwin int ret; 533*483d953aSJohn Baldwin uint64_t val; 534*483d953aSJohn Baldwin 535*483d953aSJohn Baldwin if (meta->op == VM_SNAPSHOT_SAVE) { 536*483d953aSJohn Baldwin ret = vmcs_getany(vmcs, running, ident, &val); 537*483d953aSJohn Baldwin if (ret != 0) 538*483d953aSJohn Baldwin goto done; 539*483d953aSJohn Baldwin 540*483d953aSJohn Baldwin SNAPSHOT_VAR_OR_LEAVE(val, meta, ret, done); 541*483d953aSJohn Baldwin } else if (meta->op == VM_SNAPSHOT_RESTORE) { 542*483d953aSJohn Baldwin SNAPSHOT_VAR_OR_LEAVE(val, meta, ret, done); 543*483d953aSJohn Baldwin 544*483d953aSJohn Baldwin ret = vmcs_setany(vmcs, running, ident, val); 545*483d953aSJohn Baldwin if (ret != 0) 546*483d953aSJohn Baldwin goto done; 547*483d953aSJohn Baldwin } else { 548*483d953aSJohn Baldwin ret = EINVAL; 549*483d953aSJohn Baldwin goto done; 550*483d953aSJohn Baldwin } 551*483d953aSJohn Baldwin 552*483d953aSJohn Baldwin done: 553*483d953aSJohn Baldwin return (ret); 554*483d953aSJohn Baldwin } 555*483d953aSJohn Baldwin #endif 556*483d953aSJohn Baldwin 557b3996dd4SJohn Baldwin #ifdef DDB 558b3996dd4SJohn Baldwin extern int vmxon_enabled[]; 559b3996dd4SJohn Baldwin 560b3996dd4SJohn Baldwin DB_SHOW_COMMAND(vmcs, db_show_vmcs) 561b3996dd4SJohn Baldwin { 562b3996dd4SJohn Baldwin uint64_t cur_vmcs, val; 563b3996dd4SJohn Baldwin uint32_t exit; 564b3996dd4SJohn Baldwin 565b3996dd4SJohn Baldwin if (!vmxon_enabled[curcpu]) { 566b3996dd4SJohn Baldwin db_printf("VMX not enabled\n"); 567b3996dd4SJohn Baldwin return; 568b3996dd4SJohn Baldwin } 569b3996dd4SJohn Baldwin 570b3996dd4SJohn Baldwin if (have_addr) { 571b3996dd4SJohn Baldwin db_printf("Only current VMCS supported\n"); 572b3996dd4SJohn Baldwin return; 573b3996dd4SJohn Baldwin } 574b3996dd4SJohn Baldwin 575b3996dd4SJohn Baldwin vmptrst(&cur_vmcs); 576b3996dd4SJohn Baldwin if (cur_vmcs == VMCS_INITIAL) { 577b3996dd4SJohn Baldwin db_printf("No current VM context\n"); 578b3996dd4SJohn Baldwin return; 579b3996dd4SJohn Baldwin } 580b3996dd4SJohn Baldwin db_printf("VMCS: %jx\n", cur_vmcs); 581b3996dd4SJohn Baldwin db_printf("VPID: %lu\n", vmcs_read(VMCS_VPID)); 582b3996dd4SJohn Baldwin db_printf("Activity: "); 583b3996dd4SJohn Baldwin val = vmcs_read(VMCS_GUEST_ACTIVITY); 584b3996dd4SJohn Baldwin switch (val) { 585b3996dd4SJohn Baldwin case 0: 586b3996dd4SJohn Baldwin db_printf("Active"); 587b3996dd4SJohn Baldwin break; 588b3996dd4SJohn Baldwin case 1: 589b3996dd4SJohn Baldwin db_printf("HLT"); 590b3996dd4SJohn Baldwin break; 591b3996dd4SJohn Baldwin case 2: 592b3996dd4SJohn Baldwin db_printf("Shutdown"); 593b3996dd4SJohn Baldwin break; 594b3996dd4SJohn Baldwin case 3: 595b3996dd4SJohn Baldwin db_printf("Wait for SIPI"); 596b3996dd4SJohn Baldwin break; 597b3996dd4SJohn Baldwin default: 598b3996dd4SJohn Baldwin db_printf("Unknown: %#lx", val); 599b3996dd4SJohn Baldwin } 600b3996dd4SJohn Baldwin db_printf("\n"); 601b3996dd4SJohn Baldwin exit = vmcs_read(VMCS_EXIT_REASON); 602b3996dd4SJohn Baldwin if (exit & 0x80000000) 603b3996dd4SJohn Baldwin db_printf("Entry Failure Reason: %u\n", exit & 0xffff); 604b3996dd4SJohn Baldwin else 605b3996dd4SJohn Baldwin db_printf("Exit Reason: %u\n", exit & 0xffff); 606b3996dd4SJohn Baldwin db_printf("Qualification: %#lx\n", vmcs_exit_qualification()); 607b3996dd4SJohn Baldwin db_printf("Guest Linear Address: %#lx\n", 608b3996dd4SJohn Baldwin vmcs_read(VMCS_GUEST_LINEAR_ADDRESS)); 609b3996dd4SJohn Baldwin switch (exit & 0x8000ffff) { 610b3996dd4SJohn Baldwin case EXIT_REASON_EXCEPTION: 611b3996dd4SJohn Baldwin case EXIT_REASON_EXT_INTR: 612f7d47425SNeel Natu val = vmcs_read(VMCS_EXIT_INTR_INFO); 613b3996dd4SJohn Baldwin db_printf("Interrupt Type: "); 614b3996dd4SJohn Baldwin switch (val >> 8 & 0x7) { 615b3996dd4SJohn Baldwin case 0: 616b3996dd4SJohn Baldwin db_printf("external"); 617b3996dd4SJohn Baldwin break; 618b3996dd4SJohn Baldwin case 2: 619b3996dd4SJohn Baldwin db_printf("NMI"); 620b3996dd4SJohn Baldwin break; 621b3996dd4SJohn Baldwin case 3: 622b3996dd4SJohn Baldwin db_printf("HW exception"); 623b3996dd4SJohn Baldwin break; 624b3996dd4SJohn Baldwin case 4: 625b3996dd4SJohn Baldwin db_printf("SW exception"); 626b3996dd4SJohn Baldwin break; 627b3996dd4SJohn Baldwin default: 628b3996dd4SJohn Baldwin db_printf("?? %lu", val >> 8 & 0x7); 629b3996dd4SJohn Baldwin break; 630b3996dd4SJohn Baldwin } 631b3996dd4SJohn Baldwin db_printf(" Vector: %lu", val & 0xff); 632b3996dd4SJohn Baldwin if (val & 0x800) 633b3996dd4SJohn Baldwin db_printf(" Error Code: %lx", 634f7d47425SNeel Natu vmcs_read(VMCS_EXIT_INTR_ERRCODE)); 635b3996dd4SJohn Baldwin db_printf("\n"); 636b3996dd4SJohn Baldwin break; 637b3996dd4SJohn Baldwin case EXIT_REASON_EPT_FAULT: 638b3996dd4SJohn Baldwin case EXIT_REASON_EPT_MISCONFIG: 639b3996dd4SJohn Baldwin db_printf("Guest Physical Address: %#lx\n", 640b3996dd4SJohn Baldwin vmcs_read(VMCS_GUEST_PHYSICAL_ADDRESS)); 641b3996dd4SJohn Baldwin break; 642b3996dd4SJohn Baldwin } 643b3996dd4SJohn Baldwin db_printf("VM-instruction error: %#lx\n", vmcs_instruction_error()); 644b3996dd4SJohn Baldwin } 645b3996dd4SJohn Baldwin #endif 646