vmm.h revision 269008
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: head/sys/amd64/include/vmm.h 269008 2014-07-23 04:28:51Z neel $ 27221828Sgrehan */ 28221828Sgrehan 29221828Sgrehan#ifndef _VMM_H_ 30221828Sgrehan#define _VMM_H_ 31221828Sgrehan 32265062Sneelenum vm_suspend_how { 33265062Sneel VM_SUSPEND_NONE, 34265062Sneel VM_SUSPEND_RESET, 35265062Sneel VM_SUSPEND_POWEROFF, 36265203Sneel VM_SUSPEND_HALT, 37268889Sneel VM_SUSPEND_TRIPLEFAULT, 38265062Sneel VM_SUSPEND_LAST 39265062Sneel}; 40265062Sneel 41267338Stychon/* 42267338Stychon * Identifiers for architecturally defined registers. 43267338Stychon */ 44267338Stychonenum vm_reg_name { 45267338Stychon VM_REG_GUEST_RAX, 46267338Stychon VM_REG_GUEST_RBX, 47267338Stychon VM_REG_GUEST_RCX, 48267338Stychon VM_REG_GUEST_RDX, 49267338Stychon VM_REG_GUEST_RSI, 50267338Stychon VM_REG_GUEST_RDI, 51267338Stychon VM_REG_GUEST_RBP, 52267338Stychon VM_REG_GUEST_R8, 53267338Stychon VM_REG_GUEST_R9, 54267338Stychon VM_REG_GUEST_R10, 55267338Stychon VM_REG_GUEST_R11, 56267338Stychon VM_REG_GUEST_R12, 57267338Stychon VM_REG_GUEST_R13, 58267338Stychon VM_REG_GUEST_R14, 59267338Stychon VM_REG_GUEST_R15, 60267338Stychon VM_REG_GUEST_CR0, 61267338Stychon VM_REG_GUEST_CR3, 62267338Stychon VM_REG_GUEST_CR4, 63267338Stychon VM_REG_GUEST_DR7, 64267338Stychon VM_REG_GUEST_RSP, 65267338Stychon VM_REG_GUEST_RIP, 66267338Stychon VM_REG_GUEST_RFLAGS, 67267338Stychon VM_REG_GUEST_ES, 68267338Stychon VM_REG_GUEST_CS, 69267338Stychon VM_REG_GUEST_SS, 70267338Stychon VM_REG_GUEST_DS, 71267338Stychon VM_REG_GUEST_FS, 72267338Stychon VM_REG_GUEST_GS, 73267338Stychon VM_REG_GUEST_LDTR, 74267338Stychon VM_REG_GUEST_TR, 75267338Stychon VM_REG_GUEST_IDTR, 76267338Stychon VM_REG_GUEST_GDTR, 77267338Stychon VM_REG_GUEST_EFER, 78267338Stychon VM_REG_GUEST_CR2, 79268777Sneel VM_REG_GUEST_PDPTE0, 80268777Sneel VM_REG_GUEST_PDPTE1, 81268777Sneel VM_REG_GUEST_PDPTE2, 82268777Sneel VM_REG_GUEST_PDPTE3, 83267338Stychon VM_REG_LAST 84267338Stychon}; 85267338Stychon 86267338Stychonenum x2apic_state { 87267338Stychon X2APIC_DISABLED, 88267338Stychon X2APIC_ENABLED, 89267338Stychon X2APIC_STATE_LAST 90267338Stychon}; 91267338Stychon 92268889Sneel#define VM_INTINFO_VECTOR(info) ((info) & 0xff) 93268889Sneel#define VM_INTINFO_DEL_ERRCODE 0x800 94268889Sneel#define VM_INTINFO_RSVD 0x7ffff000 95268889Sneel#define VM_INTINFO_VALID 0x80000000 96268889Sneel#define VM_INTINFO_TYPE 0x700 97268889Sneel#define VM_INTINFO_HWINTR (0 << 8) 98268889Sneel#define VM_INTINFO_NMI (2 << 8) 99268889Sneel#define VM_INTINFO_HWEXCEPTION (3 << 8) 100268889Sneel#define VM_INTINFO_SWINTR (4 << 8) 101268889Sneel 102221828Sgrehan#ifdef _KERNEL 103221828Sgrehan 104221828Sgrehan#define VM_MAX_NAMELEN 32 105221828Sgrehan 106221828Sgrehanstruct vm; 107262506Sneelstruct vm_exception; 108221828Sgrehanstruct vm_memory_segment; 109221828Sgrehanstruct seg_desc; 110221828Sgrehanstruct vm_exit; 111221828Sgrehanstruct vm_run; 112258579Sneelstruct vhpet; 113258075Sneelstruct vioapic; 114221828Sgrehanstruct vlapic; 115256072Sneelstruct vmspace; 116256072Sneelstruct vm_object; 117269008Sneelstruct vm_guest_paging; 118256072Sneelstruct pmap; 119221828Sgrehan 120260466Sneeltypedef int (*vmm_init_func_t)(int ipinum); 121221828Sgrehantypedef int (*vmm_cleanup_func_t)(void); 122259782Sjhbtypedef void (*vmm_resume_func_t)(void); 123256072Sneeltypedef void * (*vmi_init_func_t)(struct vm *vm, struct pmap *pmap); 124256072Sneeltypedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip, 125263780Sneel struct pmap *pmap, void *rendezvous_cookie, 126263780Sneel void *suspend_cookie); 127221828Sgrehantypedef void (*vmi_cleanup_func_t)(void *vmi); 128221828Sgrehantypedef int (*vmi_get_register_t)(void *vmi, int vcpu, int num, 129221828Sgrehan uint64_t *retval); 130221828Sgrehantypedef int (*vmi_set_register_t)(void *vmi, int vcpu, int num, 131221828Sgrehan uint64_t val); 132221828Sgrehantypedef int (*vmi_get_desc_t)(void *vmi, int vcpu, int num, 133221828Sgrehan struct seg_desc *desc); 134221828Sgrehantypedef int (*vmi_set_desc_t)(void *vmi, int vcpu, int num, 135221828Sgrehan struct seg_desc *desc); 136221828Sgrehantypedef int (*vmi_get_cap_t)(void *vmi, int vcpu, int num, int *retval); 137221828Sgrehantypedef int (*vmi_set_cap_t)(void *vmi, int vcpu, int num, int val); 138256072Sneeltypedef struct vmspace * (*vmi_vmspace_alloc)(vm_offset_t min, vm_offset_t max); 139256072Sneeltypedef void (*vmi_vmspace_free)(struct vmspace *vmspace); 140259863Sneeltypedef struct vlapic * (*vmi_vlapic_init)(void *vmi, int vcpu); 141259863Sneeltypedef void (*vmi_vlapic_cleanup)(void *vmi, struct vlapic *vlapic); 142221828Sgrehan 143221828Sgrehanstruct vmm_ops { 144221828Sgrehan vmm_init_func_t init; /* module wide initialization */ 145221828Sgrehan vmm_cleanup_func_t cleanup; 146259782Sjhb vmm_resume_func_t resume; 147221828Sgrehan 148221828Sgrehan vmi_init_func_t vminit; /* vm-specific initialization */ 149221828Sgrehan vmi_run_func_t vmrun; 150221828Sgrehan vmi_cleanup_func_t vmcleanup; 151221828Sgrehan vmi_get_register_t vmgetreg; 152221828Sgrehan vmi_set_register_t vmsetreg; 153221828Sgrehan vmi_get_desc_t vmgetdesc; 154221828Sgrehan vmi_set_desc_t vmsetdesc; 155221828Sgrehan vmi_get_cap_t vmgetcap; 156221828Sgrehan vmi_set_cap_t vmsetcap; 157256072Sneel vmi_vmspace_alloc vmspace_alloc; 158256072Sneel vmi_vmspace_free vmspace_free; 159259863Sneel vmi_vlapic_init vlapic_init; 160259863Sneel vmi_vlapic_cleanup vlapic_cleanup; 161221828Sgrehan}; 162221828Sgrehan 163221828Sgrehanextern struct vmm_ops vmm_ops_intel; 164221828Sgrehanextern struct vmm_ops vmm_ops_amd; 165221828Sgrehan 166249396Sneelint vm_create(const char *name, struct vm **retvm); 167221828Sgrehanvoid vm_destroy(struct vm *vm); 168267216Sneelint vm_reinit(struct vm *vm); 169221828Sgrehanconst char *vm_name(struct vm *vm); 170241041Sneelint vm_malloc(struct vm *vm, vm_paddr_t gpa, size_t len); 171221828Sgrehanint vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa); 172221828Sgrehanint vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len); 173256072Sneelvoid *vm_gpa_hold(struct vm *, vm_paddr_t gpa, size_t len, int prot, 174256072Sneel void **cookie); 175256072Sneelvoid vm_gpa_release(void *cookie); 176221828Sgrehanint vm_gpabase2memseg(struct vm *vm, vm_paddr_t gpabase, 177221828Sgrehan struct vm_memory_segment *seg); 178256072Sneelint vm_get_memobj(struct vm *vm, vm_paddr_t gpa, size_t len, 179256072Sneel vm_offset_t *offset, struct vm_object **object); 180256072Sneelboolean_t vm_mem_allocated(struct vm *vm, vm_paddr_t gpa); 181221828Sgrehanint vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval); 182221828Sgrehanint vm_set_register(struct vm *vm, int vcpu, int reg, uint64_t val); 183221828Sgrehanint vm_get_seg_desc(struct vm *vm, int vcpu, int reg, 184221828Sgrehan struct seg_desc *ret_desc); 185221828Sgrehanint vm_set_seg_desc(struct vm *vm, int vcpu, int reg, 186221828Sgrehan struct seg_desc *desc); 187221828Sgrehanint vm_run(struct vm *vm, struct vm_run *vmrun); 188265062Sneelint vm_suspend(struct vm *vm, enum vm_suspend_how how); 189221828Sgrehanint vm_inject_nmi(struct vm *vm, int vcpu); 190241982Sneelint vm_nmi_pending(struct vm *vm, int vcpuid); 191241982Sneelvoid vm_nmi_clear(struct vm *vm, int vcpuid); 192263211Stychonint vm_inject_extint(struct vm *vm, int vcpu); 193263211Stychonint vm_extint_pending(struct vm *vm, int vcpuid); 194263211Stychonvoid vm_extint_clear(struct vm *vm, int vcpuid); 195221828Sgrehanuint64_t *vm_guest_msrs(struct vm *vm, int cpu); 196221828Sgrehanstruct vlapic *vm_lapic(struct vm *vm, int cpu); 197258075Sneelstruct vioapic *vm_ioapic(struct vm *vm); 198258579Sneelstruct vhpet *vm_hpet(struct vm *vm); 199221828Sgrehanint vm_get_capability(struct vm *vm, int vcpu, int type, int *val); 200221828Sgrehanint vm_set_capability(struct vm *vm, int vcpu, int type, int val); 201240922Sneelint vm_get_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state *state); 202240922Sneelint vm_set_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state state); 203258075Sneelint vm_apicid2vcpuid(struct vm *vm, int apicid); 204266933Sneelint vm_activate_cpu(struct vm *vm, int vcpu); 205223621Sgrehancpuset_t vm_active_cpus(struct vm *vm); 206266933Sneelcpuset_t vm_suspended_cpus(struct vm *vm); 207240894Sneelstruct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid); 208265062Sneelvoid vm_exit_suspended(struct vm *vm, int vcpuid, uint64_t rip); 209267330Sneelvoid vm_exit_rendezvous(struct vm *vm, int vcpuid, uint64_t rip); 210267330Sneelvoid vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip); 211221828Sgrehan 212221828Sgrehan/* 213260619Sneel * Rendezvous all vcpus specified in 'dest' and execute 'func(arg)'. 214260619Sneel * The rendezvous 'func(arg)' is not allowed to do anything that will 215260619Sneel * cause the thread to be put to sleep. 216260619Sneel * 217260619Sneel * If the rendezvous is being initiated from a vcpu context then the 218260619Sneel * 'vcpuid' must refer to that vcpu, otherwise it should be set to -1. 219260619Sneel * 220260619Sneel * The caller cannot hold any locks when initiating the rendezvous. 221260619Sneel * 222260619Sneel * The implementation of this API may cause vcpus other than those specified 223260619Sneel * by 'dest' to be stalled. The caller should not rely on any vcpus making 224260619Sneel * forward progress when the rendezvous is in progress. 225260619Sneel */ 226260619Sneeltypedef void (*vm_rendezvous_func_t)(struct vm *vm, int vcpuid, void *arg); 227260619Sneelvoid vm_smp_rendezvous(struct vm *vm, int vcpuid, cpuset_t dest, 228260619Sneel vm_rendezvous_func_t func, void *arg); 229260619Sneel 230260619Sneelstatic __inline int 231260619Sneelvcpu_rendezvous_pending(void *rendezvous_cookie) 232260619Sneel{ 233260619Sneel 234260619Sneel return (*(uintptr_t *)rendezvous_cookie != 0); 235260619Sneel} 236260619Sneel 237263780Sneelstatic __inline int 238263780Sneelvcpu_suspended(void *suspend_cookie) 239263780Sneel{ 240263780Sneel 241263780Sneel return (*(int *)suspend_cookie); 242263780Sneel} 243263780Sneel 244260619Sneel/* 245221828Sgrehan * Return 1 if device indicated by bus/slot/func is supposed to be a 246221828Sgrehan * pci passthrough device. 247221828Sgrehan * 248221828Sgrehan * Return 0 otherwise. 249221828Sgrehan */ 250221828Sgrehanint vmm_is_pptdev(int bus, int slot, int func); 251221828Sgrehan 252221828Sgrehanvoid *vm_iommu_domain(struct vm *vm); 253221828Sgrehan 254241489Sneelenum vcpu_state { 255241489Sneel VCPU_IDLE, 256256072Sneel VCPU_FROZEN, 257241489Sneel VCPU_RUNNING, 258256072Sneel VCPU_SLEEPING, 259241489Sneel}; 260221828Sgrehan 261259737Sneelint vcpu_set_state(struct vm *vm, int vcpu, enum vcpu_state state, 262259737Sneel bool from_idle); 263249879Sgrehanenum vcpu_state vcpu_get_state(struct vm *vm, int vcpu, int *hostcpu); 264221828Sgrehan 265221828Sgrehanstatic int __inline 266249879Sgrehanvcpu_is_running(struct vm *vm, int vcpu, int *hostcpu) 267221828Sgrehan{ 268249879Sgrehan return (vcpu_get_state(vm, vcpu, hostcpu) == VCPU_RUNNING); 269221828Sgrehan} 270221828Sgrehan 271241489Sneelvoid *vcpu_stats(struct vm *vm, int vcpu); 272259863Sneelvoid vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr); 273256072Sneelstruct vmspace *vm_get_vmspace(struct vm *vm); 274256072Sneelint vm_assign_pptdev(struct vm *vm, int bus, int slot, int func); 275256072Sneelint vm_unassign_pptdev(struct vm *vm, int bus, int slot, int func); 276263035Stychonstruct vatpic *vm_atpic(struct vm *vm); 277263744Stychonstruct vatpit *vm_atpit(struct vm *vm); 278262506Sneel 279262506Sneel/* 280262506Sneel * Inject exception 'vme' into the guest vcpu. This function returns 0 on 281262506Sneel * success and non-zero on failure. 282262506Sneel * 283262506Sneel * Wrapper functions like 'vm_inject_gp()' should be preferred to calling 284262506Sneel * this function directly because they enforce the trap-like or fault-like 285262506Sneel * behavior of an exception. 286262506Sneel * 287262506Sneel * This function should only be called in the context of the thread that is 288262506Sneel * executing this vcpu. 289262506Sneel */ 290262506Sneelint vm_inject_exception(struct vm *vm, int vcpuid, struct vm_exception *vme); 291262506Sneel 292262506Sneel/* 293268889Sneel * This function is called after a VM-exit that occurred during exception or 294268889Sneel * interrupt delivery through the IDT. The format of 'intinfo' is described 295268889Sneel * in Figure 15-1, "EXITINTINFO for All Intercepts", APM, Vol 2. 296262506Sneel * 297268889Sneel * If a VM-exit handler completes the event delivery successfully then it 298268889Sneel * should call vm_exit_intinfo() to extinguish the pending event. For e.g., 299268889Sneel * if the task switch emulation is triggered via a task gate then it should 300268889Sneel * call this function with 'intinfo=0' to indicate that the external event 301268889Sneel * is not pending anymore. 302268889Sneel * 303268889Sneel * Return value is 0 on success and non-zero on failure. 304262506Sneel */ 305268889Sneelint vm_exit_intinfo(struct vm *vm, int vcpuid, uint64_t intinfo); 306262506Sneel 307268889Sneel/* 308268889Sneel * This function is called before every VM-entry to retrieve a pending 309268889Sneel * event that should be injected into the guest. This function combines 310268889Sneel * nested events into a double or triple fault. 311268889Sneel * 312268889Sneel * Returns 0 if there are no events that need to be injected into the guest 313268889Sneel * and non-zero otherwise. 314268889Sneel */ 315268889Sneelint vm_entry_intinfo(struct vm *vm, int vcpuid, uint64_t *info); 316268889Sneel 317268889Sneelint vm_get_intinfo(struct vm *vm, int vcpuid, uint64_t *info1, uint64_t *info2); 318268889Sneel 319262506Sneelvoid vm_inject_gp(struct vm *vm, int vcpuid); /* general protection fault */ 320262506Sneelvoid vm_inject_ud(struct vm *vm, int vcpuid); /* undefined instruction fault */ 321269008Sneelvoid vm_inject_ac(struct vm *vm, int vcpuid, int errcode); /* #AC */ 322269008Sneelvoid vm_inject_ss(struct vm *vm, int vcpuid, int errcode); /* #SS */ 323266626Sneelvoid vm_inject_pf(struct vm *vm, int vcpuid, int error_code, uint64_t cr2); 324262506Sneel 325266573Sneelenum vm_reg_name vm_segment_name(int seg_encoding); 326266573Sneel 327269008Sneelstruct vm_copyinfo { 328269008Sneel uint64_t gpa; 329269008Sneel size_t len; 330269008Sneel void *hva; 331269008Sneel void *cookie; 332269008Sneel}; 333269008Sneel 334269008Sneel/* 335269008Sneel * Set up 'copyinfo[]' to copy to/from guest linear address space starting 336269008Sneel * at 'gla' and 'len' bytes long. The 'prot' should be set to PROT_READ for 337269008Sneel * a copyin or PROT_WRITE for a copyout. 338269008Sneel * 339269008Sneel * Returns 0 on success. 340269008Sneel * Returns 1 if an exception was injected into the guest. 341269008Sneel * Returns -1 otherwise. 342269008Sneel * 343269008Sneel * The 'copyinfo[]' can be passed to 'vm_copyin()' or 'vm_copyout()' only if 344269008Sneel * the return value is 0. The 'copyinfo[]' resources should be freed by calling 345269008Sneel * 'vm_copy_teardown()' after the copy is done. 346269008Sneel */ 347269008Sneelint vm_copy_setup(struct vm *vm, int vcpuid, struct vm_guest_paging *paging, 348269008Sneel uint64_t gla, size_t len, int prot, struct vm_copyinfo *copyinfo, 349269008Sneel int num_copyinfo); 350269008Sneelvoid vm_copy_teardown(struct vm *vm, int vcpuid, struct vm_copyinfo *copyinfo, 351269008Sneel int num_copyinfo); 352269008Sneelvoid vm_copyin(struct vm *vm, int vcpuid, struct vm_copyinfo *copyinfo, 353269008Sneel void *kaddr, size_t len); 354269008Sneelvoid vm_copyout(struct vm *vm, int vcpuid, const void *kaddr, 355269008Sneel struct vm_copyinfo *copyinfo, size_t len); 356221828Sgrehan#endif /* KERNEL */ 357221828Sgrehan 358255438Sgrehan#define VM_MAXCPU 16 /* maximum virtual cpus */ 359221828Sgrehan 360221828Sgrehan/* 361221828Sgrehan * Identifiers for optional vmm capabilities 362221828Sgrehan */ 363221828Sgrehanenum vm_cap_type { 364221828Sgrehan VM_CAP_HALT_EXIT, 365221828Sgrehan VM_CAP_MTRAP_EXIT, 366221828Sgrehan VM_CAP_PAUSE_EXIT, 367221828Sgrehan VM_CAP_UNRESTRICTED_GUEST, 368256645Sneel VM_CAP_ENABLE_INVPCID, 369221828Sgrehan VM_CAP_MAX 370221828Sgrehan}; 371221828Sgrehan 372266125Sjhbenum vm_intr_trigger { 373266125Sjhb EDGE_TRIGGER, 374266125Sjhb LEVEL_TRIGGER 375266125Sjhb}; 376266125Sjhb 377221828Sgrehan/* 378221828Sgrehan * The 'access' field has the format specified in Table 21-2 of the Intel 379221828Sgrehan * Architecture Manual vol 3b. 380221828Sgrehan * 381221828Sgrehan * XXX The contents of the 'access' field are architecturally defined except 382221828Sgrehan * bit 16 - Segment Unusable. 383221828Sgrehan */ 384221828Sgrehanstruct seg_desc { 385221828Sgrehan uint64_t base; 386221828Sgrehan uint32_t limit; 387221828Sgrehan uint32_t access; 388221828Sgrehan}; 389268701Sneel#define SEG_DESC_TYPE(access) ((access) & 0x001f) 390268777Sneel#define SEG_DESC_DPL(access) (((access) >> 5) & 0x3) 391268701Sneel#define SEG_DESC_PRESENT(access) (((access) & 0x0080) ? 1 : 0) 392268701Sneel#define SEG_DESC_DEF32(access) (((access) & 0x4000) ? 1 : 0) 393268701Sneel#define SEG_DESC_GRANULARITY(access) (((access) & 0x8000) ? 1 : 0) 394268701Sneel#define SEG_DESC_UNUSABLE(access) (((access) & 0x10000) ? 1 : 0) 395221828Sgrehan 396266627Sneelenum vm_cpu_mode { 397268428Sneel CPU_MODE_REAL, 398268428Sneel CPU_MODE_PROTECTED, 399266627Sneel CPU_MODE_COMPATIBILITY, /* IA-32E mode (CS.L = 0) */ 400266627Sneel CPU_MODE_64BIT, /* IA-32E mode (CS.L = 1) */ 401266627Sneel}; 402266627Sneel 403266627Sneelenum vm_paging_mode { 404266627Sneel PAGING_MODE_FLAT, 405266627Sneel PAGING_MODE_32, 406266627Sneel PAGING_MODE_PAE, 407266627Sneel PAGING_MODE_64, 408266627Sneel}; 409266627Sneel 410266627Sneelstruct vm_guest_paging { 411266627Sneel uint64_t cr3; 412266627Sneel int cpl; 413266627Sneel enum vm_cpu_mode cpu_mode; 414266627Sneel enum vm_paging_mode paging_mode; 415266627Sneel}; 416266627Sneel 417266627Sneel/* 418266627Sneel * The data structures 'vie' and 'vie_op' are meant to be opaque to the 419266627Sneel * consumers of instruction decoding. The only reason why their contents 420266627Sneel * need to be exposed is because they are part of the 'vm_exit' structure. 421266627Sneel */ 422266627Sneelstruct vie_op { 423266627Sneel uint8_t op_byte; /* actual opcode byte */ 424266627Sneel uint8_t op_type; /* type of operation (e.g. MOV) */ 425266627Sneel uint16_t op_flags; 426266627Sneel}; 427266627Sneel 428266627Sneel#define VIE_INST_SIZE 15 429266627Sneelstruct vie { 430266627Sneel uint8_t inst[VIE_INST_SIZE]; /* instruction bytes */ 431266627Sneel uint8_t num_valid; /* size of the instruction */ 432266627Sneel uint8_t num_processed; 433266627Sneel 434268701Sneel uint8_t addrsize:4, opsize:4; /* address and operand sizes */ 435266627Sneel uint8_t rex_w:1, /* REX prefix */ 436266627Sneel rex_r:1, 437266627Sneel rex_x:1, 438266627Sneel rex_b:1, 439268701Sneel rex_present:1, 440268701Sneel opsize_override:1, /* Operand size override */ 441268701Sneel addrsize_override:1; /* Address size override */ 442266627Sneel 443266627Sneel uint8_t mod:2, /* ModRM byte */ 444266627Sneel reg:4, 445266627Sneel rm:4; 446266627Sneel 447266627Sneel uint8_t ss:2, /* SIB byte */ 448266627Sneel index:4, 449266627Sneel base:4; 450266627Sneel 451266627Sneel uint8_t disp_bytes; 452266627Sneel uint8_t imm_bytes; 453266627Sneel 454266627Sneel uint8_t scale; 455266627Sneel int base_register; /* VM_REG_GUEST_xyz */ 456266627Sneel int index_register; /* VM_REG_GUEST_xyz */ 457266627Sneel 458266627Sneel int64_t displacement; /* optional addr displacement */ 459266627Sneel int64_t immediate; /* optional immediate operand */ 460266627Sneel 461266627Sneel uint8_t decoded; /* set to 1 if successfully decoded */ 462266627Sneel 463266627Sneel struct vie_op op; /* opcode description */ 464266627Sneel}; 465266627Sneel 466221828Sgrehanenum vm_exitcode { 467221828Sgrehan VM_EXITCODE_INOUT, 468221828Sgrehan VM_EXITCODE_VMX, 469221828Sgrehan VM_EXITCODE_BOGUS, 470221828Sgrehan VM_EXITCODE_RDMSR, 471221828Sgrehan VM_EXITCODE_WRMSR, 472221828Sgrehan VM_EXITCODE_HLT, 473221828Sgrehan VM_EXITCODE_MTRAP, 474221828Sgrehan VM_EXITCODE_PAUSE, 475234761Sgrehan VM_EXITCODE_PAGING, 476256072Sneel VM_EXITCODE_INST_EMUL, 477240912Sneel VM_EXITCODE_SPINUP_AP, 478265101Sneel VM_EXITCODE_DEPRECATED1, /* used to be SPINDOWN_CPU */ 479260619Sneel VM_EXITCODE_RENDEZVOUS, 480261170Sneel VM_EXITCODE_IOAPIC_EOI, 481263780Sneel VM_EXITCODE_SUSPENDED, 482266573Sneel VM_EXITCODE_INOUT_STR, 483268777Sneel VM_EXITCODE_TASK_SWITCH, 484234761Sgrehan VM_EXITCODE_MAX 485221828Sgrehan}; 486221828Sgrehan 487266573Sneelstruct vm_inout { 488266573Sneel uint16_t bytes:3; /* 1 or 2 or 4 */ 489266573Sneel uint16_t in:1; 490266573Sneel uint16_t string:1; 491266573Sneel uint16_t rep:1; 492266573Sneel uint16_t port; 493266573Sneel uint32_t eax; /* valid for out */ 494266573Sneel}; 495266573Sneel 496266573Sneelstruct vm_inout_str { 497266573Sneel struct vm_inout inout; /* must be the first element */ 498266627Sneel struct vm_guest_paging paging; 499266573Sneel uint64_t rflags; 500266573Sneel uint64_t cr0; 501266573Sneel uint64_t index; 502266573Sneel uint64_t count; /* rep=1 (%rcx), rep=0 (1) */ 503266573Sneel int addrsize; 504266573Sneel enum vm_reg_name seg_name; 505266573Sneel struct seg_desc seg_desc; 506266573Sneel}; 507266573Sneel 508268777Sneelenum task_switch_reason { 509268777Sneel TSR_CALL, 510268777Sneel TSR_IRET, 511268777Sneel TSR_JMP, 512268777Sneel TSR_IDT_GATE, /* task gate in IDT */ 513268777Sneel}; 514268777Sneel 515268777Sneelstruct vm_task_switch { 516268777Sneel uint16_t tsssel; /* new TSS selector */ 517268777Sneel int ext; /* task switch due to external event */ 518268777Sneel uint32_t errcode; 519268777Sneel int errcode_valid; /* push 'errcode' on the new stack */ 520268777Sneel enum task_switch_reason reason; 521268777Sneel struct vm_guest_paging paging; 522268777Sneel}; 523268777Sneel 524221828Sgrehanstruct vm_exit { 525221828Sgrehan enum vm_exitcode exitcode; 526221828Sgrehan int inst_length; /* 0 means unknown */ 527221828Sgrehan uint64_t rip; 528221828Sgrehan union { 529266573Sneel struct vm_inout inout; 530266573Sneel struct vm_inout_str inout_str; 531221828Sgrehan struct { 532241497Sgrehan uint64_t gpa; 533256072Sneel int fault_type; 534256072Sneel } paging; 535256072Sneel struct { 536256072Sneel uint64_t gpa; 537256072Sneel uint64_t gla; 538268701Sneel int cs_d; /* CS.D */ 539266627Sneel struct vm_guest_paging paging; 540243640Sneel struct vie vie; 541256072Sneel } inst_emul; 542221828Sgrehan /* 543221828Sgrehan * VMX specific payload. Used when there is no "better" 544221828Sgrehan * exitcode to represent the VM-exit. 545221828Sgrehan */ 546221828Sgrehan struct { 547260167Sneel int status; /* vmx inst status */ 548260167Sneel /* 549260167Sneel * 'exit_reason' and 'exit_qualification' are valid 550260167Sneel * only if 'status' is zero. 551260167Sneel */ 552221828Sgrehan uint32_t exit_reason; 553221828Sgrehan uint64_t exit_qualification; 554260167Sneel /* 555260167Sneel * 'inst_error' and 'inst_type' are valid 556260167Sneel * only if 'status' is non-zero. 557260167Sneel */ 558260167Sneel int inst_type; 559260167Sneel int inst_error; 560221828Sgrehan } vmx; 561221828Sgrehan struct { 562221828Sgrehan uint32_t code; /* ecx value */ 563221828Sgrehan uint64_t wval; 564221828Sgrehan } msr; 565240912Sneel struct { 566240912Sneel int vcpu; 567240912Sneel uint64_t rip; 568240912Sneel } spinup_ap; 569259081Sneel struct { 570259081Sneel uint64_t rflags; 571259081Sneel } hlt; 572261170Sneel struct { 573261170Sneel int vector; 574261170Sneel } ioapic_eoi; 575265062Sneel struct { 576265062Sneel enum vm_suspend_how how; 577265062Sneel } suspended; 578268777Sneel struct vm_task_switch task_switch; 579221828Sgrehan } u; 580221828Sgrehan}; 581221828Sgrehan 582221828Sgrehan#endif /* _VMM_H_ */ 583