vmm.h revision 268777
1221828Sgrehan/*- 2221828Sgrehan * Copyright (c) 2011 NetApp, Inc. 3221828Sgrehan * All rights reserved. 4221828Sgrehan * 5221828Sgrehan * Redistribution and use in source and binary forms, with or without 6221828Sgrehan * modification, are permitted provided that the following conditions 7221828Sgrehan * are met: 8221828Sgrehan * 1. Redistributions of source code must retain the above copyright 9221828Sgrehan * notice, this list of conditions and the following disclaimer. 10221828Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 11221828Sgrehan * notice, this list of conditions and the following disclaimer in the 12221828Sgrehan * documentation and/or other materials provided with the distribution. 13221828Sgrehan * 14221828Sgrehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15221828Sgrehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16221828Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17221828Sgrehan * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18221828Sgrehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19221828Sgrehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20221828Sgrehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21221828Sgrehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22221828Sgrehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23221828Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24221828Sgrehan * SUCH DAMAGE. 25221828Sgrehan * 26245678Sneel * $FreeBSD: head/sys/amd64/include/vmm.h 268777 2014-07-16 21:26:26Z 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, 37265062Sneel VM_SUSPEND_LAST 38265062Sneel}; 39265062Sneel 40267338Stychon/* 41267338Stychon * Identifiers for architecturally defined registers. 42267338Stychon */ 43267338Stychonenum vm_reg_name { 44267338Stychon VM_REG_GUEST_RAX, 45267338Stychon VM_REG_GUEST_RBX, 46267338Stychon VM_REG_GUEST_RCX, 47267338Stychon VM_REG_GUEST_RDX, 48267338Stychon VM_REG_GUEST_RSI, 49267338Stychon VM_REG_GUEST_RDI, 50267338Stychon VM_REG_GUEST_RBP, 51267338Stychon VM_REG_GUEST_R8, 52267338Stychon VM_REG_GUEST_R9, 53267338Stychon VM_REG_GUEST_R10, 54267338Stychon VM_REG_GUEST_R11, 55267338Stychon VM_REG_GUEST_R12, 56267338Stychon VM_REG_GUEST_R13, 57267338Stychon VM_REG_GUEST_R14, 58267338Stychon VM_REG_GUEST_R15, 59267338Stychon VM_REG_GUEST_CR0, 60267338Stychon VM_REG_GUEST_CR3, 61267338Stychon VM_REG_GUEST_CR4, 62267338Stychon VM_REG_GUEST_DR7, 63267338Stychon VM_REG_GUEST_RSP, 64267338Stychon VM_REG_GUEST_RIP, 65267338Stychon VM_REG_GUEST_RFLAGS, 66267338Stychon VM_REG_GUEST_ES, 67267338Stychon VM_REG_GUEST_CS, 68267338Stychon VM_REG_GUEST_SS, 69267338Stychon VM_REG_GUEST_DS, 70267338Stychon VM_REG_GUEST_FS, 71267338Stychon VM_REG_GUEST_GS, 72267338Stychon VM_REG_GUEST_LDTR, 73267338Stychon VM_REG_GUEST_TR, 74267338Stychon VM_REG_GUEST_IDTR, 75267338Stychon VM_REG_GUEST_GDTR, 76267338Stychon VM_REG_GUEST_EFER, 77267338Stychon VM_REG_GUEST_CR2, 78268777Sneel VM_REG_GUEST_PDPTE0, 79268777Sneel VM_REG_GUEST_PDPTE1, 80268777Sneel VM_REG_GUEST_PDPTE2, 81268777Sneel VM_REG_GUEST_PDPTE3, 82267338Stychon VM_REG_LAST 83267338Stychon}; 84267338Stychon 85267338Stychonenum x2apic_state { 86267338Stychon X2APIC_DISABLED, 87267338Stychon X2APIC_ENABLED, 88267338Stychon X2APIC_STATE_LAST 89267338Stychon}; 90267338Stychon 91221828Sgrehan#ifdef _KERNEL 92221828Sgrehan 93221828Sgrehan#define VM_MAX_NAMELEN 32 94221828Sgrehan 95221828Sgrehanstruct vm; 96262506Sneelstruct vm_exception; 97221828Sgrehanstruct vm_memory_segment; 98221828Sgrehanstruct seg_desc; 99221828Sgrehanstruct vm_exit; 100221828Sgrehanstruct vm_run; 101258579Sneelstruct vhpet; 102258075Sneelstruct vioapic; 103221828Sgrehanstruct vlapic; 104256072Sneelstruct vmspace; 105256072Sneelstruct vm_object; 106256072Sneelstruct pmap; 107221828Sgrehan 108260466Sneeltypedef int (*vmm_init_func_t)(int ipinum); 109221828Sgrehantypedef int (*vmm_cleanup_func_t)(void); 110259782Sjhbtypedef void (*vmm_resume_func_t)(void); 111256072Sneeltypedef void * (*vmi_init_func_t)(struct vm *vm, struct pmap *pmap); 112256072Sneeltypedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip, 113263780Sneel struct pmap *pmap, void *rendezvous_cookie, 114263780Sneel void *suspend_cookie); 115221828Sgrehantypedef void (*vmi_cleanup_func_t)(void *vmi); 116221828Sgrehantypedef int (*vmi_get_register_t)(void *vmi, int vcpu, int num, 117221828Sgrehan uint64_t *retval); 118221828Sgrehantypedef int (*vmi_set_register_t)(void *vmi, int vcpu, int num, 119221828Sgrehan uint64_t val); 120221828Sgrehantypedef int (*vmi_get_desc_t)(void *vmi, int vcpu, int num, 121221828Sgrehan struct seg_desc *desc); 122221828Sgrehantypedef int (*vmi_set_desc_t)(void *vmi, int vcpu, int num, 123221828Sgrehan struct seg_desc *desc); 124221828Sgrehantypedef int (*vmi_get_cap_t)(void *vmi, int vcpu, int num, int *retval); 125221828Sgrehantypedef int (*vmi_set_cap_t)(void *vmi, int vcpu, int num, int val); 126256072Sneeltypedef struct vmspace * (*vmi_vmspace_alloc)(vm_offset_t min, vm_offset_t max); 127256072Sneeltypedef void (*vmi_vmspace_free)(struct vmspace *vmspace); 128259863Sneeltypedef struct vlapic * (*vmi_vlapic_init)(void *vmi, int vcpu); 129259863Sneeltypedef void (*vmi_vlapic_cleanup)(void *vmi, struct vlapic *vlapic); 130221828Sgrehan 131221828Sgrehanstruct vmm_ops { 132221828Sgrehan vmm_init_func_t init; /* module wide initialization */ 133221828Sgrehan vmm_cleanup_func_t cleanup; 134259782Sjhb vmm_resume_func_t resume; 135221828Sgrehan 136221828Sgrehan vmi_init_func_t vminit; /* vm-specific initialization */ 137221828Sgrehan vmi_run_func_t vmrun; 138221828Sgrehan vmi_cleanup_func_t vmcleanup; 139221828Sgrehan vmi_get_register_t vmgetreg; 140221828Sgrehan vmi_set_register_t vmsetreg; 141221828Sgrehan vmi_get_desc_t vmgetdesc; 142221828Sgrehan vmi_set_desc_t vmsetdesc; 143221828Sgrehan vmi_get_cap_t vmgetcap; 144221828Sgrehan vmi_set_cap_t vmsetcap; 145256072Sneel vmi_vmspace_alloc vmspace_alloc; 146256072Sneel vmi_vmspace_free vmspace_free; 147259863Sneel vmi_vlapic_init vlapic_init; 148259863Sneel vmi_vlapic_cleanup vlapic_cleanup; 149221828Sgrehan}; 150221828Sgrehan 151221828Sgrehanextern struct vmm_ops vmm_ops_intel; 152221828Sgrehanextern struct vmm_ops vmm_ops_amd; 153221828Sgrehan 154249396Sneelint vm_create(const char *name, struct vm **retvm); 155221828Sgrehanvoid vm_destroy(struct vm *vm); 156267216Sneelint vm_reinit(struct vm *vm); 157221828Sgrehanconst char *vm_name(struct vm *vm); 158241041Sneelint vm_malloc(struct vm *vm, vm_paddr_t gpa, size_t len); 159221828Sgrehanint vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa); 160221828Sgrehanint vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len); 161256072Sneelvoid *vm_gpa_hold(struct vm *, vm_paddr_t gpa, size_t len, int prot, 162256072Sneel void **cookie); 163256072Sneelvoid vm_gpa_release(void *cookie); 164221828Sgrehanint vm_gpabase2memseg(struct vm *vm, vm_paddr_t gpabase, 165221828Sgrehan struct vm_memory_segment *seg); 166256072Sneelint vm_get_memobj(struct vm *vm, vm_paddr_t gpa, size_t len, 167256072Sneel vm_offset_t *offset, struct vm_object **object); 168256072Sneelboolean_t vm_mem_allocated(struct vm *vm, vm_paddr_t gpa); 169221828Sgrehanint vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval); 170221828Sgrehanint vm_set_register(struct vm *vm, int vcpu, int reg, uint64_t val); 171221828Sgrehanint vm_get_seg_desc(struct vm *vm, int vcpu, int reg, 172221828Sgrehan struct seg_desc *ret_desc); 173221828Sgrehanint vm_set_seg_desc(struct vm *vm, int vcpu, int reg, 174221828Sgrehan struct seg_desc *desc); 175221828Sgrehanint vm_run(struct vm *vm, struct vm_run *vmrun); 176265062Sneelint vm_suspend(struct vm *vm, enum vm_suspend_how how); 177221828Sgrehanint vm_inject_nmi(struct vm *vm, int vcpu); 178241982Sneelint vm_nmi_pending(struct vm *vm, int vcpuid); 179241982Sneelvoid vm_nmi_clear(struct vm *vm, int vcpuid); 180263211Stychonint vm_inject_extint(struct vm *vm, int vcpu); 181263211Stychonint vm_extint_pending(struct vm *vm, int vcpuid); 182263211Stychonvoid vm_extint_clear(struct vm *vm, int vcpuid); 183221828Sgrehanuint64_t *vm_guest_msrs(struct vm *vm, int cpu); 184221828Sgrehanstruct vlapic *vm_lapic(struct vm *vm, int cpu); 185258075Sneelstruct vioapic *vm_ioapic(struct vm *vm); 186258579Sneelstruct vhpet *vm_hpet(struct vm *vm); 187221828Sgrehanint vm_get_capability(struct vm *vm, int vcpu, int type, int *val); 188221828Sgrehanint vm_set_capability(struct vm *vm, int vcpu, int type, int val); 189240922Sneelint vm_get_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state *state); 190240922Sneelint vm_set_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state state); 191258075Sneelint vm_apicid2vcpuid(struct vm *vm, int apicid); 192266933Sneelint vm_activate_cpu(struct vm *vm, int vcpu); 193223621Sgrehancpuset_t vm_active_cpus(struct vm *vm); 194266933Sneelcpuset_t vm_suspended_cpus(struct vm *vm); 195240894Sneelstruct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid); 196265062Sneelvoid vm_exit_suspended(struct vm *vm, int vcpuid, uint64_t rip); 197267330Sneelvoid vm_exit_rendezvous(struct vm *vm, int vcpuid, uint64_t rip); 198267330Sneelvoid vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip); 199221828Sgrehan 200221828Sgrehan/* 201260619Sneel * Rendezvous all vcpus specified in 'dest' and execute 'func(arg)'. 202260619Sneel * The rendezvous 'func(arg)' is not allowed to do anything that will 203260619Sneel * cause the thread to be put to sleep. 204260619Sneel * 205260619Sneel * If the rendezvous is being initiated from a vcpu context then the 206260619Sneel * 'vcpuid' must refer to that vcpu, otherwise it should be set to -1. 207260619Sneel * 208260619Sneel * The caller cannot hold any locks when initiating the rendezvous. 209260619Sneel * 210260619Sneel * The implementation of this API may cause vcpus other than those specified 211260619Sneel * by 'dest' to be stalled. The caller should not rely on any vcpus making 212260619Sneel * forward progress when the rendezvous is in progress. 213260619Sneel */ 214260619Sneeltypedef void (*vm_rendezvous_func_t)(struct vm *vm, int vcpuid, void *arg); 215260619Sneelvoid vm_smp_rendezvous(struct vm *vm, int vcpuid, cpuset_t dest, 216260619Sneel vm_rendezvous_func_t func, void *arg); 217260619Sneel 218260619Sneelstatic __inline int 219260619Sneelvcpu_rendezvous_pending(void *rendezvous_cookie) 220260619Sneel{ 221260619Sneel 222260619Sneel return (*(uintptr_t *)rendezvous_cookie != 0); 223260619Sneel} 224260619Sneel 225263780Sneelstatic __inline int 226263780Sneelvcpu_suspended(void *suspend_cookie) 227263780Sneel{ 228263780Sneel 229263780Sneel return (*(int *)suspend_cookie); 230263780Sneel} 231263780Sneel 232260619Sneel/* 233221828Sgrehan * Return 1 if device indicated by bus/slot/func is supposed to be a 234221828Sgrehan * pci passthrough device. 235221828Sgrehan * 236221828Sgrehan * Return 0 otherwise. 237221828Sgrehan */ 238221828Sgrehanint vmm_is_pptdev(int bus, int slot, int func); 239221828Sgrehan 240221828Sgrehanvoid *vm_iommu_domain(struct vm *vm); 241221828Sgrehan 242241489Sneelenum vcpu_state { 243241489Sneel VCPU_IDLE, 244256072Sneel VCPU_FROZEN, 245241489Sneel VCPU_RUNNING, 246256072Sneel VCPU_SLEEPING, 247241489Sneel}; 248221828Sgrehan 249259737Sneelint vcpu_set_state(struct vm *vm, int vcpu, enum vcpu_state state, 250259737Sneel bool from_idle); 251249879Sgrehanenum vcpu_state vcpu_get_state(struct vm *vm, int vcpu, int *hostcpu); 252221828Sgrehan 253221828Sgrehanstatic int __inline 254249879Sgrehanvcpu_is_running(struct vm *vm, int vcpu, int *hostcpu) 255221828Sgrehan{ 256249879Sgrehan return (vcpu_get_state(vm, vcpu, hostcpu) == VCPU_RUNNING); 257221828Sgrehan} 258221828Sgrehan 259241489Sneelvoid *vcpu_stats(struct vm *vm, int vcpu); 260259863Sneelvoid vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr); 261256072Sneelstruct vmspace *vm_get_vmspace(struct vm *vm); 262256072Sneelint vm_assign_pptdev(struct vm *vm, int bus, int slot, int func); 263256072Sneelint vm_unassign_pptdev(struct vm *vm, int bus, int slot, int func); 264263035Stychonstruct vatpic *vm_atpic(struct vm *vm); 265263744Stychonstruct vatpit *vm_atpit(struct vm *vm); 266262506Sneel 267262506Sneel/* 268262506Sneel * Inject exception 'vme' into the guest vcpu. This function returns 0 on 269262506Sneel * success and non-zero on failure. 270262506Sneel * 271262506Sneel * Wrapper functions like 'vm_inject_gp()' should be preferred to calling 272262506Sneel * this function directly because they enforce the trap-like or fault-like 273262506Sneel * behavior of an exception. 274262506Sneel * 275262506Sneel * This function should only be called in the context of the thread that is 276262506Sneel * executing this vcpu. 277262506Sneel */ 278262506Sneelint vm_inject_exception(struct vm *vm, int vcpuid, struct vm_exception *vme); 279262506Sneel 280262506Sneel/* 281262506Sneel * Returns 0 if there is no exception pending for this vcpu. Returns 1 if an 282262506Sneel * exception is pending and also updates 'vme'. The pending exception is 283262506Sneel * cleared when this function returns. 284262506Sneel * 285262506Sneel * This function should only be called in the context of the thread that is 286262506Sneel * executing this vcpu. 287262506Sneel */ 288262506Sneelint vm_exception_pending(struct vm *vm, int vcpuid, struct vm_exception *vme); 289262506Sneel 290262506Sneelvoid vm_inject_gp(struct vm *vm, int vcpuid); /* general protection fault */ 291262506Sneelvoid vm_inject_ud(struct vm *vm, int vcpuid); /* undefined instruction fault */ 292266626Sneelvoid vm_inject_pf(struct vm *vm, int vcpuid, int error_code, uint64_t cr2); 293262506Sneel 294266573Sneelenum vm_reg_name vm_segment_name(int seg_encoding); 295266573Sneel 296221828Sgrehan#endif /* KERNEL */ 297221828Sgrehan 298255438Sgrehan#define VM_MAXCPU 16 /* maximum virtual cpus */ 299221828Sgrehan 300221828Sgrehan/* 301221828Sgrehan * Identifiers for optional vmm capabilities 302221828Sgrehan */ 303221828Sgrehanenum vm_cap_type { 304221828Sgrehan VM_CAP_HALT_EXIT, 305221828Sgrehan VM_CAP_MTRAP_EXIT, 306221828Sgrehan VM_CAP_PAUSE_EXIT, 307221828Sgrehan VM_CAP_UNRESTRICTED_GUEST, 308256645Sneel VM_CAP_ENABLE_INVPCID, 309221828Sgrehan VM_CAP_MAX 310221828Sgrehan}; 311221828Sgrehan 312266125Sjhbenum vm_intr_trigger { 313266125Sjhb EDGE_TRIGGER, 314266125Sjhb LEVEL_TRIGGER 315266125Sjhb}; 316266125Sjhb 317221828Sgrehan/* 318221828Sgrehan * The 'access' field has the format specified in Table 21-2 of the Intel 319221828Sgrehan * Architecture Manual vol 3b. 320221828Sgrehan * 321221828Sgrehan * XXX The contents of the 'access' field are architecturally defined except 322221828Sgrehan * bit 16 - Segment Unusable. 323221828Sgrehan */ 324221828Sgrehanstruct seg_desc { 325221828Sgrehan uint64_t base; 326221828Sgrehan uint32_t limit; 327221828Sgrehan uint32_t access; 328221828Sgrehan}; 329268701Sneel#define SEG_DESC_TYPE(access) ((access) & 0x001f) 330268777Sneel#define SEG_DESC_DPL(access) (((access) >> 5) & 0x3) 331268701Sneel#define SEG_DESC_PRESENT(access) (((access) & 0x0080) ? 1 : 0) 332268701Sneel#define SEG_DESC_DEF32(access) (((access) & 0x4000) ? 1 : 0) 333268701Sneel#define SEG_DESC_GRANULARITY(access) (((access) & 0x8000) ? 1 : 0) 334268701Sneel#define SEG_DESC_UNUSABLE(access) (((access) & 0x10000) ? 1 : 0) 335221828Sgrehan 336266627Sneelenum vm_cpu_mode { 337268428Sneel CPU_MODE_REAL, 338268428Sneel CPU_MODE_PROTECTED, 339266627Sneel CPU_MODE_COMPATIBILITY, /* IA-32E mode (CS.L = 0) */ 340266627Sneel CPU_MODE_64BIT, /* IA-32E mode (CS.L = 1) */ 341266627Sneel}; 342266627Sneel 343266627Sneelenum vm_paging_mode { 344266627Sneel PAGING_MODE_FLAT, 345266627Sneel PAGING_MODE_32, 346266627Sneel PAGING_MODE_PAE, 347266627Sneel PAGING_MODE_64, 348266627Sneel}; 349266627Sneel 350266627Sneelstruct vm_guest_paging { 351266627Sneel uint64_t cr3; 352266627Sneel int cpl; 353266627Sneel enum vm_cpu_mode cpu_mode; 354266627Sneel enum vm_paging_mode paging_mode; 355266627Sneel}; 356266627Sneel 357266627Sneel/* 358266627Sneel * The data structures 'vie' and 'vie_op' are meant to be opaque to the 359266627Sneel * consumers of instruction decoding. The only reason why their contents 360266627Sneel * need to be exposed is because they are part of the 'vm_exit' structure. 361266627Sneel */ 362266627Sneelstruct vie_op { 363266627Sneel uint8_t op_byte; /* actual opcode byte */ 364266627Sneel uint8_t op_type; /* type of operation (e.g. MOV) */ 365266627Sneel uint16_t op_flags; 366266627Sneel}; 367266627Sneel 368266627Sneel#define VIE_INST_SIZE 15 369266627Sneelstruct vie { 370266627Sneel uint8_t inst[VIE_INST_SIZE]; /* instruction bytes */ 371266627Sneel uint8_t num_valid; /* size of the instruction */ 372266627Sneel uint8_t num_processed; 373266627Sneel 374268701Sneel uint8_t addrsize:4, opsize:4; /* address and operand sizes */ 375266627Sneel uint8_t rex_w:1, /* REX prefix */ 376266627Sneel rex_r:1, 377266627Sneel rex_x:1, 378266627Sneel rex_b:1, 379268701Sneel rex_present:1, 380268701Sneel opsize_override:1, /* Operand size override */ 381268701Sneel addrsize_override:1; /* Address size override */ 382266627Sneel 383266627Sneel uint8_t mod:2, /* ModRM byte */ 384266627Sneel reg:4, 385266627Sneel rm:4; 386266627Sneel 387266627Sneel uint8_t ss:2, /* SIB byte */ 388266627Sneel index:4, 389266627Sneel base:4; 390266627Sneel 391266627Sneel uint8_t disp_bytes; 392266627Sneel uint8_t imm_bytes; 393266627Sneel 394266627Sneel uint8_t scale; 395266627Sneel int base_register; /* VM_REG_GUEST_xyz */ 396266627Sneel int index_register; /* VM_REG_GUEST_xyz */ 397266627Sneel 398266627Sneel int64_t displacement; /* optional addr displacement */ 399266627Sneel int64_t immediate; /* optional immediate operand */ 400266627Sneel 401266627Sneel uint8_t decoded; /* set to 1 if successfully decoded */ 402266627Sneel 403266627Sneel struct vie_op op; /* opcode description */ 404266627Sneel}; 405266627Sneel 406221828Sgrehanenum vm_exitcode { 407221828Sgrehan VM_EXITCODE_INOUT, 408221828Sgrehan VM_EXITCODE_VMX, 409221828Sgrehan VM_EXITCODE_BOGUS, 410221828Sgrehan VM_EXITCODE_RDMSR, 411221828Sgrehan VM_EXITCODE_WRMSR, 412221828Sgrehan VM_EXITCODE_HLT, 413221828Sgrehan VM_EXITCODE_MTRAP, 414221828Sgrehan VM_EXITCODE_PAUSE, 415234761Sgrehan VM_EXITCODE_PAGING, 416256072Sneel VM_EXITCODE_INST_EMUL, 417240912Sneel VM_EXITCODE_SPINUP_AP, 418265101Sneel VM_EXITCODE_DEPRECATED1, /* used to be SPINDOWN_CPU */ 419260619Sneel VM_EXITCODE_RENDEZVOUS, 420261170Sneel VM_EXITCODE_IOAPIC_EOI, 421263780Sneel VM_EXITCODE_SUSPENDED, 422266573Sneel VM_EXITCODE_INOUT_STR, 423268777Sneel VM_EXITCODE_TASK_SWITCH, 424234761Sgrehan VM_EXITCODE_MAX 425221828Sgrehan}; 426221828Sgrehan 427266573Sneelstruct vm_inout { 428266573Sneel uint16_t bytes:3; /* 1 or 2 or 4 */ 429266573Sneel uint16_t in:1; 430266573Sneel uint16_t string:1; 431266573Sneel uint16_t rep:1; 432266573Sneel uint16_t port; 433266573Sneel uint32_t eax; /* valid for out */ 434266573Sneel}; 435266573Sneel 436266573Sneelstruct vm_inout_str { 437266573Sneel struct vm_inout inout; /* must be the first element */ 438266627Sneel struct vm_guest_paging paging; 439266573Sneel uint64_t rflags; 440266573Sneel uint64_t cr0; 441266573Sneel uint64_t index; 442266573Sneel uint64_t count; /* rep=1 (%rcx), rep=0 (1) */ 443266573Sneel int addrsize; 444266573Sneel enum vm_reg_name seg_name; 445266573Sneel struct seg_desc seg_desc; 446266573Sneel}; 447266573Sneel 448268777Sneelenum task_switch_reason { 449268777Sneel TSR_CALL, 450268777Sneel TSR_IRET, 451268777Sneel TSR_JMP, 452268777Sneel TSR_IDT_GATE, /* task gate in IDT */ 453268777Sneel}; 454268777Sneel 455268777Sneelstruct vm_task_switch { 456268777Sneel uint16_t tsssel; /* new TSS selector */ 457268777Sneel int ext; /* task switch due to external event */ 458268777Sneel uint32_t errcode; 459268777Sneel int errcode_valid; /* push 'errcode' on the new stack */ 460268777Sneel enum task_switch_reason reason; 461268777Sneel struct vm_guest_paging paging; 462268777Sneel}; 463268777Sneel 464221828Sgrehanstruct vm_exit { 465221828Sgrehan enum vm_exitcode exitcode; 466221828Sgrehan int inst_length; /* 0 means unknown */ 467221828Sgrehan uint64_t rip; 468221828Sgrehan union { 469266573Sneel struct vm_inout inout; 470266573Sneel struct vm_inout_str inout_str; 471221828Sgrehan struct { 472241497Sgrehan uint64_t gpa; 473256072Sneel int fault_type; 474256072Sneel } paging; 475256072Sneel struct { 476256072Sneel uint64_t gpa; 477256072Sneel uint64_t gla; 478268701Sneel int cs_d; /* CS.D */ 479266627Sneel struct vm_guest_paging paging; 480243640Sneel struct vie vie; 481256072Sneel } inst_emul; 482221828Sgrehan /* 483221828Sgrehan * VMX specific payload. Used when there is no "better" 484221828Sgrehan * exitcode to represent the VM-exit. 485221828Sgrehan */ 486221828Sgrehan struct { 487260167Sneel int status; /* vmx inst status */ 488260167Sneel /* 489260167Sneel * 'exit_reason' and 'exit_qualification' are valid 490260167Sneel * only if 'status' is zero. 491260167Sneel */ 492221828Sgrehan uint32_t exit_reason; 493221828Sgrehan uint64_t exit_qualification; 494260167Sneel /* 495260167Sneel * 'inst_error' and 'inst_type' are valid 496260167Sneel * only if 'status' is non-zero. 497260167Sneel */ 498260167Sneel int inst_type; 499260167Sneel int inst_error; 500221828Sgrehan } vmx; 501221828Sgrehan struct { 502221828Sgrehan uint32_t code; /* ecx value */ 503221828Sgrehan uint64_t wval; 504221828Sgrehan } msr; 505240912Sneel struct { 506240912Sneel int vcpu; 507240912Sneel uint64_t rip; 508240912Sneel } spinup_ap; 509259081Sneel struct { 510259081Sneel uint64_t rflags; 511259081Sneel } hlt; 512261170Sneel struct { 513261170Sneel int vector; 514261170Sneel } ioapic_eoi; 515265062Sneel struct { 516265062Sneel enum vm_suspend_how how; 517265062Sneel } suspended; 518268777Sneel struct vm_task_switch task_switch; 519221828Sgrehan } u; 520221828Sgrehan}; 521221828Sgrehan 522221828Sgrehan#endif /* _VMM_H_ */ 523