vmm.h revision 241041
199193Sjmallett/*-
299193Sjmallett * Copyright (c) 2011 NetApp, Inc.
399193Sjmallett * All rights reserved.
499193Sjmallett *
599193Sjmallett * Redistribution and use in source and binary forms, with or without
699193Sjmallett * modification, are permitted provided that the following conditions
799193Sjmallett * are met:
899193Sjmallett * 1. Redistributions of source code must retain the above copyright
999193Sjmallett *    notice, this list of conditions and the following disclaimer.
1099193Sjmallett * 2. Redistributions in binary form must reproduce the above copyright
1199193Sjmallett *    notice, this list of conditions and the following disclaimer in the
1299193Sjmallett *    documentation and/or other materials provided with the distribution.
1399193Sjmallett *
1499193Sjmallett * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
1599193Sjmallett * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1699193Sjmallett * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1799193Sjmallett * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
1899193Sjmallett * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1999193Sjmallett * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2099193Sjmallett * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2199193Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2299193Sjmallett * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2399193Sjmallett * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2499193Sjmallett * SUCH DAMAGE.
2599193Sjmallett *
2699193Sjmallett * $FreeBSD: vmm.h 482 2011-05-09 21:22:43Z grehan $
2799193Sjmallett */
2899193Sjmallett
2999193Sjmallett#ifndef _VMM_H_
3099193Sjmallett#define	_VMM_H_
3199193Sjmallett
3299193Sjmallett#ifdef _KERNEL
3399193Sjmallett
3499193Sjmallett#define	VM_MAX_NAMELEN	32
3599193Sjmallett
3699193Sjmallettstruct vm;
3799193Sjmallettstruct vm_memory_segment;
3899193Sjmallettstruct seg_desc;
3999193Sjmallettstruct vm_exit;
4099193Sjmallettstruct vm_run;
4199193Sjmallettstruct vlapic;
42109506Sjmallett
43109506Sjmallettenum x2apic_state;
4499193Sjmallett
4599193Sjmalletttypedef int	(*vmm_init_func_t)(void);
4699193Sjmalletttypedef int	(*vmm_cleanup_func_t)(void);
4799193Sjmalletttypedef void *	(*vmi_init_func_t)(struct vm *vm); /* instance specific apis */
4899193Sjmalletttypedef int	(*vmi_run_func_t)(void *vmi, int vcpu, register_t rip);
4999193Sjmalletttypedef void	(*vmi_cleanup_func_t)(void *vmi);
5099193Sjmalletttypedef int	(*vmi_mmap_func_t)(void *vmi, vm_paddr_t gpa, vm_paddr_t hpa,
51109506Sjmallett				   size_t length, vm_memattr_t attr,
52109506Sjmallett				   int prot, boolean_t superpages_ok);
53110066Sjmalletttypedef int	(*vmi_get_register_t)(void *vmi, int vcpu, int num,
54110066Sjmallett				      uint64_t *retval);
55109506Sjmalletttypedef int	(*vmi_set_register_t)(void *vmi, int vcpu, int num,
5699193Sjmallett				      uint64_t val);
5799193Sjmalletttypedef int	(*vmi_get_desc_t)(void *vmi, int vcpu, int num,
5899193Sjmallett				  struct seg_desc *desc);
5999193Sjmalletttypedef int	(*vmi_set_desc_t)(void *vmi, int vcpu, int num,
6099193Sjmallett				  struct seg_desc *desc);
61109462Sjmalletttypedef int	(*vmi_inject_event_t)(void *vmi, int vcpu,
6299193Sjmallett				      int type, int vector,
63109462Sjmallett				      uint32_t code, int code_valid);
64109462Sjmalletttypedef	int	(*vmi_inject_nmi_t)(void *vmi, int vcpu);
6599193Sjmalletttypedef int	(*vmi_get_cap_t)(void *vmi, int vcpu, int num, int *retval);
6699193Sjmalletttypedef int	(*vmi_set_cap_t)(void *vmi, int vcpu, int num, int val);
67109462Sjmallett
6899193Sjmallettstruct vmm_ops {
6999193Sjmallett	vmm_init_func_t		init;		/* module wide initialization */
7099193Sjmallett	vmm_cleanup_func_t	cleanup;
7199193Sjmallett
72109462Sjmallett	vmi_init_func_t		vminit;		/* vm-specific initialization */
7399193Sjmallett	vmi_run_func_t		vmrun;
7499193Sjmallett	vmi_cleanup_func_t	vmcleanup;
7599193Sjmallett	vmi_mmap_func_t		vmmmap;
7699193Sjmallett	vmi_get_register_t	vmgetreg;
7799193Sjmallett	vmi_set_register_t	vmsetreg;
7899193Sjmallett	vmi_get_desc_t		vmgetdesc;
7999193Sjmallett	vmi_set_desc_t		vmsetdesc;
8099193Sjmallett	vmi_inject_event_t	vminject;
81109462Sjmallett	vmi_inject_nmi_t	vmnmi;
8299193Sjmallett	vmi_get_cap_t		vmgetcap;
83109462Sjmallett	vmi_set_cap_t		vmsetcap;
84109462Sjmallett};
85109462Sjmallett
86109462Sjmallettextern struct vmm_ops vmm_ops_intel;
87109462Sjmallettextern struct vmm_ops vmm_ops_amd;
88109462Sjmallett
89109462Sjmallettstruct vm *vm_create(const char *name);
90109462Sjmallettvoid vm_destroy(struct vm *vm);
91109462Sjmallettconst char *vm_name(struct vm *vm);
92109462Sjmallettint vm_malloc(struct vm *vm, vm_paddr_t gpa, size_t len);
93109462Sjmallettint vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa);
94109462Sjmallettint vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len);
9599193Sjmallettvm_paddr_t vm_gpa2hpa(struct vm *vm, vm_paddr_t gpa, size_t size);
9699193Sjmallettint vm_gpabase2memseg(struct vm *vm, vm_paddr_t gpabase,
9799193Sjmallett	      struct vm_memory_segment *seg);
9899193Sjmallettint vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval);
9999193Sjmallettint vm_set_register(struct vm *vm, int vcpu, int reg, uint64_t val);
100109462Sjmallettint vm_get_seg_desc(struct vm *vm, int vcpu, int reg,
10199193Sjmallett		    struct seg_desc *ret_desc);
10299193Sjmallettint vm_set_seg_desc(struct vm *vm, int vcpu, int reg,
10399193Sjmallett		    struct seg_desc *desc);
10499193Sjmallettint vm_get_pinning(struct vm *vm, int vcpu, int *cpuid);
10599193Sjmallettint vm_set_pinning(struct vm *vm, int vcpu, int cpuid);
106109506Sjmallettint vm_run(struct vm *vm, struct vm_run *vmrun);
107109506Sjmallettint vm_inject_event(struct vm *vm, int vcpu, int type,
108109506Sjmallett		    int vector, uint32_t error_code, int error_code_valid);
109109506Sjmallettint vm_inject_nmi(struct vm *vm, int vcpu);
11099193Sjmallettuint64_t *vm_guest_msrs(struct vm *vm, int cpu);
11199193Sjmallettstruct vlapic *vm_lapic(struct vm *vm, int cpu);
11299193Sjmallettint vm_get_capability(struct vm *vm, int vcpu, int type, int *val);
11399193Sjmallettint vm_set_capability(struct vm *vm, int vcpu, int type, int val);
11499193Sjmallettint vm_get_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state *state);
11599193Sjmallettint vm_set_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state state);
116109755Sjmallettvoid vm_activate_cpu(struct vm *vm, int vcpu);
117109755Sjmallettcpuset_t vm_active_cpus(struct vm *vm);
118109755Sjmallettstruct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid);
119109755Sjmallett
120109755Sjmallett/*
121109755Sjmallett * Return 1 if device indicated by bus/slot/func is supposed to be a
122109755Sjmallett * pci passthrough device.
123109755Sjmallett *
124109755Sjmallett * Return 0 otherwise.
125109755Sjmallett */
126109755Sjmallettint vmm_is_pptdev(int bus, int slot, int func);
127109755Sjmallett
128109506Sjmallettvoid *vm_iommu_domain(struct vm *vm);
129109506Sjmallett
130109506Sjmallett#define	VCPU_STOPPED	0
131109506Sjmallett#define	VCPU_RUNNING	1
13299193Sjmallettvoid vm_set_run_state(struct vm *vm, int vcpu, int running);
13399193Sjmallettint vm_get_run_state(struct vm *vm, int vcpu, int *hostcpu);
134109462Sjmallett
13599222Sjmallettvoid *vcpu_stats(struct vm *vm, int vcpu);
136109506Sjmallett
137109506Sjmallettstatic int __inline
138109506Sjmallettvcpu_is_running(struct vm *vm, int vcpu, int *hostcpu)
139109506Sjmallett{
140109506Sjmallett	return (vm_get_run_state(vm, vcpu, hostcpu) == VCPU_RUNNING);
141109506Sjmallett}
142109506Sjmallett
143109506Sjmallett#endif	/* KERNEL */
144109506Sjmallett
145109506Sjmallett#define	VM_MAXCPU	8			/* maximum virtual cpus */
146109506Sjmallett
147109506Sjmallett/*
148109506Sjmallett * Identifiers for events that can be injected into the VM
149109506Sjmallett */
150109506Sjmallettenum vm_event_type {
15199193Sjmallett	VM_EVENT_NONE,
15299193Sjmallett	VM_HW_INTR,
153109506Sjmallett	VM_NMI,
15499193Sjmallett	VM_HW_EXCEPTION,
15599193Sjmallett	VM_SW_INTR,
15699193Sjmallett	VM_PRIV_SW_EXCEPTION,
15799193Sjmallett	VM_SW_EXCEPTION,
158109509Sjmallett	VM_EVENT_MAX
15999193Sjmallett};
16099193Sjmallett
16199823Sjmallett/*
16299823Sjmallett * Identifiers for architecturally defined registers.
163109518Sjmallett */
164109506Sjmallettenum vm_reg_name {
165101687Sjmallett	VM_REG_GUEST_RAX,
166105737Sjmallett	VM_REG_GUEST_RBX,
16799193Sjmallett	VM_REG_GUEST_RCX,
168109506Sjmallett	VM_REG_GUEST_RDX,
169109506Sjmallett	VM_REG_GUEST_RSI,
170109506Sjmallett	VM_REG_GUEST_RDI,
171109506Sjmallett	VM_REG_GUEST_RBP,
172109506Sjmallett	VM_REG_GUEST_R8,
173109506Sjmallett	VM_REG_GUEST_R9,
174109506Sjmallett	VM_REG_GUEST_R10,
175109506Sjmallett	VM_REG_GUEST_R11,
176109506Sjmallett	VM_REG_GUEST_R12,
177109506Sjmallett	VM_REG_GUEST_R13,
17899193Sjmallett	VM_REG_GUEST_R14,
17999193Sjmallett	VM_REG_GUEST_R15,
180110066Sjmallett	VM_REG_GUEST_CR0,
181110066Sjmallett	VM_REG_GUEST_CR3,
182110066Sjmallett	VM_REG_GUEST_CR4,
183110066Sjmallett	VM_REG_GUEST_DR7,
184110066Sjmallett	VM_REG_GUEST_RSP,
185110066Sjmallett	VM_REG_GUEST_RIP,
186110066Sjmallett	VM_REG_GUEST_RFLAGS,
187110066Sjmallett	VM_REG_GUEST_ES,
188110066Sjmallett	VM_REG_GUEST_CS,
189110066Sjmallett	VM_REG_GUEST_SS,
190110066Sjmallett	VM_REG_GUEST_DS,
191110066Sjmallett	VM_REG_GUEST_FS,
192110066Sjmallett	VM_REG_GUEST_GS,
193110066Sjmallett	VM_REG_GUEST_LDTR,
194110066Sjmallett	VM_REG_GUEST_TR,
195110066Sjmallett	VM_REG_GUEST_IDTR,
196110066Sjmallett	VM_REG_GUEST_GDTR,
197110066Sjmallett	VM_REG_GUEST_EFER,
198110066Sjmallett	VM_REG_LAST
199110066Sjmallett};
200110066Sjmallett
201110066Sjmallett/*
202110066Sjmallett * Identifiers for optional vmm capabilities
203110066Sjmallett */
204enum vm_cap_type {
205	VM_CAP_HALT_EXIT,
206	VM_CAP_MTRAP_EXIT,
207	VM_CAP_PAUSE_EXIT,
208	VM_CAP_UNRESTRICTED_GUEST,
209	VM_CAP_MAX
210};
211
212enum x2apic_state {
213	X2APIC_ENABLED,
214	X2APIC_AVAILABLE,
215	X2APIC_DISABLED,
216	X2APIC_STATE_LAST
217};
218
219/*
220 * The 'access' field has the format specified in Table 21-2 of the Intel
221 * Architecture Manual vol 3b.
222 *
223 * XXX The contents of the 'access' field are architecturally defined except
224 * bit 16 - Segment Unusable.
225 */
226struct seg_desc {
227	uint64_t	base;
228	uint32_t	limit;
229	uint32_t	access;
230};
231
232enum vm_exitcode {
233	VM_EXITCODE_INOUT,
234	VM_EXITCODE_VMX,
235	VM_EXITCODE_BOGUS,
236	VM_EXITCODE_RDMSR,
237	VM_EXITCODE_WRMSR,
238	VM_EXITCODE_HLT,
239	VM_EXITCODE_MTRAP,
240	VM_EXITCODE_PAUSE,
241	VM_EXITCODE_PAGING,
242	VM_EXITCODE_SPINUP_AP,
243	VM_EXITCODE_MAX
244};
245
246struct vm_exit {
247	enum vm_exitcode	exitcode;
248	int			inst_length;	/* 0 means unknown */
249	uint64_t		rip;
250	union {
251		struct {
252			uint16_t	bytes:3;	/* 1 or 2 or 4 */
253			uint16_t	in:1;		/* out is 0, in is 1 */
254			uint16_t	string:1;
255			uint16_t	rep:1;
256			uint16_t	port;
257			uint32_t	eax;		/* valid for out */
258		} inout;
259		struct {
260			uint64_t	cr3;
261		} paging;
262		/*
263		 * VMX specific payload. Used when there is no "better"
264		 * exitcode to represent the VM-exit.
265		 */
266		struct {
267			int		error;		/* vmx inst error */
268			uint32_t	exit_reason;
269			uint64_t	exit_qualification;
270		} vmx;
271		struct {
272			uint32_t	code;		/* ecx value */
273			uint64_t	wval;
274		} msr;
275		struct {
276			int		vcpu;
277			uint64_t	rip;
278		} spinup_ap;
279	} u;
280};
281
282#endif	/* _VMM_H_ */
283