vmm.h revision 266339
18549Sjkh/*-
28549Sjkh * Copyright (c) 2011 NetApp, Inc.
38549Sjkh * All rights reserved.
48549Sjkh *
58549Sjkh * Redistribution and use in source and binary forms, with or without
68549Sjkh * modification, are permitted provided that the following conditions
715440Sjkh * are met:
88549Sjkh * 1. Redistributions of source code must retain the above copyright
98549Sjkh *    notice, this list of conditions and the following disclaimer.
108549Sjkh * 2. Redistributions in binary form must reproduce the above copyright
118549Sjkh *    notice, this list of conditions and the following disclaimer in the
128549Sjkh *    documentation and/or other materials provided with the distribution.
138549Sjkh *
148549Sjkh * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
158549Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
168881Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
178881Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
188549Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
198549Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
208549Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
218549Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
228549Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
238549Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
248549Sjkh * SUCH DAMAGE.
258549Sjkh *
268549Sjkh * $FreeBSD: stable/10/sys/amd64/include/vmm.h 266339 2014-05-17 19:11:08Z jhb $
278549Sjkh */
288549Sjkh
298549Sjkh#ifndef _VMM_H_
308549Sjkh#define	_VMM_H_
318549Sjkh
328549Sjkh#ifdef _KERNEL
338549Sjkh
348549Sjkh#define	VM_MAX_NAMELEN	32
358549Sjkh
368549Sjkhstruct vm;
378549Sjkhstruct vm_memory_segment;
388549Sjkhstruct seg_desc;
398549Sjkhstruct vm_exit;
4010882Speterstruct vm_run;
4110882Speterstruct vhpet;
428549Sjkhstruct vioapic;
438549Sjkhstruct vlapic;
448549Sjkhstruct vmspace;
458549Sjkhstruct vm_object;
468549Sjkhstruct pmap;
478549Sjkh
488549Sjkhenum x2apic_state;
498549Sjkh
508549Sjkhtypedef int	(*vmm_init_func_t)(int ipinum);
518549Sjkhtypedef int	(*vmm_cleanup_func_t)(void);
528622Sjkhtypedef void	(*vmm_resume_func_t)(void);
538549Sjkhtypedef void *	(*vmi_init_func_t)(struct vm *vm, struct pmap *pmap);
548549Sjkhtypedef int	(*vmi_run_func_t)(void *vmi, int vcpu, register_t rip,
558702Sjkh				  struct pmap *pmap, void *rendezvous_cookie);
568549Sjkhtypedef void	(*vmi_cleanup_func_t)(void *vmi);
578672Sjkhtypedef int	(*vmi_get_register_t)(void *vmi, int vcpu, int num,
5812661Speter				      uint64_t *retval);
598549Sjkhtypedef int	(*vmi_set_register_t)(void *vmi, int vcpu, int num,
6012661Speter				      uint64_t val);
6112661Spetertypedef int	(*vmi_get_desc_t)(void *vmi, int vcpu, int num,
6212661Speter				  struct seg_desc *desc);
6312661Spetertypedef int	(*vmi_set_desc_t)(void *vmi, int vcpu, int num,
6412661Speter				  struct seg_desc *desc);
6512661Spetertypedef int	(*vmi_inject_event_t)(void *vmi, int vcpu,
6612661Speter				      int type, int vector,
6712661Speter				      uint32_t code, int code_valid);
6812661Spetertypedef int	(*vmi_get_cap_t)(void *vmi, int vcpu, int num, int *retval);
6915440Sjkhtypedef int	(*vmi_set_cap_t)(void *vmi, int vcpu, int num, int val);
7015440Sjkhtypedef struct vmspace * (*vmi_vmspace_alloc)(vm_offset_t min, vm_offset_t max);
7115440Sjkhtypedef void	(*vmi_vmspace_free)(struct vmspace *vmspace);
7215440Sjkhtypedef struct vlapic * (*vmi_vlapic_init)(void *vmi, int vcpu);
738549Sjkhtypedef void	(*vmi_vlapic_cleanup)(void *vmi, struct vlapic *vlapic);
748549Sjkh
758549Sjkhstruct vmm_ops {
768549Sjkh	vmm_init_func_t		init;		/* module wide initialization */
778549Sjkh	vmm_cleanup_func_t	cleanup;
788549Sjkh	vmm_resume_func_t	resume;
798549Sjkh
8015440Sjkh	vmi_init_func_t		vminit;		/* vm-specific initialization */
8115440Sjkh	vmi_run_func_t		vmrun;
8215440Sjkh	vmi_cleanup_func_t	vmcleanup;
8312661Speter	vmi_get_register_t	vmgetreg;
8412661Speter	vmi_set_register_t	vmsetreg;
8512661Speter	vmi_get_desc_t		vmgetdesc;
8615091Sjkh	vmi_set_desc_t		vmsetdesc;
8712661Speter	vmi_inject_event_t	vminject;
8812661Speter	vmi_get_cap_t		vmgetcap;
8915242Sjkh	vmi_set_cap_t		vmsetcap;
9015242Sjkh	vmi_vmspace_alloc	vmspace_alloc;
9112661Speter	vmi_vmspace_free	vmspace_free;
9212661Speter	vmi_vlapic_init		vlapic_init;
9312661Speter	vmi_vlapic_cleanup	vlapic_cleanup;
9412661Speter};
9512661Speter
9612661Speterextern struct vmm_ops vmm_ops_intel;
9712661Speterextern struct vmm_ops vmm_ops_amd;
9812661Speter
9915242Sjkhint vm_create(const char *name, struct vm **retvm);
10012661Spetervoid vm_destroy(struct vm *vm);
10115242Sjkhconst char *vm_name(struct vm *vm);
10215242Sjkhint vm_malloc(struct vm *vm, vm_paddr_t gpa, size_t len);
10315242Sjkhint vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa);
10412661Speterint vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len);
10515242Sjkhvoid *vm_gpa_hold(struct vm *, vm_paddr_t gpa, size_t len, int prot,
10615242Sjkh		  void **cookie);
10715419Sjkhvoid vm_gpa_release(void *cookie);
10815242Sjkhint vm_gpabase2memseg(struct vm *vm, vm_paddr_t gpabase,
10912661Speter	      struct vm_memory_segment *seg);
11015242Sjkhint vm_get_memobj(struct vm *vm, vm_paddr_t gpa, size_t len,
11115419Sjkh		  vm_offset_t *offset, struct vm_object **object);
11215242Sjkhboolean_t vm_mem_allocated(struct vm *vm, vm_paddr_t gpa);
11312661Speterint vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval);
11412661Speterint vm_set_register(struct vm *vm, int vcpu, int reg, uint64_t val);
11512661Speterint vm_get_seg_desc(struct vm *vm, int vcpu, int reg,
11612661Speter		    struct seg_desc *ret_desc);
11715091Sjkhint vm_set_seg_desc(struct vm *vm, int vcpu, int reg,
11812661Speter		    struct seg_desc *desc);
11912661Speterint vm_run(struct vm *vm, struct vm_run *vmrun);
12012661Speterint vm_inject_event(struct vm *vm, int vcpu, int type,
12112661Speter		    int vector, uint32_t error_code, int error_code_valid);
12212661Speterint vm_inject_nmi(struct vm *vm, int vcpu);
12314670Sjkhint vm_nmi_pending(struct vm *vm, int vcpuid);
12414670Sjkhvoid vm_nmi_clear(struct vm *vm, int vcpuid);
12515242Sjkhuint64_t *vm_guest_msrs(struct vm *vm, int cpu);
12614670Sjkhstruct vlapic *vm_lapic(struct vm *vm, int cpu);
12712661Speterstruct vioapic *vm_ioapic(struct vm *vm);
12812661Speterstruct vhpet *vm_hpet(struct vm *vm);
12915242Sjkhint vm_get_capability(struct vm *vm, int vcpu, int type, int *val);
13012661Speterint vm_set_capability(struct vm *vm, int vcpu, int type, int val);
13112661Speterint vm_get_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state *state);
13215419Sjkhint vm_set_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state state);
13315242Sjkhint vm_apicid2vcpuid(struct vm *vm, int apicid);
13415419Sjkhvoid vm_activate_cpu(struct vm *vm, int vcpu);
13515242Sjkhcpuset_t vm_active_cpus(struct vm *vm);
13612661Speterstruct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid);
13712661Speter
13812661Speter/*
13915242Sjkh * Rendezvous all vcpus specified in 'dest' and execute 'func(arg)'.
14012661Speter * The rendezvous 'func(arg)' is not allowed to do anything that will
14112661Speter * cause the thread to be put to sleep.
14212661Speter *
14312661Speter * If the rendezvous is being initiated from a vcpu context then the
1448549Sjkh * 'vcpuid' must refer to that vcpu, otherwise it should be set to -1.
1458549Sjkh *
1468549Sjkh * The caller cannot hold any locks when initiating the rendezvous.
1478549Sjkh *
1488549Sjkh * The implementation of this API may cause vcpus other than those specified
1498549Sjkh * by 'dest' to be stalled. The caller should not rely on any vcpus making
1508751Sjkh * forward progress when the rendezvous is in progress.
15114793Sjoerg */
15214793Sjoergtypedef void (*vm_rendezvous_func_t)(struct vm *vm, int vcpuid, void *arg);
1538549Sjkhvoid vm_smp_rendezvous(struct vm *vm, int vcpuid, cpuset_t dest,
1548549Sjkh    vm_rendezvous_func_t func, void *arg);
1558549Sjkh
1568549Sjkhstatic __inline int
1578549Sjkhvcpu_rendezvous_pending(void *rendezvous_cookie)
1588549Sjkh{
1598549Sjkh
1608549Sjkh	return (*(uintptr_t *)rendezvous_cookie != 0);
16112661Speter}
1628549Sjkh
1638549Sjkh/*
16412661Speter * Return 1 if device indicated by bus/slot/func is supposed to be a
1658549Sjkh * pci passthrough device.
1668549Sjkh *
1678549Sjkh * Return 0 otherwise.
1688549Sjkh */
1698549Sjkhint vmm_is_pptdev(int bus, int slot, int func);
1708549Sjkh
1718549Sjkhvoid *vm_iommu_domain(struct vm *vm);
1728549Sjkh
1738549Sjkhenum vcpu_state {
1748549Sjkh	VCPU_IDLE,
17512661Speter	VCPU_FROZEN,
1768549Sjkh	VCPU_RUNNING,
1778549Sjkh	VCPU_SLEEPING,
1788549Sjkh};
1798556Sjkh
1808549Sjkhint vcpu_set_state(struct vm *vm, int vcpu, enum vcpu_state state);
18115440Sjkhenum vcpu_state vcpu_get_state(struct vm *vm, int vcpu, int *hostcpu);
1828549Sjkh
1838556Sjkhstatic int __inline
1848549Sjkhvcpu_is_running(struct vm *vm, int vcpu, int *hostcpu)
1858556Sjkh{
1868556Sjkh	return (vcpu_get_state(vm, vcpu, hostcpu) == VCPU_RUNNING);
1878556Sjkh}
1888556Sjkh
1898556Sjkhvoid *vcpu_stats(struct vm *vm, int vcpu);
1908549Sjkhvoid vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr);
1918556Sjkhstruct vmspace *vm_get_vmspace(struct vm *vm);
1928556Sjkhint vm_assign_pptdev(struct vm *vm, int bus, int slot, int func);
1938549Sjkhint vm_unassign_pptdev(struct vm *vm, int bus, int slot, int func);
1948549Sjkh#endif	/* KERNEL */
1958549Sjkh
1968549Sjkh#include <machine/vmm_instruction_emul.h>
19715440Sjkh
1988549Sjkh#define	VM_MAXCPU	16			/* maximum virtual cpus */
1998549Sjkh
2008549Sjkh/*
20112661Speter * Identifiers for events that can be injected into the VM
2028556Sjkh */
2038556Sjkhenum vm_event_type {
2048556Sjkh	VM_EVENT_NONE,
2058556Sjkh	VM_HW_INTR,
2068556Sjkh	VM_NMI,
2078549Sjkh	VM_HW_EXCEPTION,
2088556Sjkh	VM_SW_INTR,
2098549Sjkh	VM_PRIV_SW_EXCEPTION,
2108549Sjkh	VM_SW_EXCEPTION,
2118549Sjkh	VM_EVENT_MAX
2128549Sjkh};
2138549Sjkh
2148549Sjkh/*
2158549Sjkh * Identifiers for architecturally defined registers.
2168549Sjkh */
2178549Sjkhenum vm_reg_name {
2188549Sjkh	VM_REG_GUEST_RAX,
2198549Sjkh	VM_REG_GUEST_RBX,
2208549Sjkh	VM_REG_GUEST_RCX,
2218549Sjkh	VM_REG_GUEST_RDX,
2228549Sjkh	VM_REG_GUEST_RSI,
2238549Sjkh	VM_REG_GUEST_RDI,
2248702Sjkh	VM_REG_GUEST_RBP,
2258549Sjkh	VM_REG_GUEST_R8,
2268549Sjkh	VM_REG_GUEST_R9,
2278549Sjkh	VM_REG_GUEST_R10,
2288549Sjkh	VM_REG_GUEST_R11,
2298549Sjkh	VM_REG_GUEST_R12,
2308549Sjkh	VM_REG_GUEST_R13,
23115440Sjkh	VM_REG_GUEST_R14,
23215440Sjkh	VM_REG_GUEST_R15,
23315440Sjkh	VM_REG_GUEST_CR0,
23415440Sjkh	VM_REG_GUEST_CR3,
2358549Sjkh	VM_REG_GUEST_CR4,
2368549Sjkh	VM_REG_GUEST_DR7,
2378549Sjkh	VM_REG_GUEST_RSP,
2388549Sjkh	VM_REG_GUEST_RIP,
2398665Sphk	VM_REG_GUEST_RFLAGS,
2408549Sjkh	VM_REG_GUEST_ES,
2418549Sjkh	VM_REG_GUEST_CS,
2429202Srgrimes	VM_REG_GUEST_SS,
2438549Sjkh	VM_REG_GUEST_DS,
2449202Srgrimes	VM_REG_GUEST_FS,
2459202Srgrimes	VM_REG_GUEST_GS,
2469202Srgrimes	VM_REG_GUEST_LDTR,
2478549Sjkh	VM_REG_GUEST_TR,
2488549Sjkh	VM_REG_GUEST_IDTR,
24914335Sjkh	VM_REG_GUEST_GDTR,
2508666Sphk	VM_REG_GUEST_EFER,
2518669Sphk	VM_REG_LAST
2528669Sphk};
2538820Sjkh
2548820Sjkh/*
2558881Srgrimes * Identifiers for optional vmm capabilities
2568820Sjkh */
2578666Sphkenum vm_cap_type {
2588666Sphk	VM_CAP_HALT_EXIT,
2598665Sphk	VM_CAP_MTRAP_EXIT,
2608665Sphk	VM_CAP_PAUSE_EXIT,
2618549Sjkh	VM_CAP_UNRESTRICTED_GUEST,
2628549Sjkh	VM_CAP_ENABLE_INVPCID,
2638549Sjkh	VM_CAP_MAX
2648549Sjkh};
26512661Speter
2668589Sjkhenum x2apic_state {
2678549Sjkh	X2APIC_ENABLED,
2688549Sjkh	X2APIC_AVAILABLE,
2698549Sjkh	X2APIC_DISABLED,
2708549Sjkh	X2APIC_STATE_LAST
27114793Sjoerg};
27214793Sjoerg
2738810Sjkh/*
2748810Sjkh * The 'access' field has the format specified in Table 21-2 of the Intel
2758810Sjkh * Architecture Manual vol 3b.
2768764Sjkh *
2778751Sjkh * XXX The contents of the 'access' field are architecturally defined except
2788751Sjkh * bit 16 - Segment Unusable.
2798751Sjkh */
28014793Sjoergstruct seg_desc {
28114793Sjoerg	uint64_t	base;
2828751Sjkh	uint32_t	limit;
2838669Sphk	uint32_t	access;
2848751Sjkh};
2858669Sphk
2868669Sphkenum vm_exitcode {
2878810Sjkh	VM_EXITCODE_INOUT,
2888669Sphk	VM_EXITCODE_VMX,
2898810Sjkh	VM_EXITCODE_BOGUS,
2908810Sjkh	VM_EXITCODE_RDMSR,
2918669Sphk	VM_EXITCODE_WRMSR,
2928669Sphk	VM_EXITCODE_HLT,
2938669Sphk	VM_EXITCODE_MTRAP,
2948549Sjkh	VM_EXITCODE_PAUSE,
2958810Sjkh	VM_EXITCODE_PAGING,
2968810Sjkh	VM_EXITCODE_INST_EMUL,
2978669Sphk	VM_EXITCODE_SPINUP_AP,
2988669Sphk	VM_EXITCODE_SPINDOWN_CPU,
2998669Sphk	VM_EXITCODE_RENDEZVOUS,
3008669Sphk	VM_EXITCODE_IOAPIC_EOI,
3018810Sjkh	VM_EXITCODE_MAX
3028810Sjkh};
3038669Sphk
3048669Sphkstruct vm_exit {
3058669Sphk	enum vm_exitcode	exitcode;
3068810Sjkh	int			inst_length;	/* 0 means unknown */
3078810Sjkh	uint64_t		rip;
3088669Sphk	union {
3098810Sjkh		struct {
3108810Sjkh			uint16_t	bytes:3;	/* 1 or 2 or 4 */
3118669Sphk			uint16_t	in:1;		/* out is 0, in is 1 */
3128669Sphk			uint16_t	string:1;
31314793Sjoerg			uint16_t	rep:1;
3148669Sphk			uint16_t	port;
3158669Sphk			uint32_t	eax;		/* valid for out */
3168669Sphk		} inout;
3178549Sjkh		struct {
3188549Sjkh			uint64_t	gpa;
3198549Sjkh			int		fault_type;
3208549Sjkh		} paging;
3218549Sjkh		struct {
3228549Sjkh			uint64_t	gpa;
3238549Sjkh			uint64_t	gla;
3248669Sphk			uint64_t	cr3;
32515440Sjkh			struct vie	vie;
3268669Sphk		} inst_emul;
3278549Sjkh		/*
3288549Sjkh		 * VMX specific payload. Used when there is no "better"
3298549Sjkh		 * exitcode to represent the VM-exit.
3308549Sjkh		 */
3318549Sjkh		struct {
3328549Sjkh			int		status;		/* vmx inst status */
3338669Sphk			/*
33412661Speter			 * 'exit_reason' and 'exit_qualification' are valid
33512661Speter			 * only if 'status' is zero.
33612661Speter			 */
33715440Sjkh			uint32_t	exit_reason;
3388669Sphk			uint64_t	exit_qualification;
3398549Sjkh			/*
3408549Sjkh			 * 'inst_error' and 'inst_type' are valid
3418549Sjkh			 * only if 'status' is non-zero.
3428549Sjkh			 */
3438549Sjkh			int		inst_type;
3448549Sjkh			int		inst_error;
3458549Sjkh		} vmx;
3468549Sjkh		struct {
3478549Sjkh			uint32_t	code;		/* ecx value */
3488549Sjkh			uint64_t	wval;
3498549Sjkh		} msr;
3508549Sjkh		struct {
3518549Sjkh			int		vcpu;
3528549Sjkh			uint64_t	rip;
3538549Sjkh		} spinup_ap;
35412661Speter		struct {
35512661Speter			uint64_t	rflags;
3568549Sjkh		} hlt;
3578549Sjkh		struct {
3588549Sjkh			int		vector;
3598549Sjkh		} ioapic_eoi;
3608549Sjkh	} u;
3618549Sjkh};
3628549Sjkh
3638549Sjkh#endif	/* _VMM_H_ */
3648549Sjkh