1366f6083SPeter Grehan /*- 2366f6083SPeter Grehan * Copyright (c) 2011 NetApp, Inc. 3366f6083SPeter Grehan * All rights reserved. 4366f6083SPeter Grehan * 5366f6083SPeter Grehan * Redistribution and use in source and binary forms, with or without 6366f6083SPeter Grehan * modification, are permitted provided that the following conditions 7366f6083SPeter Grehan * are met: 8366f6083SPeter Grehan * 1. Redistributions of source code must retain the above copyright 9366f6083SPeter Grehan * notice, this list of conditions and the following disclaimer. 10366f6083SPeter Grehan * 2. Redistributions in binary form must reproduce the above copyright 11366f6083SPeter Grehan * notice, this list of conditions and the following disclaimer in the 12366f6083SPeter Grehan * documentation and/or other materials provided with the distribution. 13366f6083SPeter Grehan * 14366f6083SPeter Grehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15366f6083SPeter Grehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16366f6083SPeter Grehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17366f6083SPeter Grehan * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18366f6083SPeter Grehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19366f6083SPeter Grehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20366f6083SPeter Grehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21366f6083SPeter Grehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22366f6083SPeter Grehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23366f6083SPeter Grehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24366f6083SPeter Grehan * SUCH DAMAGE. 25366f6083SPeter Grehan * 26366f6083SPeter Grehan * $FreeBSD: vmm.h 482 2011-05-09 21:22:43Z grehan $ 27366f6083SPeter Grehan */ 28366f6083SPeter Grehan 29366f6083SPeter Grehan #ifndef _VMM_H_ 30366f6083SPeter Grehan #define _VMM_H_ 31366f6083SPeter Grehan 32366f6083SPeter Grehan #ifdef _KERNEL 33366f6083SPeter Grehan 34366f6083SPeter Grehan #define VM_MAX_NAMELEN 32 35366f6083SPeter Grehan 36366f6083SPeter Grehan struct vm; 37366f6083SPeter Grehan struct vm_memory_segment; 38366f6083SPeter Grehan struct seg_desc; 39366f6083SPeter Grehan struct vm_exit; 40366f6083SPeter Grehan struct vm_run; 41366f6083SPeter Grehan struct vlapic; 42366f6083SPeter Grehan 43366f6083SPeter Grehan typedef int (*vmm_init_func_t)(void); 44366f6083SPeter Grehan typedef int (*vmm_cleanup_func_t)(void); 45366f6083SPeter Grehan typedef void * (*vmi_init_func_t)(struct vm *vm); /* instance specific apis */ 46366f6083SPeter Grehan typedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip, 47366f6083SPeter Grehan struct vm_exit *vmexit); 48366f6083SPeter Grehan typedef void (*vmi_cleanup_func_t)(void *vmi); 49366f6083SPeter Grehan typedef int (*vmi_mmap_func_t)(void *vmi, vm_paddr_t gpa, vm_paddr_t hpa, 50366f6083SPeter Grehan size_t length, vm_memattr_t attr, 51366f6083SPeter Grehan int prot, boolean_t superpages_ok); 52366f6083SPeter Grehan typedef int (*vmi_get_register_t)(void *vmi, int vcpu, int num, 53366f6083SPeter Grehan uint64_t *retval); 54366f6083SPeter Grehan typedef int (*vmi_set_register_t)(void *vmi, int vcpu, int num, 55366f6083SPeter Grehan uint64_t val); 56366f6083SPeter Grehan typedef int (*vmi_get_desc_t)(void *vmi, int vcpu, int num, 57366f6083SPeter Grehan struct seg_desc *desc); 58366f6083SPeter Grehan typedef int (*vmi_set_desc_t)(void *vmi, int vcpu, int num, 59366f6083SPeter Grehan struct seg_desc *desc); 60366f6083SPeter Grehan typedef int (*vmi_inject_event_t)(void *vmi, int vcpu, 61366f6083SPeter Grehan int type, int vector, 62366f6083SPeter Grehan uint32_t code, int code_valid); 63366f6083SPeter Grehan typedef int (*vmi_inject_nmi_t)(void *vmi, int vcpu); 64366f6083SPeter Grehan typedef int (*vmi_get_cap_t)(void *vmi, int vcpu, int num, int *retval); 65366f6083SPeter Grehan typedef int (*vmi_set_cap_t)(void *vmi, int vcpu, int num, int val); 66366f6083SPeter Grehan 67366f6083SPeter Grehan struct vmm_ops { 68366f6083SPeter Grehan vmm_init_func_t init; /* module wide initialization */ 69366f6083SPeter Grehan vmm_cleanup_func_t cleanup; 70366f6083SPeter Grehan 71366f6083SPeter Grehan vmi_init_func_t vminit; /* vm-specific initialization */ 72366f6083SPeter Grehan vmi_run_func_t vmrun; 73366f6083SPeter Grehan vmi_cleanup_func_t vmcleanup; 74366f6083SPeter Grehan vmi_mmap_func_t vmmmap; 75366f6083SPeter Grehan vmi_get_register_t vmgetreg; 76366f6083SPeter Grehan vmi_set_register_t vmsetreg; 77366f6083SPeter Grehan vmi_get_desc_t vmgetdesc; 78366f6083SPeter Grehan vmi_set_desc_t vmsetdesc; 79366f6083SPeter Grehan vmi_inject_event_t vminject; 80366f6083SPeter Grehan vmi_inject_nmi_t vmnmi; 81366f6083SPeter Grehan vmi_get_cap_t vmgetcap; 82366f6083SPeter Grehan vmi_set_cap_t vmsetcap; 83366f6083SPeter Grehan }; 84366f6083SPeter Grehan 85366f6083SPeter Grehan extern struct vmm_ops vmm_ops_intel; 86366f6083SPeter Grehan extern struct vmm_ops vmm_ops_amd; 87366f6083SPeter Grehan 88366f6083SPeter Grehan struct vm *vm_create(const char *name); 89366f6083SPeter Grehan void vm_destroy(struct vm *vm); 90366f6083SPeter Grehan const char *vm_name(struct vm *vm); 91366f6083SPeter Grehan int vm_malloc(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t *ret_hpa); 92366f6083SPeter Grehan int vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa); 93366f6083SPeter Grehan int vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len); 94366f6083SPeter Grehan vm_paddr_t vm_gpa2hpa(struct vm *vm, vm_paddr_t gpa, size_t size); 95366f6083SPeter Grehan int vm_gpabase2memseg(struct vm *vm, vm_paddr_t gpabase, 96366f6083SPeter Grehan struct vm_memory_segment *seg); 97366f6083SPeter Grehan int vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval); 98366f6083SPeter Grehan int vm_set_register(struct vm *vm, int vcpu, int reg, uint64_t val); 99366f6083SPeter Grehan int vm_get_seg_desc(struct vm *vm, int vcpu, int reg, 100366f6083SPeter Grehan struct seg_desc *ret_desc); 101366f6083SPeter Grehan int vm_set_seg_desc(struct vm *vm, int vcpu, int reg, 102366f6083SPeter Grehan struct seg_desc *desc); 103366f6083SPeter Grehan int vm_get_pinning(struct vm *vm, int vcpu, int *cpuid); 104366f6083SPeter Grehan int vm_set_pinning(struct vm *vm, int vcpu, int cpuid); 105366f6083SPeter Grehan int vm_run(struct vm *vm, struct vm_run *vmrun); 106366f6083SPeter Grehan int vm_inject_event(struct vm *vm, int vcpu, int type, 107366f6083SPeter Grehan int vector, uint32_t error_code, int error_code_valid); 108366f6083SPeter Grehan int vm_inject_nmi(struct vm *vm, int vcpu); 109366f6083SPeter Grehan uint64_t *vm_guest_msrs(struct vm *vm, int cpu); 110366f6083SPeter Grehan struct vlapic *vm_lapic(struct vm *vm, int cpu); 111366f6083SPeter Grehan int vm_get_capability(struct vm *vm, int vcpu, int type, int *val); 112366f6083SPeter Grehan int vm_set_capability(struct vm *vm, int vcpu, int type, int val); 113366f6083SPeter Grehan void vm_activate_cpu(struct vm *vm, int vcpu); 114a5615c90SPeter Grehan cpuset_t vm_active_cpus(struct vm *vm); 115366f6083SPeter Grehan 116366f6083SPeter Grehan /* 117366f6083SPeter Grehan * Return 1 if device indicated by bus/slot/func is supposed to be a 118366f6083SPeter Grehan * pci passthrough device. 119366f6083SPeter Grehan * 120366f6083SPeter Grehan * Return 0 otherwise. 121366f6083SPeter Grehan */ 122366f6083SPeter Grehan int vmm_is_pptdev(int bus, int slot, int func); 123366f6083SPeter Grehan 124366f6083SPeter Grehan void *vm_iommu_domain(struct vm *vm); 125366f6083SPeter Grehan 126366f6083SPeter Grehan #define VCPU_STOPPED 0 127366f6083SPeter Grehan #define VCPU_RUNNING 1 128366f6083SPeter Grehan void vm_set_run_state(struct vm *vm, int vcpu, int running); 129366f6083SPeter Grehan int vm_get_run_state(struct vm *vm, int vcpu, int *hostcpu); 130366f6083SPeter Grehan 131366f6083SPeter Grehan void *vcpu_stats(struct vm *vm, int vcpu); 132366f6083SPeter Grehan 133366f6083SPeter Grehan static int __inline 134366f6083SPeter Grehan vcpu_is_running(struct vm *vm, int vcpu, int *hostcpu) 135366f6083SPeter Grehan { 136366f6083SPeter Grehan return (vm_get_run_state(vm, vcpu, hostcpu) == VCPU_RUNNING); 137366f6083SPeter Grehan } 138366f6083SPeter Grehan 139366f6083SPeter Grehan #endif /* KERNEL */ 140366f6083SPeter Grehan 141366f6083SPeter Grehan #define VM_MAXCPU 8 /* maximum virtual cpus */ 142366f6083SPeter Grehan 143366f6083SPeter Grehan /* 144366f6083SPeter Grehan * Identifiers for events that can be injected into the VM 145366f6083SPeter Grehan */ 146366f6083SPeter Grehan enum vm_event_type { 147366f6083SPeter Grehan VM_EVENT_NONE, 148366f6083SPeter Grehan VM_HW_INTR, 149366f6083SPeter Grehan VM_NMI, 150366f6083SPeter Grehan VM_HW_EXCEPTION, 151366f6083SPeter Grehan VM_SW_INTR, 152366f6083SPeter Grehan VM_PRIV_SW_EXCEPTION, 153366f6083SPeter Grehan VM_SW_EXCEPTION, 154366f6083SPeter Grehan VM_EVENT_MAX 155366f6083SPeter Grehan }; 156366f6083SPeter Grehan 157366f6083SPeter Grehan /* 158366f6083SPeter Grehan * Identifiers for architecturally defined registers. 159366f6083SPeter Grehan */ 160366f6083SPeter Grehan enum vm_reg_name { 161366f6083SPeter Grehan VM_REG_GUEST_RAX, 162366f6083SPeter Grehan VM_REG_GUEST_RBX, 163366f6083SPeter Grehan VM_REG_GUEST_RCX, 164366f6083SPeter Grehan VM_REG_GUEST_RDX, 165366f6083SPeter Grehan VM_REG_GUEST_RSI, 166366f6083SPeter Grehan VM_REG_GUEST_RDI, 167366f6083SPeter Grehan VM_REG_GUEST_RBP, 168366f6083SPeter Grehan VM_REG_GUEST_R8, 169366f6083SPeter Grehan VM_REG_GUEST_R9, 170366f6083SPeter Grehan VM_REG_GUEST_R10, 171366f6083SPeter Grehan VM_REG_GUEST_R11, 172366f6083SPeter Grehan VM_REG_GUEST_R12, 173366f6083SPeter Grehan VM_REG_GUEST_R13, 174366f6083SPeter Grehan VM_REG_GUEST_R14, 175366f6083SPeter Grehan VM_REG_GUEST_R15, 176366f6083SPeter Grehan VM_REG_GUEST_CR0, 177366f6083SPeter Grehan VM_REG_GUEST_CR3, 178366f6083SPeter Grehan VM_REG_GUEST_CR4, 179366f6083SPeter Grehan VM_REG_GUEST_DR7, 180366f6083SPeter Grehan VM_REG_GUEST_RSP, 181366f6083SPeter Grehan VM_REG_GUEST_RIP, 182366f6083SPeter Grehan VM_REG_GUEST_RFLAGS, 183366f6083SPeter Grehan VM_REG_GUEST_ES, 184366f6083SPeter Grehan VM_REG_GUEST_CS, 185366f6083SPeter Grehan VM_REG_GUEST_SS, 186366f6083SPeter Grehan VM_REG_GUEST_DS, 187366f6083SPeter Grehan VM_REG_GUEST_FS, 188366f6083SPeter Grehan VM_REG_GUEST_GS, 189366f6083SPeter Grehan VM_REG_GUEST_LDTR, 190366f6083SPeter Grehan VM_REG_GUEST_TR, 191366f6083SPeter Grehan VM_REG_GUEST_IDTR, 192366f6083SPeter Grehan VM_REG_GUEST_GDTR, 193366f6083SPeter Grehan VM_REG_GUEST_EFER, 194366f6083SPeter Grehan VM_REG_LAST 195366f6083SPeter Grehan }; 196366f6083SPeter Grehan 197366f6083SPeter Grehan /* 198366f6083SPeter Grehan * Identifiers for optional vmm capabilities 199366f6083SPeter Grehan */ 200366f6083SPeter Grehan enum vm_cap_type { 201366f6083SPeter Grehan VM_CAP_HALT_EXIT, 202366f6083SPeter Grehan VM_CAP_MTRAP_EXIT, 203366f6083SPeter Grehan VM_CAP_PAUSE_EXIT, 204366f6083SPeter Grehan VM_CAP_UNRESTRICTED_GUEST, 205366f6083SPeter Grehan VM_CAP_MAX 206366f6083SPeter Grehan }; 207366f6083SPeter Grehan 208366f6083SPeter Grehan /* 209366f6083SPeter Grehan * The 'access' field has the format specified in Table 21-2 of the Intel 210366f6083SPeter Grehan * Architecture Manual vol 3b. 211366f6083SPeter Grehan * 212366f6083SPeter Grehan * XXX The contents of the 'access' field are architecturally defined except 213366f6083SPeter Grehan * bit 16 - Segment Unusable. 214366f6083SPeter Grehan */ 215366f6083SPeter Grehan struct seg_desc { 216366f6083SPeter Grehan uint64_t base; 217366f6083SPeter Grehan uint32_t limit; 218366f6083SPeter Grehan uint32_t access; 219366f6083SPeter Grehan }; 220366f6083SPeter Grehan 221366f6083SPeter Grehan enum vm_exitcode { 222366f6083SPeter Grehan VM_EXITCODE_INOUT, 223366f6083SPeter Grehan VM_EXITCODE_VMX, 224366f6083SPeter Grehan VM_EXITCODE_BOGUS, 225366f6083SPeter Grehan VM_EXITCODE_RDMSR, 226366f6083SPeter Grehan VM_EXITCODE_WRMSR, 227366f6083SPeter Grehan VM_EXITCODE_HLT, 228366f6083SPeter Grehan VM_EXITCODE_MTRAP, 229366f6083SPeter Grehan VM_EXITCODE_PAUSE, 230cd942e0fSPeter Grehan VM_EXITCODE_PAGING, 231cd942e0fSPeter Grehan VM_EXITCODE_MAX 232366f6083SPeter Grehan }; 233366f6083SPeter Grehan 234366f6083SPeter Grehan struct vm_exit { 235366f6083SPeter Grehan enum vm_exitcode exitcode; 236366f6083SPeter Grehan int inst_length; /* 0 means unknown */ 237366f6083SPeter Grehan uint64_t rip; 238366f6083SPeter Grehan union { 239366f6083SPeter Grehan struct { 240366f6083SPeter Grehan uint16_t bytes:3; /* 1 or 2 or 4 */ 241366f6083SPeter Grehan uint16_t in:1; /* out is 0, in is 1 */ 242366f6083SPeter Grehan uint16_t string:1; 243366f6083SPeter Grehan uint16_t rep:1; 244366f6083SPeter Grehan uint16_t port; 245366f6083SPeter Grehan uint32_t eax; /* valid for out */ 246366f6083SPeter Grehan } inout; 247cd942e0fSPeter Grehan struct { 248cd942e0fSPeter Grehan uint64_t cr3; 249cd942e0fSPeter Grehan } paging; 250366f6083SPeter Grehan /* 251366f6083SPeter Grehan * VMX specific payload. Used when there is no "better" 252366f6083SPeter Grehan * exitcode to represent the VM-exit. 253366f6083SPeter Grehan */ 254366f6083SPeter Grehan struct { 255366f6083SPeter Grehan int error; /* vmx inst error */ 256366f6083SPeter Grehan uint32_t exit_reason; 257366f6083SPeter Grehan uint64_t exit_qualification; 258366f6083SPeter Grehan } vmx; 259366f6083SPeter Grehan struct { 260366f6083SPeter Grehan uint32_t code; /* ecx value */ 261366f6083SPeter Grehan uint64_t wval; 262366f6083SPeter Grehan } msr; 263366f6083SPeter Grehan } u; 264366f6083SPeter Grehan }; 265366f6083SPeter Grehan 266366f6083SPeter Grehan #endif /* _VMM_H_ */ 267