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 * 26245678Sneel * $FreeBSD: stable/11/sys/amd64/include/vmm.h 351753 2019-09-03 16:23:46Z emaste $ 27221828Sgrehan */ 28221828Sgrehan 29221828Sgrehan#ifndef _VMM_H_ 30221828Sgrehan#define _VMM_H_ 31221828Sgrehan 32347416Sjhb#include <sys/sdt.h> 33269042Sneel#include <x86/segments.h> 34269042Sneel 35347416Sjhb#ifdef _KERNEL 36347416SjhbSDT_PROVIDER_DECLARE(vmm); 37347416Sjhb#endif 38347416Sjhb 39265062Sneelenum vm_suspend_how { 40265062Sneel VM_SUSPEND_NONE, 41265062Sneel VM_SUSPEND_RESET, 42265062Sneel VM_SUSPEND_POWEROFF, 43265203Sneel VM_SUSPEND_HALT, 44268889Sneel VM_SUSPEND_TRIPLEFAULT, 45265062Sneel VM_SUSPEND_LAST 46265062Sneel}; 47265062Sneel 48267338Stychon/* 49267338Stychon * Identifiers for architecturally defined registers. 50267338Stychon */ 51267338Stychonenum vm_reg_name { 52267338Stychon VM_REG_GUEST_RAX, 53267338Stychon VM_REG_GUEST_RBX, 54267338Stychon VM_REG_GUEST_RCX, 55267338Stychon VM_REG_GUEST_RDX, 56267338Stychon VM_REG_GUEST_RSI, 57267338Stychon VM_REG_GUEST_RDI, 58267338Stychon VM_REG_GUEST_RBP, 59267338Stychon VM_REG_GUEST_R8, 60267338Stychon VM_REG_GUEST_R9, 61267338Stychon VM_REG_GUEST_R10, 62267338Stychon VM_REG_GUEST_R11, 63267338Stychon VM_REG_GUEST_R12, 64267338Stychon VM_REG_GUEST_R13, 65267338Stychon VM_REG_GUEST_R14, 66267338Stychon VM_REG_GUEST_R15, 67267338Stychon VM_REG_GUEST_CR0, 68267338Stychon VM_REG_GUEST_CR3, 69267338Stychon VM_REG_GUEST_CR4, 70267338Stychon VM_REG_GUEST_DR7, 71267338Stychon VM_REG_GUEST_RSP, 72267338Stychon VM_REG_GUEST_RIP, 73267338Stychon VM_REG_GUEST_RFLAGS, 74267338Stychon VM_REG_GUEST_ES, 75267338Stychon VM_REG_GUEST_CS, 76267338Stychon VM_REG_GUEST_SS, 77267338Stychon VM_REG_GUEST_DS, 78267338Stychon VM_REG_GUEST_FS, 79267338Stychon VM_REG_GUEST_GS, 80267338Stychon VM_REG_GUEST_LDTR, 81267338Stychon VM_REG_GUEST_TR, 82267338Stychon VM_REG_GUEST_IDTR, 83267338Stychon VM_REG_GUEST_GDTR, 84267338Stychon VM_REG_GUEST_EFER, 85267338Stychon VM_REG_GUEST_CR2, 86268777Sneel VM_REG_GUEST_PDPTE0, 87268777Sneel VM_REG_GUEST_PDPTE1, 88268777Sneel VM_REG_GUEST_PDPTE2, 89268777Sneel VM_REG_GUEST_PDPTE3, 90271451Sneel VM_REG_GUEST_INTR_SHADOW, 91330623Sjhb VM_REG_GUEST_DR0, 92330623Sjhb VM_REG_GUEST_DR1, 93330623Sjhb VM_REG_GUEST_DR2, 94330623Sjhb VM_REG_GUEST_DR3, 95330623Sjhb VM_REG_GUEST_DR6, 96267338Stychon VM_REG_LAST 97267338Stychon}; 98267338Stychon 99267338Stychonenum x2apic_state { 100267338Stychon X2APIC_DISABLED, 101267338Stychon X2APIC_ENABLED, 102267338Stychon X2APIC_STATE_LAST 103267338Stychon}; 104267338Stychon 105268889Sneel#define VM_INTINFO_VECTOR(info) ((info) & 0xff) 106268889Sneel#define VM_INTINFO_DEL_ERRCODE 0x800 107268889Sneel#define VM_INTINFO_RSVD 0x7ffff000 108268889Sneel#define VM_INTINFO_VALID 0x80000000 109268889Sneel#define VM_INTINFO_TYPE 0x700 110268889Sneel#define VM_INTINFO_HWINTR (0 << 8) 111268889Sneel#define VM_INTINFO_NMI (2 << 8) 112268889Sneel#define VM_INTINFO_HWEXCEPTION (3 << 8) 113268889Sneel#define VM_INTINFO_SWINTR (4 << 8) 114268889Sneel 115221828Sgrehan#ifdef _KERNEL 116221828Sgrehan 117221828Sgrehan#define VM_MAX_NAMELEN 32 118221828Sgrehan 119221828Sgrehanstruct vm; 120262506Sneelstruct vm_exception; 121221828Sgrehanstruct seg_desc; 122221828Sgrehanstruct vm_exit; 123221828Sgrehanstruct vm_run; 124258579Sneelstruct vhpet; 125258075Sneelstruct vioapic; 126221828Sgrehanstruct vlapic; 127256072Sneelstruct vmspace; 128256072Sneelstruct vm_object; 129269008Sneelstruct vm_guest_paging; 130256072Sneelstruct pmap; 131221828Sgrehan 132283657Sneelstruct vm_eventinfo { 133283657Sneel void *rptr; /* rendezvous cookie */ 134283657Sneel int *sptr; /* suspend cookie */ 135283657Sneel int *iptr; /* reqidle cookie */ 136283657Sneel}; 137283657Sneel 138260466Sneeltypedef int (*vmm_init_func_t)(int ipinum); 139221828Sgrehantypedef int (*vmm_cleanup_func_t)(void); 140259782Sjhbtypedef void (*vmm_resume_func_t)(void); 141256072Sneeltypedef void * (*vmi_init_func_t)(struct vm *vm, struct pmap *pmap); 142256072Sneeltypedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip, 143283657Sneel struct pmap *pmap, struct vm_eventinfo *info); 144221828Sgrehantypedef void (*vmi_cleanup_func_t)(void *vmi); 145221828Sgrehantypedef int (*vmi_get_register_t)(void *vmi, int vcpu, int num, 146221828Sgrehan uint64_t *retval); 147221828Sgrehantypedef int (*vmi_set_register_t)(void *vmi, int vcpu, int num, 148221828Sgrehan uint64_t val); 149221828Sgrehantypedef int (*vmi_get_desc_t)(void *vmi, int vcpu, int num, 150221828Sgrehan struct seg_desc *desc); 151221828Sgrehantypedef int (*vmi_set_desc_t)(void *vmi, int vcpu, int num, 152221828Sgrehan struct seg_desc *desc); 153221828Sgrehantypedef int (*vmi_get_cap_t)(void *vmi, int vcpu, int num, int *retval); 154221828Sgrehantypedef int (*vmi_set_cap_t)(void *vmi, int vcpu, int num, int val); 155256072Sneeltypedef struct vmspace * (*vmi_vmspace_alloc)(vm_offset_t min, vm_offset_t max); 156256072Sneeltypedef void (*vmi_vmspace_free)(struct vmspace *vmspace); 157259863Sneeltypedef struct vlapic * (*vmi_vlapic_init)(void *vmi, int vcpu); 158259863Sneeltypedef void (*vmi_vlapic_cleanup)(void *vmi, struct vlapic *vlapic); 159221828Sgrehan 160221828Sgrehanstruct vmm_ops { 161221828Sgrehan vmm_init_func_t init; /* module wide initialization */ 162221828Sgrehan vmm_cleanup_func_t cleanup; 163259782Sjhb vmm_resume_func_t resume; 164221828Sgrehan 165221828Sgrehan vmi_init_func_t vminit; /* vm-specific initialization */ 166221828Sgrehan vmi_run_func_t vmrun; 167221828Sgrehan vmi_cleanup_func_t vmcleanup; 168221828Sgrehan vmi_get_register_t vmgetreg; 169221828Sgrehan vmi_set_register_t vmsetreg; 170221828Sgrehan vmi_get_desc_t vmgetdesc; 171221828Sgrehan vmi_set_desc_t vmsetdesc; 172221828Sgrehan vmi_get_cap_t vmgetcap; 173221828Sgrehan vmi_set_cap_t vmsetcap; 174256072Sneel vmi_vmspace_alloc vmspace_alloc; 175256072Sneel vmi_vmspace_free vmspace_free; 176259863Sneel vmi_vlapic_init vlapic_init; 177259863Sneel vmi_vlapic_cleanup vlapic_cleanup; 178221828Sgrehan}; 179221828Sgrehan 180221828Sgrehanextern struct vmm_ops vmm_ops_intel; 181221828Sgrehanextern struct vmm_ops vmm_ops_amd; 182221828Sgrehan 183249396Sneelint vm_create(const char *name, struct vm **retvm); 184221828Sgrehanvoid vm_destroy(struct vm *vm); 185267216Sneelint vm_reinit(struct vm *vm); 186221828Sgrehanconst char *vm_name(struct vm *vm); 187348271Srgrimesuint16_t vm_get_maxcpus(struct vm *vm); 188348201Srgrimesvoid vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores, 189348201Srgrimes uint16_t *threads, uint16_t *maxcpus); 190348201Srgrimesint vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores, 191348201Srgrimes uint16_t threads, uint16_t maxcpus); 192284539Sneel 193284539Sneel/* 194284539Sneel * APIs that modify the guest memory map require all vcpus to be frozen. 195284539Sneel */ 196284539Sneelint vm_mmap_memseg(struct vm *vm, vm_paddr_t gpa, int segid, vm_ooffset_t off, 197284539Sneel size_t len, int prot, int flags); 198284539Sneelint vm_alloc_memseg(struct vm *vm, int ident, size_t len, bool sysmem); 199284539Sneelvoid vm_free_memseg(struct vm *vm, int ident); 200221828Sgrehanint vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa); 201221828Sgrehanint vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len); 202284539Sneelint vm_assign_pptdev(struct vm *vm, int bus, int slot, int func); 203284539Sneelint vm_unassign_pptdev(struct vm *vm, int bus, int slot, int func); 204284539Sneel 205284539Sneel/* 206284539Sneel * APIs that inspect the guest memory map require only a *single* vcpu to 207284539Sneel * be frozen. This acts like a read lock on the guest memory map since any 208284539Sneel * modification requires *all* vcpus to be frozen. 209284539Sneel */ 210284539Sneelint vm_mmap_getnext(struct vm *vm, vm_paddr_t *gpa, int *segid, 211284539Sneel vm_ooffset_t *segoff, size_t *len, int *prot, int *flags); 212284539Sneelint vm_get_memseg(struct vm *vm, int ident, size_t *len, bool *sysmem, 213284539Sneel struct vm_object **objptr); 214347409Sjhbvm_paddr_t vmm_sysmem_maxaddr(struct vm *vm); 215284539Sneelvoid *vm_gpa_hold(struct vm *, int vcpuid, vm_paddr_t gpa, size_t len, 216284539Sneel int prot, void **cookie); 217256072Sneelvoid vm_gpa_release(void *cookie); 218284539Sneelbool vm_mem_allocated(struct vm *vm, int vcpuid, vm_paddr_t gpa); 219284539Sneel 220221828Sgrehanint vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval); 221221828Sgrehanint vm_set_register(struct vm *vm, int vcpu, int reg, uint64_t val); 222221828Sgrehanint vm_get_seg_desc(struct vm *vm, int vcpu, int reg, 223221828Sgrehan struct seg_desc *ret_desc); 224221828Sgrehanint vm_set_seg_desc(struct vm *vm, int vcpu, int reg, 225221828Sgrehan struct seg_desc *desc); 226221828Sgrehanint vm_run(struct vm *vm, struct vm_run *vmrun); 227265062Sneelint vm_suspend(struct vm *vm, enum vm_suspend_how how); 228221828Sgrehanint vm_inject_nmi(struct vm *vm, int vcpu); 229241982Sneelint vm_nmi_pending(struct vm *vm, int vcpuid); 230241982Sneelvoid vm_nmi_clear(struct vm *vm, int vcpuid); 231263211Stychonint vm_inject_extint(struct vm *vm, int vcpu); 232263211Stychonint vm_extint_pending(struct vm *vm, int vcpuid); 233263211Stychonvoid vm_extint_clear(struct vm *vm, int vcpuid); 234221828Sgrehanstruct vlapic *vm_lapic(struct vm *vm, int cpu); 235258075Sneelstruct vioapic *vm_ioapic(struct vm *vm); 236258579Sneelstruct vhpet *vm_hpet(struct vm *vm); 237221828Sgrehanint vm_get_capability(struct vm *vm, int vcpu, int type, int *val); 238221828Sgrehanint vm_set_capability(struct vm *vm, int vcpu, int type, int val); 239240922Sneelint vm_get_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state *state); 240240922Sneelint vm_set_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state state); 241258075Sneelint vm_apicid2vcpuid(struct vm *vm, int apicid); 242266933Sneelint vm_activate_cpu(struct vm *vm, int vcpu); 243240894Sneelstruct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid); 244265062Sneelvoid vm_exit_suspended(struct vm *vm, int vcpuid, uint64_t rip); 245267330Sneelvoid vm_exit_rendezvous(struct vm *vm, int vcpuid, uint64_t rip); 246267330Sneelvoid vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip); 247283657Sneelvoid vm_exit_reqidle(struct vm *vm, int vcpuid, uint64_t rip); 248221828Sgrehan 249282287Sneel#ifdef _SYS__CPUSET_H_ 250221828Sgrehan/* 251260619Sneel * Rendezvous all vcpus specified in 'dest' and execute 'func(arg)'. 252260619Sneel * The rendezvous 'func(arg)' is not allowed to do anything that will 253260619Sneel * cause the thread to be put to sleep. 254260619Sneel * 255260619Sneel * If the rendezvous is being initiated from a vcpu context then the 256260619Sneel * 'vcpuid' must refer to that vcpu, otherwise it should be set to -1. 257260619Sneel * 258260619Sneel * The caller cannot hold any locks when initiating the rendezvous. 259260619Sneel * 260260619Sneel * The implementation of this API may cause vcpus other than those specified 261260619Sneel * by 'dest' to be stalled. The caller should not rely on any vcpus making 262260619Sneel * forward progress when the rendezvous is in progress. 263260619Sneel */ 264260619Sneeltypedef void (*vm_rendezvous_func_t)(struct vm *vm, int vcpuid, void *arg); 265260619Sneelvoid vm_smp_rendezvous(struct vm *vm, int vcpuid, cpuset_t dest, 266260619Sneel vm_rendezvous_func_t func, void *arg); 267282287Sneelcpuset_t vm_active_cpus(struct vm *vm); 268282287Sneelcpuset_t vm_suspended_cpus(struct vm *vm); 269282287Sneel#endif /* _SYS__CPUSET_H_ */ 270260619Sneel 271260619Sneelstatic __inline int 272283657Sneelvcpu_rendezvous_pending(struct vm_eventinfo *info) 273260619Sneel{ 274260619Sneel 275283657Sneel return (*((uintptr_t *)(info->rptr)) != 0); 276260619Sneel} 277260619Sneel 278263780Sneelstatic __inline int 279283657Sneelvcpu_suspended(struct vm_eventinfo *info) 280263780Sneel{ 281263780Sneel 282283657Sneel return (*info->sptr); 283263780Sneel} 284263780Sneel 285283657Sneelstatic __inline int 286283657Sneelvcpu_reqidle(struct vm_eventinfo *info) 287283657Sneel{ 288283657Sneel 289283657Sneel return (*info->iptr); 290283657Sneel} 291283657Sneel 292260619Sneel/* 293351753Semaste * Return true if device indicated by bus/slot/func is supposed to be a 294221828Sgrehan * pci passthrough device. 295221828Sgrehan * 296351753Semaste * Return false otherwise. 297221828Sgrehan */ 298351753Semastebool vmm_is_pptdev(int bus, int slot, int func); 299221828Sgrehan 300221828Sgrehanvoid *vm_iommu_domain(struct vm *vm); 301221828Sgrehan 302241489Sneelenum vcpu_state { 303241489Sneel VCPU_IDLE, 304256072Sneel VCPU_FROZEN, 305241489Sneel VCPU_RUNNING, 306256072Sneel VCPU_SLEEPING, 307241489Sneel}; 308221828Sgrehan 309259737Sneelint vcpu_set_state(struct vm *vm, int vcpu, enum vcpu_state state, 310259737Sneel bool from_idle); 311249879Sgrehanenum vcpu_state vcpu_get_state(struct vm *vm, int vcpu, int *hostcpu); 312221828Sgrehan 313221828Sgrehanstatic int __inline 314249879Sgrehanvcpu_is_running(struct vm *vm, int vcpu, int *hostcpu) 315221828Sgrehan{ 316249879Sgrehan return (vcpu_get_state(vm, vcpu, hostcpu) == VCPU_RUNNING); 317221828Sgrehan} 318221828Sgrehan 319269109Sneel#ifdef _SYS_PROC_H_ 320269109Sneelstatic int __inline 321269109Sneelvcpu_should_yield(struct vm *vm, int vcpu) 322269109Sneel{ 323282571Sneel 324282571Sneel if (curthread->td_flags & (TDF_ASTPENDING | TDF_NEEDRESCHED)) 325282571Sneel return (1); 326282571Sneel else if (curthread->td_owepreempt) 327282571Sneel return (1); 328282571Sneel else 329282571Sneel return (0); 330269109Sneel} 331269109Sneel#endif 332269109Sneel 333241489Sneelvoid *vcpu_stats(struct vm *vm, int vcpu); 334259863Sneelvoid vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr); 335256072Sneelstruct vmspace *vm_get_vmspace(struct vm *vm); 336263035Stychonstruct vatpic *vm_atpic(struct vm *vm); 337263744Stychonstruct vatpit *vm_atpit(struct vm *vm); 338273683Sneelstruct vpmtmr *vm_pmtmr(struct vm *vm); 339276428Sneelstruct vrtc *vm_rtc(struct vm *vm); 340262506Sneel 341262506Sneel/* 342277149Sneel * Inject exception 'vector' into the guest vcpu. This function returns 0 on 343262506Sneel * success and non-zero on failure. 344262506Sneel * 345262506Sneel * Wrapper functions like 'vm_inject_gp()' should be preferred to calling 346262506Sneel * this function directly because they enforce the trap-like or fault-like 347262506Sneel * behavior of an exception. 348262506Sneel * 349262506Sneel * This function should only be called in the context of the thread that is 350262506Sneel * executing this vcpu. 351262506Sneel */ 352277149Sneelint vm_inject_exception(struct vm *vm, int vcpuid, int vector, int err_valid, 353277149Sneel uint32_t errcode, int restart_instruction); 354262506Sneel 355262506Sneel/* 356268889Sneel * This function is called after a VM-exit that occurred during exception or 357268889Sneel * interrupt delivery through the IDT. The format of 'intinfo' is described 358268889Sneel * in Figure 15-1, "EXITINTINFO for All Intercepts", APM, Vol 2. 359262506Sneel * 360268889Sneel * If a VM-exit handler completes the event delivery successfully then it 361268889Sneel * should call vm_exit_intinfo() to extinguish the pending event. For e.g., 362268889Sneel * if the task switch emulation is triggered via a task gate then it should 363268889Sneel * call this function with 'intinfo=0' to indicate that the external event 364268889Sneel * is not pending anymore. 365268889Sneel * 366268889Sneel * Return value is 0 on success and non-zero on failure. 367262506Sneel */ 368268889Sneelint vm_exit_intinfo(struct vm *vm, int vcpuid, uint64_t intinfo); 369262506Sneel 370268889Sneel/* 371268889Sneel * This function is called before every VM-entry to retrieve a pending 372268889Sneel * event that should be injected into the guest. This function combines 373268889Sneel * nested events into a double or triple fault. 374268889Sneel * 375268889Sneel * Returns 0 if there are no events that need to be injected into the guest 376268889Sneel * and non-zero otherwise. 377268889Sneel */ 378268889Sneelint vm_entry_intinfo(struct vm *vm, int vcpuid, uint64_t *info); 379268889Sneel 380268889Sneelint vm_get_intinfo(struct vm *vm, int vcpuid, uint64_t *info1, uint64_t *info2); 381268889Sneel 382266573Sneelenum vm_reg_name vm_segment_name(int seg_encoding); 383266573Sneel 384269008Sneelstruct vm_copyinfo { 385269008Sneel uint64_t gpa; 386269008Sneel size_t len; 387269008Sneel void *hva; 388269008Sneel void *cookie; 389269008Sneel}; 390269008Sneel 391269008Sneel/* 392269008Sneel * Set up 'copyinfo[]' to copy to/from guest linear address space starting 393269008Sneel * at 'gla' and 'len' bytes long. The 'prot' should be set to PROT_READ for 394269008Sneel * a copyin or PROT_WRITE for a copyout. 395269008Sneel * 396299010Spfg * retval is_fault Interpretation 397282558Sneel * 0 0 Success 398282558Sneel * 0 1 An exception was injected into the guest 399282558Sneel * EFAULT N/A Unrecoverable error 400269008Sneel * 401269008Sneel * The 'copyinfo[]' can be passed to 'vm_copyin()' or 'vm_copyout()' only if 402269008Sneel * the return value is 0. The 'copyinfo[]' resources should be freed by calling 403269008Sneel * 'vm_copy_teardown()' after the copy is done. 404269008Sneel */ 405269008Sneelint vm_copy_setup(struct vm *vm, int vcpuid, struct vm_guest_paging *paging, 406269008Sneel uint64_t gla, size_t len, int prot, struct vm_copyinfo *copyinfo, 407282558Sneel int num_copyinfo, int *is_fault); 408269008Sneelvoid vm_copy_teardown(struct vm *vm, int vcpuid, struct vm_copyinfo *copyinfo, 409269008Sneel int num_copyinfo); 410269008Sneelvoid vm_copyin(struct vm *vm, int vcpuid, struct vm_copyinfo *copyinfo, 411269008Sneel void *kaddr, size_t len); 412269008Sneelvoid vm_copyout(struct vm *vm, int vcpuid, const void *kaddr, 413269008Sneel struct vm_copyinfo *copyinfo, size_t len); 414276098Sneel 415276098Sneelint vcpu_trace_exceptions(struct vm *vm, int vcpuid); 416221828Sgrehan#endif /* KERNEL */ 417221828Sgrehan 418255438Sgrehan#define VM_MAXCPU 16 /* maximum virtual cpus */ 419221828Sgrehan 420221828Sgrehan/* 421221828Sgrehan * Identifiers for optional vmm capabilities 422221828Sgrehan */ 423221828Sgrehanenum vm_cap_type { 424221828Sgrehan VM_CAP_HALT_EXIT, 425221828Sgrehan VM_CAP_MTRAP_EXIT, 426221828Sgrehan VM_CAP_PAUSE_EXIT, 427221828Sgrehan VM_CAP_UNRESTRICTED_GUEST, 428256645Sneel VM_CAP_ENABLE_INVPCID, 429221828Sgrehan VM_CAP_MAX 430221828Sgrehan}; 431221828Sgrehan 432266125Sjhbenum vm_intr_trigger { 433266125Sjhb EDGE_TRIGGER, 434266125Sjhb LEVEL_TRIGGER 435266125Sjhb}; 436266125Sjhb 437221828Sgrehan/* 438221828Sgrehan * The 'access' field has the format specified in Table 21-2 of the Intel 439221828Sgrehan * Architecture Manual vol 3b. 440221828Sgrehan * 441221828Sgrehan * XXX The contents of the 'access' field are architecturally defined except 442221828Sgrehan * bit 16 - Segment Unusable. 443221828Sgrehan */ 444221828Sgrehanstruct seg_desc { 445221828Sgrehan uint64_t base; 446221828Sgrehan uint32_t limit; 447221828Sgrehan uint32_t access; 448221828Sgrehan}; 449268701Sneel#define SEG_DESC_TYPE(access) ((access) & 0x001f) 450268777Sneel#define SEG_DESC_DPL(access) (((access) >> 5) & 0x3) 451268701Sneel#define SEG_DESC_PRESENT(access) (((access) & 0x0080) ? 1 : 0) 452268701Sneel#define SEG_DESC_DEF32(access) (((access) & 0x4000) ? 1 : 0) 453268701Sneel#define SEG_DESC_GRANULARITY(access) (((access) & 0x8000) ? 1 : 0) 454268701Sneel#define SEG_DESC_UNUSABLE(access) (((access) & 0x10000) ? 1 : 0) 455221828Sgrehan 456266627Sneelenum vm_cpu_mode { 457268428Sneel CPU_MODE_REAL, 458268428Sneel CPU_MODE_PROTECTED, 459266627Sneel CPU_MODE_COMPATIBILITY, /* IA-32E mode (CS.L = 0) */ 460266627Sneel CPU_MODE_64BIT, /* IA-32E mode (CS.L = 1) */ 461266627Sneel}; 462266627Sneel 463266627Sneelenum vm_paging_mode { 464266627Sneel PAGING_MODE_FLAT, 465266627Sneel PAGING_MODE_32, 466266627Sneel PAGING_MODE_PAE, 467266627Sneel PAGING_MODE_64, 468266627Sneel}; 469266627Sneel 470266627Sneelstruct vm_guest_paging { 471266627Sneel uint64_t cr3; 472266627Sneel int cpl; 473266627Sneel enum vm_cpu_mode cpu_mode; 474266627Sneel enum vm_paging_mode paging_mode; 475266627Sneel}; 476266627Sneel 477266627Sneel/* 478266627Sneel * The data structures 'vie' and 'vie_op' are meant to be opaque to the 479266627Sneel * consumers of instruction decoding. The only reason why their contents 480266627Sneel * need to be exposed is because they are part of the 'vm_exit' structure. 481266627Sneel */ 482266627Sneelstruct vie_op { 483266627Sneel uint8_t op_byte; /* actual opcode byte */ 484266627Sneel uint8_t op_type; /* type of operation (e.g. MOV) */ 485266627Sneel uint16_t op_flags; 486266627Sneel}; 487266627Sneel 488266627Sneel#define VIE_INST_SIZE 15 489266627Sneelstruct vie { 490266627Sneel uint8_t inst[VIE_INST_SIZE]; /* instruction bytes */ 491266627Sneel uint8_t num_valid; /* size of the instruction */ 492266627Sneel uint8_t num_processed; 493266627Sneel 494268701Sneel uint8_t addrsize:4, opsize:4; /* address and operand sizes */ 495266627Sneel uint8_t rex_w:1, /* REX prefix */ 496266627Sneel rex_r:1, 497266627Sneel rex_x:1, 498266627Sneel rex_b:1, 499268701Sneel rex_present:1, 500277360Sneel repz_present:1, /* REP/REPE/REPZ prefix */ 501277360Sneel repnz_present:1, /* REPNE/REPNZ prefix */ 502268701Sneel opsize_override:1, /* Operand size override */ 503277360Sneel addrsize_override:1, /* Address size override */ 504277360Sneel segment_override:1; /* Segment override */ 505266627Sneel 506266627Sneel uint8_t mod:2, /* ModRM byte */ 507266627Sneel reg:4, 508266627Sneel rm:4; 509266627Sneel 510266627Sneel uint8_t ss:2, /* SIB byte */ 511266627Sneel index:4, 512266627Sneel base:4; 513266627Sneel 514266627Sneel uint8_t disp_bytes; 515266627Sneel uint8_t imm_bytes; 516266627Sneel 517266627Sneel uint8_t scale; 518266627Sneel int base_register; /* VM_REG_GUEST_xyz */ 519266627Sneel int index_register; /* VM_REG_GUEST_xyz */ 520277360Sneel int segment_register; /* VM_REG_GUEST_xyz */ 521266627Sneel 522266627Sneel int64_t displacement; /* optional addr displacement */ 523266627Sneel int64_t immediate; /* optional immediate operand */ 524266627Sneel 525266627Sneel uint8_t decoded; /* set to 1 if successfully decoded */ 526266627Sneel 527266627Sneel struct vie_op op; /* opcode description */ 528266627Sneel}; 529266627Sneel 530221828Sgrehanenum vm_exitcode { 531221828Sgrehan VM_EXITCODE_INOUT, 532221828Sgrehan VM_EXITCODE_VMX, 533221828Sgrehan VM_EXITCODE_BOGUS, 534221828Sgrehan VM_EXITCODE_RDMSR, 535221828Sgrehan VM_EXITCODE_WRMSR, 536221828Sgrehan VM_EXITCODE_HLT, 537221828Sgrehan VM_EXITCODE_MTRAP, 538221828Sgrehan VM_EXITCODE_PAUSE, 539234761Sgrehan VM_EXITCODE_PAGING, 540256072Sneel VM_EXITCODE_INST_EMUL, 541240912Sneel VM_EXITCODE_SPINUP_AP, 542265101Sneel VM_EXITCODE_DEPRECATED1, /* used to be SPINDOWN_CPU */ 543260619Sneel VM_EXITCODE_RENDEZVOUS, 544261170Sneel VM_EXITCODE_IOAPIC_EOI, 545263780Sneel VM_EXITCODE_SUSPENDED, 546266573Sneel VM_EXITCODE_INOUT_STR, 547268777Sneel VM_EXITCODE_TASK_SWITCH, 548272670Sneel VM_EXITCODE_MONITOR, 549272670Sneel VM_EXITCODE_MWAIT, 550273375Sneel VM_EXITCODE_SVM, 551283657Sneel VM_EXITCODE_REQIDLE, 552347435Sjhb VM_EXITCODE_VMINSN, 553234761Sgrehan VM_EXITCODE_MAX 554221828Sgrehan}; 555221828Sgrehan 556266573Sneelstruct vm_inout { 557266573Sneel uint16_t bytes:3; /* 1 or 2 or 4 */ 558266573Sneel uint16_t in:1; 559266573Sneel uint16_t string:1; 560266573Sneel uint16_t rep:1; 561266573Sneel uint16_t port; 562266573Sneel uint32_t eax; /* valid for out */ 563266573Sneel}; 564266573Sneel 565266573Sneelstruct vm_inout_str { 566266573Sneel struct vm_inout inout; /* must be the first element */ 567266627Sneel struct vm_guest_paging paging; 568266573Sneel uint64_t rflags; 569266573Sneel uint64_t cr0; 570266573Sneel uint64_t index; 571266573Sneel uint64_t count; /* rep=1 (%rcx), rep=0 (1) */ 572266573Sneel int addrsize; 573266573Sneel enum vm_reg_name seg_name; 574266573Sneel struct seg_desc seg_desc; 575266573Sneel}; 576266573Sneel 577268777Sneelenum task_switch_reason { 578268777Sneel TSR_CALL, 579268777Sneel TSR_IRET, 580268777Sneel TSR_JMP, 581268777Sneel TSR_IDT_GATE, /* task gate in IDT */ 582268777Sneel}; 583268777Sneel 584268777Sneelstruct vm_task_switch { 585268777Sneel uint16_t tsssel; /* new TSS selector */ 586268777Sneel int ext; /* task switch due to external event */ 587268777Sneel uint32_t errcode; 588268777Sneel int errcode_valid; /* push 'errcode' on the new stack */ 589268777Sneel enum task_switch_reason reason; 590268777Sneel struct vm_guest_paging paging; 591268777Sneel}; 592268777Sneel 593221828Sgrehanstruct vm_exit { 594221828Sgrehan enum vm_exitcode exitcode; 595221828Sgrehan int inst_length; /* 0 means unknown */ 596221828Sgrehan uint64_t rip; 597221828Sgrehan union { 598266573Sneel struct vm_inout inout; 599266573Sneel struct vm_inout_str inout_str; 600221828Sgrehan struct { 601241497Sgrehan uint64_t gpa; 602256072Sneel int fault_type; 603256072Sneel } paging; 604256072Sneel struct { 605256072Sneel uint64_t gpa; 606256072Sneel uint64_t gla; 607280447Stychon uint64_t cs_base; 608268701Sneel int cs_d; /* CS.D */ 609266627Sneel struct vm_guest_paging paging; 610243640Sneel struct vie vie; 611256072Sneel } inst_emul; 612221828Sgrehan /* 613221828Sgrehan * VMX specific payload. Used when there is no "better" 614221828Sgrehan * exitcode to represent the VM-exit. 615221828Sgrehan */ 616221828Sgrehan struct { 617260167Sneel int status; /* vmx inst status */ 618260167Sneel /* 619260167Sneel * 'exit_reason' and 'exit_qualification' are valid 620260167Sneel * only if 'status' is zero. 621260167Sneel */ 622221828Sgrehan uint32_t exit_reason; 623221828Sgrehan uint64_t exit_qualification; 624260167Sneel /* 625260167Sneel * 'inst_error' and 'inst_type' are valid 626260167Sneel * only if 'status' is non-zero. 627260167Sneel */ 628260167Sneel int inst_type; 629260167Sneel int inst_error; 630221828Sgrehan } vmx; 631273375Sneel /* 632273375Sneel * SVM specific payload. 633273375Sneel */ 634221828Sgrehan struct { 635273375Sneel uint64_t exitcode; 636273375Sneel uint64_t exitinfo1; 637273375Sneel uint64_t exitinfo2; 638273375Sneel } svm; 639273375Sneel struct { 640221828Sgrehan uint32_t code; /* ecx value */ 641221828Sgrehan uint64_t wval; 642221828Sgrehan } msr; 643240912Sneel struct { 644240912Sneel int vcpu; 645240912Sneel uint64_t rip; 646240912Sneel } spinup_ap; 647259081Sneel struct { 648259081Sneel uint64_t rflags; 649347074Sjhb uint64_t intr_status; 650259081Sneel } hlt; 651261170Sneel struct { 652261170Sneel int vector; 653261170Sneel } ioapic_eoi; 654265062Sneel struct { 655265062Sneel enum vm_suspend_how how; 656265062Sneel } suspended; 657268777Sneel struct vm_task_switch task_switch; 658221828Sgrehan } u; 659221828Sgrehan}; 660221828Sgrehan 661269042Sneel/* APIs to inject faults into the guest */ 662269042Sneelvoid vm_inject_fault(void *vm, int vcpuid, int vector, int errcode_valid, 663269042Sneel int errcode); 664269042Sneel 665270438Sgrehanstatic __inline void 666269042Sneelvm_inject_ud(void *vm, int vcpuid) 667269042Sneel{ 668269042Sneel vm_inject_fault(vm, vcpuid, IDT_UD, 0, 0); 669269042Sneel} 670269042Sneel 671270438Sgrehanstatic __inline void 672269042Sneelvm_inject_gp(void *vm, int vcpuid) 673269042Sneel{ 674269042Sneel vm_inject_fault(vm, vcpuid, IDT_GP, 1, 0); 675269042Sneel} 676269042Sneel 677270438Sgrehanstatic __inline void 678269042Sneelvm_inject_ac(void *vm, int vcpuid, int errcode) 679269042Sneel{ 680269042Sneel vm_inject_fault(vm, vcpuid, IDT_AC, 1, errcode); 681269042Sneel} 682269042Sneel 683270438Sgrehanstatic __inline void 684269042Sneelvm_inject_ss(void *vm, int vcpuid, int errcode) 685269042Sneel{ 686269042Sneel vm_inject_fault(vm, vcpuid, IDT_SS, 1, errcode); 687269042Sneel} 688269042Sneel 689269042Sneelvoid vm_inject_pf(void *vm, int vcpuid, int error_code, uint64_t cr2); 690269042Sneel 691277149Sneelint vm_restart_instruction(void *vm, int vcpuid); 692277149Sneel 693221828Sgrehan#endif /* _VMM_H_ */ 694