xref: /freebsd/sys/amd64/include/vmm.h (revision cfdea69d)
1366f6083SPeter Grehan /*-
2c49761ddSPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3c49761ddSPedro F. Giffuni  *
4366f6083SPeter Grehan  * Copyright (c) 2011 NetApp, Inc.
5366f6083SPeter Grehan  * All rights reserved.
6366f6083SPeter Grehan  *
7366f6083SPeter Grehan  * Redistribution and use in source and binary forms, with or without
8366f6083SPeter Grehan  * modification, are permitted provided that the following conditions
9366f6083SPeter Grehan  * are met:
10366f6083SPeter Grehan  * 1. Redistributions of source code must retain the above copyright
11366f6083SPeter Grehan  *    notice, this list of conditions and the following disclaimer.
12366f6083SPeter Grehan  * 2. Redistributions in binary form must reproduce the above copyright
13366f6083SPeter Grehan  *    notice, this list of conditions and the following disclaimer in the
14366f6083SPeter Grehan  *    documentation and/or other materials provided with the distribution.
15366f6083SPeter Grehan  *
16366f6083SPeter Grehan  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
17366f6083SPeter Grehan  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18366f6083SPeter Grehan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19366f6083SPeter Grehan  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
20366f6083SPeter Grehan  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21366f6083SPeter Grehan  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22366f6083SPeter Grehan  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23366f6083SPeter Grehan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24366f6083SPeter Grehan  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25366f6083SPeter Grehan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26366f6083SPeter Grehan  * SUCH DAMAGE.
27366f6083SPeter Grehan  *
28912a3e67SNeel Natu  * $FreeBSD$
29366f6083SPeter Grehan  */
30366f6083SPeter Grehan 
31366f6083SPeter Grehan #ifndef _VMM_H_
32366f6083SPeter Grehan #define	_VMM_H_
33366f6083SPeter Grehan 
346ac73777STycho Nightingale #include <sys/sdt.h>
35d37f2adbSNeel Natu #include <x86/segments.h>
36d37f2adbSNeel Natu 
376ac73777STycho Nightingale #ifdef _KERNEL
386ac73777STycho Nightingale SDT_PROVIDER_DECLARE(vmm);
396ac73777STycho Nightingale #endif
406ac73777STycho Nightingale 
41f0fdcfe2SNeel Natu enum vm_suspend_how {
42f0fdcfe2SNeel Natu 	VM_SUSPEND_NONE,
43f0fdcfe2SNeel Natu 	VM_SUSPEND_RESET,
44f0fdcfe2SNeel Natu 	VM_SUSPEND_POWEROFF,
45e50ce2aaSNeel Natu 	VM_SUSPEND_HALT,
46091d4532SNeel Natu 	VM_SUSPEND_TRIPLEFAULT,
47f0fdcfe2SNeel Natu 	VM_SUSPEND_LAST
48f0fdcfe2SNeel Natu };
49f0fdcfe2SNeel Natu 
505ebc578bSTycho Nightingale /*
515ebc578bSTycho Nightingale  * Identifiers for architecturally defined registers.
525ebc578bSTycho Nightingale  */
535ebc578bSTycho Nightingale enum vm_reg_name {
545ebc578bSTycho Nightingale 	VM_REG_GUEST_RAX,
555ebc578bSTycho Nightingale 	VM_REG_GUEST_RBX,
565ebc578bSTycho Nightingale 	VM_REG_GUEST_RCX,
575ebc578bSTycho Nightingale 	VM_REG_GUEST_RDX,
585ebc578bSTycho Nightingale 	VM_REG_GUEST_RSI,
595ebc578bSTycho Nightingale 	VM_REG_GUEST_RDI,
605ebc578bSTycho Nightingale 	VM_REG_GUEST_RBP,
615ebc578bSTycho Nightingale 	VM_REG_GUEST_R8,
625ebc578bSTycho Nightingale 	VM_REG_GUEST_R9,
635ebc578bSTycho Nightingale 	VM_REG_GUEST_R10,
645ebc578bSTycho Nightingale 	VM_REG_GUEST_R11,
655ebc578bSTycho Nightingale 	VM_REG_GUEST_R12,
665ebc578bSTycho Nightingale 	VM_REG_GUEST_R13,
675ebc578bSTycho Nightingale 	VM_REG_GUEST_R14,
685ebc578bSTycho Nightingale 	VM_REG_GUEST_R15,
695ebc578bSTycho Nightingale 	VM_REG_GUEST_CR0,
705ebc578bSTycho Nightingale 	VM_REG_GUEST_CR3,
715ebc578bSTycho Nightingale 	VM_REG_GUEST_CR4,
725ebc578bSTycho Nightingale 	VM_REG_GUEST_DR7,
735ebc578bSTycho Nightingale 	VM_REG_GUEST_RSP,
745ebc578bSTycho Nightingale 	VM_REG_GUEST_RIP,
755ebc578bSTycho Nightingale 	VM_REG_GUEST_RFLAGS,
765ebc578bSTycho Nightingale 	VM_REG_GUEST_ES,
775ebc578bSTycho Nightingale 	VM_REG_GUEST_CS,
785ebc578bSTycho Nightingale 	VM_REG_GUEST_SS,
795ebc578bSTycho Nightingale 	VM_REG_GUEST_DS,
805ebc578bSTycho Nightingale 	VM_REG_GUEST_FS,
815ebc578bSTycho Nightingale 	VM_REG_GUEST_GS,
825ebc578bSTycho Nightingale 	VM_REG_GUEST_LDTR,
835ebc578bSTycho Nightingale 	VM_REG_GUEST_TR,
845ebc578bSTycho Nightingale 	VM_REG_GUEST_IDTR,
855ebc578bSTycho Nightingale 	VM_REG_GUEST_GDTR,
865ebc578bSTycho Nightingale 	VM_REG_GUEST_EFER,
875ebc578bSTycho Nightingale 	VM_REG_GUEST_CR2,
883d5444c8SNeel Natu 	VM_REG_GUEST_PDPTE0,
893d5444c8SNeel Natu 	VM_REG_GUEST_PDPTE1,
903d5444c8SNeel Natu 	VM_REG_GUEST_PDPTE2,
913d5444c8SNeel Natu 	VM_REG_GUEST_PDPTE3,
92d1819632SNeel Natu 	VM_REG_GUEST_INTR_SHADOW,
9365eefbe4SJohn Baldwin 	VM_REG_GUEST_DR0,
9465eefbe4SJohn Baldwin 	VM_REG_GUEST_DR1,
9565eefbe4SJohn Baldwin 	VM_REG_GUEST_DR2,
9665eefbe4SJohn Baldwin 	VM_REG_GUEST_DR3,
9765eefbe4SJohn Baldwin 	VM_REG_GUEST_DR6,
98cbd03a9dSJohn Baldwin 	VM_REG_GUEST_ENTRY_INST_LENGTH,
995ebc578bSTycho Nightingale 	VM_REG_LAST
1005ebc578bSTycho Nightingale };
1015ebc578bSTycho Nightingale 
1025ebc578bSTycho Nightingale enum x2apic_state {
1035ebc578bSTycho Nightingale 	X2APIC_DISABLED,
1045ebc578bSTycho Nightingale 	X2APIC_ENABLED,
1055ebc578bSTycho Nightingale 	X2APIC_STATE_LAST
1065ebc578bSTycho Nightingale };
1075ebc578bSTycho Nightingale 
108091d4532SNeel Natu #define	VM_INTINFO_VECTOR(info)	((info) & 0xff)
109091d4532SNeel Natu #define	VM_INTINFO_DEL_ERRCODE	0x800
110091d4532SNeel Natu #define	VM_INTINFO_RSVD		0x7ffff000
111091d4532SNeel Natu #define	VM_INTINFO_VALID	0x80000000
112091d4532SNeel Natu #define	VM_INTINFO_TYPE		0x700
113091d4532SNeel Natu #define	VM_INTINFO_HWINTR	(0 << 8)
114091d4532SNeel Natu #define	VM_INTINFO_NMI		(2 << 8)
115091d4532SNeel Natu #define	VM_INTINFO_HWEXCEPTION	(3 << 8)
116091d4532SNeel Natu #define	VM_INTINFO_SWINTR	(4 << 8)
117091d4532SNeel Natu 
118422a8a4dSScott Long /*
119422a8a4dSScott Long  * The VM name has to fit into the pathname length constraints of devfs,
120422a8a4dSScott Long  * governed primarily by SPECNAMELEN.  The length is the total number of
121422a8a4dSScott Long  * characters in the full path, relative to the mount point and not
122422a8a4dSScott Long  * including any leading '/' characters.
123422a8a4dSScott Long  * A prefix and a suffix are added to the name specified by the user.
124422a8a4dSScott Long  * The prefix is usually "vmm/" or "vmm.io/", but can be a few characters
125422a8a4dSScott Long  * longer for future use.
126422a8a4dSScott Long  * The suffix is a string that identifies a bootrom image or some similar
127422a8a4dSScott Long  * image that is attached to the VM. A separator character gets added to
128422a8a4dSScott Long  * the suffix automatically when generating the full path, so it must be
129422a8a4dSScott Long  * accounted for, reducing the effective length by 1.
130422a8a4dSScott Long  * The effective length of a VM name is 229 bytes for FreeBSD 13 and 37
131422a8a4dSScott Long  * bytes for FreeBSD 12.  A minimum length is set for safety and supports
132422a8a4dSScott Long  * a SPECNAMELEN as small as 32 on old systems.
133422a8a4dSScott Long  */
134422a8a4dSScott Long #define VM_MAX_PREFIXLEN 10
135422a8a4dSScott Long #define VM_MAX_SUFFIXLEN 15
136422a8a4dSScott Long #define VM_MIN_NAMELEN   6
137422a8a4dSScott Long #define VM_MAX_NAMELEN \
138422a8a4dSScott Long     (SPECNAMELEN - VM_MAX_PREFIXLEN - VM_MAX_SUFFIXLEN - 1)
139366f6083SPeter Grehan 
140422a8a4dSScott Long #ifdef _KERNEL
141422a8a4dSScott Long CTASSERT(VM_MAX_NAMELEN >= VM_MIN_NAMELEN);
142366f6083SPeter Grehan 
143366f6083SPeter Grehan struct vm;
144dc506506SNeel Natu struct vm_exception;
145366f6083SPeter Grehan struct seg_desc;
146366f6083SPeter Grehan struct vm_exit;
147366f6083SPeter Grehan struct vm_run;
14808e3ff32SNeel Natu struct vhpet;
149565bbb86SNeel Natu struct vioapic;
150366f6083SPeter Grehan struct vlapic;
151318224bbSNeel Natu struct vmspace;
152318224bbSNeel Natu struct vm_object;
153d665d229SNeel Natu struct vm_guest_paging;
154318224bbSNeel Natu struct pmap;
155366f6083SPeter Grehan 
156248e6799SNeel Natu struct vm_eventinfo {
157248e6799SNeel Natu 	void	*rptr;		/* rendezvous cookie */
158248e6799SNeel Natu 	int	*sptr;		/* suspend cookie */
159248e6799SNeel Natu 	int	*iptr;		/* reqidle cookie */
160248e6799SNeel Natu };
161248e6799SNeel Natu 
162add611fdSNeel Natu typedef int	(*vmm_init_func_t)(int ipinum);
163366f6083SPeter Grehan typedef int	(*vmm_cleanup_func_t)(void);
16463e62d39SJohn Baldwin typedef void	(*vmm_resume_func_t)(void);
165318224bbSNeel Natu typedef void *	(*vmi_init_func_t)(struct vm *vm, struct pmap *pmap);
166318224bbSNeel Natu typedef int	(*vmi_run_func_t)(void *vmi, int vcpu, register_t rip,
167248e6799SNeel Natu 		    struct pmap *pmap, struct vm_eventinfo *info);
168366f6083SPeter Grehan typedef void	(*vmi_cleanup_func_t)(void *vmi);
169366f6083SPeter Grehan typedef int	(*vmi_get_register_t)(void *vmi, int vcpu, int num,
170366f6083SPeter Grehan 				      uint64_t *retval);
171366f6083SPeter Grehan typedef int	(*vmi_set_register_t)(void *vmi, int vcpu, int num,
172366f6083SPeter Grehan 				      uint64_t val);
173366f6083SPeter Grehan typedef int	(*vmi_get_desc_t)(void *vmi, int vcpu, int num,
174366f6083SPeter Grehan 				  struct seg_desc *desc);
175366f6083SPeter Grehan typedef int	(*vmi_set_desc_t)(void *vmi, int vcpu, int num,
176366f6083SPeter Grehan 				  struct seg_desc *desc);
177366f6083SPeter Grehan typedef int	(*vmi_get_cap_t)(void *vmi, int vcpu, int num, int *retval);
178366f6083SPeter Grehan typedef int	(*vmi_set_cap_t)(void *vmi, int vcpu, int num, int val);
179318224bbSNeel Natu typedef struct vmspace * (*vmi_vmspace_alloc)(vm_offset_t min, vm_offset_t max);
180318224bbSNeel Natu typedef void	(*vmi_vmspace_free)(struct vmspace *vmspace);
181de5ea6b6SNeel Natu typedef struct vlapic * (*vmi_vlapic_init)(void *vmi, int vcpu);
182de5ea6b6SNeel Natu typedef void	(*vmi_vlapic_cleanup)(void *vmi, struct vlapic *vlapic);
183366f6083SPeter Grehan 
184366f6083SPeter Grehan struct vmm_ops {
185366f6083SPeter Grehan 	vmm_init_func_t		init;		/* module wide initialization */
186366f6083SPeter Grehan 	vmm_cleanup_func_t	cleanup;
18763e62d39SJohn Baldwin 	vmm_resume_func_t	resume;
188366f6083SPeter Grehan 
189366f6083SPeter Grehan 	vmi_init_func_t		vminit;		/* vm-specific initialization */
190366f6083SPeter Grehan 	vmi_run_func_t		vmrun;
191366f6083SPeter Grehan 	vmi_cleanup_func_t	vmcleanup;
192366f6083SPeter Grehan 	vmi_get_register_t	vmgetreg;
193366f6083SPeter Grehan 	vmi_set_register_t	vmsetreg;
194366f6083SPeter Grehan 	vmi_get_desc_t		vmgetdesc;
195366f6083SPeter Grehan 	vmi_set_desc_t		vmsetdesc;
196366f6083SPeter Grehan 	vmi_get_cap_t		vmgetcap;
197366f6083SPeter Grehan 	vmi_set_cap_t		vmsetcap;
198318224bbSNeel Natu 	vmi_vmspace_alloc	vmspace_alloc;
199318224bbSNeel Natu 	vmi_vmspace_free	vmspace_free;
200de5ea6b6SNeel Natu 	vmi_vlapic_init		vlapic_init;
201de5ea6b6SNeel Natu 	vmi_vlapic_cleanup	vlapic_cleanup;
202366f6083SPeter Grehan };
203366f6083SPeter Grehan 
204366f6083SPeter Grehan extern struct vmm_ops vmm_ops_intel;
205366f6083SPeter Grehan extern struct vmm_ops vmm_ops_amd;
206366f6083SPeter Grehan 
207d5408b1dSNeel Natu int vm_create(const char *name, struct vm **retvm);
208366f6083SPeter Grehan void vm_destroy(struct vm *vm);
2095fcf252fSNeel Natu int vm_reinit(struct vm *vm);
210366f6083SPeter Grehan const char *vm_name(struct vm *vm);
211a488c9c9SRodney W. Grimes uint16_t vm_get_maxcpus(struct vm *vm);
21201d822d3SRodney W. Grimes void vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores,
21301d822d3SRodney W. Grimes     uint16_t *threads, uint16_t *maxcpus);
21401d822d3SRodney W. Grimes int vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores,
21501d822d3SRodney W. Grimes     uint16_t threads, uint16_t maxcpus);
2169b1aa8d6SNeel Natu 
2179b1aa8d6SNeel Natu /*
2189b1aa8d6SNeel Natu  * APIs that modify the guest memory map require all vcpus to be frozen.
2199b1aa8d6SNeel Natu  */
2209b1aa8d6SNeel Natu int vm_mmap_memseg(struct vm *vm, vm_paddr_t gpa, int segid, vm_ooffset_t off,
2219b1aa8d6SNeel Natu     size_t len, int prot, int flags);
2229b1aa8d6SNeel Natu int vm_alloc_memseg(struct vm *vm, int ident, size_t len, bool sysmem);
2239b1aa8d6SNeel Natu void vm_free_memseg(struct vm *vm, int ident);
224366f6083SPeter Grehan int vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa);
225366f6083SPeter Grehan int vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len);
2269b1aa8d6SNeel Natu int vm_assign_pptdev(struct vm *vm, int bus, int slot, int func);
2279b1aa8d6SNeel Natu int vm_unassign_pptdev(struct vm *vm, int bus, int slot, int func);
2289b1aa8d6SNeel Natu 
2299b1aa8d6SNeel Natu /*
2309b1aa8d6SNeel Natu  * APIs that inspect the guest memory map require only a *single* vcpu to
2319b1aa8d6SNeel Natu  * be frozen. This acts like a read lock on the guest memory map since any
2329b1aa8d6SNeel Natu  * modification requires *all* vcpus to be frozen.
2339b1aa8d6SNeel Natu  */
2349b1aa8d6SNeel Natu int vm_mmap_getnext(struct vm *vm, vm_paddr_t *gpa, int *segid,
2359b1aa8d6SNeel Natu     vm_ooffset_t *segoff, size_t *len, int *prot, int *flags);
2369b1aa8d6SNeel Natu int vm_get_memseg(struct vm *vm, int ident, size_t *len, bool *sysmem,
2379b1aa8d6SNeel Natu     struct vm_object **objptr);
238147d12a7SAntoine Brodin vm_paddr_t vmm_sysmem_maxaddr(struct vm *vm);
2399b1aa8d6SNeel Natu void *vm_gpa_hold(struct vm *, int vcpuid, vm_paddr_t gpa, size_t len,
2409b1aa8d6SNeel Natu     int prot, void **cookie);
241318224bbSNeel Natu void vm_gpa_release(void *cookie);
2429b1aa8d6SNeel Natu bool vm_mem_allocated(struct vm *vm, int vcpuid, vm_paddr_t gpa);
2439b1aa8d6SNeel Natu 
244366f6083SPeter Grehan int vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval);
245366f6083SPeter Grehan int vm_set_register(struct vm *vm, int vcpu, int reg, uint64_t val);
246366f6083SPeter Grehan int vm_get_seg_desc(struct vm *vm, int vcpu, int reg,
247366f6083SPeter Grehan 		    struct seg_desc *ret_desc);
248366f6083SPeter Grehan int vm_set_seg_desc(struct vm *vm, int vcpu, int reg,
249366f6083SPeter Grehan 		    struct seg_desc *desc);
250366f6083SPeter Grehan int vm_run(struct vm *vm, struct vm_run *vmrun);
251f0fdcfe2SNeel Natu int vm_suspend(struct vm *vm, enum vm_suspend_how how);
252366f6083SPeter Grehan int vm_inject_nmi(struct vm *vm, int vcpu);
253f352ff0cSNeel Natu int vm_nmi_pending(struct vm *vm, int vcpuid);
254f352ff0cSNeel Natu void vm_nmi_clear(struct vm *vm, int vcpuid);
2550775fbb4STycho Nightingale int vm_inject_extint(struct vm *vm, int vcpu);
2560775fbb4STycho Nightingale int vm_extint_pending(struct vm *vm, int vcpuid);
2570775fbb4STycho Nightingale void vm_extint_clear(struct vm *vm, int vcpuid);
258366f6083SPeter Grehan struct vlapic *vm_lapic(struct vm *vm, int cpu);
259565bbb86SNeel Natu struct vioapic *vm_ioapic(struct vm *vm);
26008e3ff32SNeel Natu struct vhpet *vm_hpet(struct vm *vm);
261366f6083SPeter Grehan int vm_get_capability(struct vm *vm, int vcpu, int type, int *val);
262366f6083SPeter Grehan int vm_set_capability(struct vm *vm, int vcpu, int type, int val);
263e9027382SNeel Natu int vm_get_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state *state);
264e9027382SNeel Natu int vm_set_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state state);
265565bbb86SNeel Natu int vm_apicid2vcpuid(struct vm *vm, int apicid);
26695ebc360SNeel Natu int vm_activate_cpu(struct vm *vm, int vcpu);
267fc276d92SJohn Baldwin int vm_suspend_cpu(struct vm *vm, int vcpu);
268fc276d92SJohn Baldwin int vm_resume_cpu(struct vm *vm, int vcpu);
26998ed632cSNeel Natu struct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid);
270f0fdcfe2SNeel Natu void vm_exit_suspended(struct vm *vm, int vcpuid, uint64_t rip);
271fc276d92SJohn Baldwin void vm_exit_debug(struct vm *vm, int vcpuid, uint64_t rip);
27240487465SNeel Natu void vm_exit_rendezvous(struct vm *vm, int vcpuid, uint64_t rip);
27340487465SNeel Natu void vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip);
274248e6799SNeel Natu void vm_exit_reqidle(struct vm *vm, int vcpuid, uint64_t rip);
275366f6083SPeter Grehan 
2768325ce5cSNeel Natu #ifdef _SYS__CPUSET_H_
277366f6083SPeter Grehan /*
2785b8a8cd1SNeel Natu  * Rendezvous all vcpus specified in 'dest' and execute 'func(arg)'.
2795b8a8cd1SNeel Natu  * The rendezvous 'func(arg)' is not allowed to do anything that will
2805b8a8cd1SNeel Natu  * cause the thread to be put to sleep.
2815b8a8cd1SNeel Natu  *
2825b8a8cd1SNeel Natu  * If the rendezvous is being initiated from a vcpu context then the
2835b8a8cd1SNeel Natu  * 'vcpuid' must refer to that vcpu, otherwise it should be set to -1.
2845b8a8cd1SNeel Natu  *
2855b8a8cd1SNeel Natu  * The caller cannot hold any locks when initiating the rendezvous.
2865b8a8cd1SNeel Natu  *
2875b8a8cd1SNeel Natu  * The implementation of this API may cause vcpus other than those specified
2885b8a8cd1SNeel Natu  * by 'dest' to be stalled. The caller should not rely on any vcpus making
2895b8a8cd1SNeel Natu  * forward progress when the rendezvous is in progress.
2905b8a8cd1SNeel Natu  */
2915b8a8cd1SNeel Natu typedef void (*vm_rendezvous_func_t)(struct vm *vm, int vcpuid, void *arg);
292b837daddSKonstantin Belousov int vm_smp_rendezvous(struct vm *vm, int vcpuid, cpuset_t dest,
2935b8a8cd1SNeel Natu     vm_rendezvous_func_t func, void *arg);
2948325ce5cSNeel Natu cpuset_t vm_active_cpus(struct vm *vm);
295fc276d92SJohn Baldwin cpuset_t vm_debug_cpus(struct vm *vm);
2968325ce5cSNeel Natu cpuset_t vm_suspended_cpus(struct vm *vm);
2978325ce5cSNeel Natu #endif	/* _SYS__CPUSET_H_ */
2985b8a8cd1SNeel Natu 
2995b8a8cd1SNeel Natu static __inline int
300248e6799SNeel Natu vcpu_rendezvous_pending(struct vm_eventinfo *info)
3015b8a8cd1SNeel Natu {
3025b8a8cd1SNeel Natu 
303248e6799SNeel Natu 	return (*((uintptr_t *)(info->rptr)) != 0);
3045b8a8cd1SNeel Natu }
3055b8a8cd1SNeel Natu 
306b15a09c0SNeel Natu static __inline int
307248e6799SNeel Natu vcpu_suspended(struct vm_eventinfo *info)
308b15a09c0SNeel Natu {
309b15a09c0SNeel Natu 
310248e6799SNeel Natu 	return (*info->sptr);
311248e6799SNeel Natu }
312248e6799SNeel Natu 
313248e6799SNeel Natu static __inline int
314248e6799SNeel Natu vcpu_reqidle(struct vm_eventinfo *info)
315248e6799SNeel Natu {
316248e6799SNeel Natu 
317248e6799SNeel Natu 	return (*info->iptr);
318b15a09c0SNeel Natu }
319b15a09c0SNeel Natu 
320fc276d92SJohn Baldwin int vcpu_debugged(struct vm *vm, int vcpuid);
321fc276d92SJohn Baldwin 
3225b8a8cd1SNeel Natu /*
323490d56c5SEd Maste  * Return true if device indicated by bus/slot/func is supposed to be a
324366f6083SPeter Grehan  * pci passthrough device.
325366f6083SPeter Grehan  *
326490d56c5SEd Maste  * Return false otherwise.
327366f6083SPeter Grehan  */
328490d56c5SEd Maste bool vmm_is_pptdev(int bus, int slot, int func);
329366f6083SPeter Grehan 
330366f6083SPeter Grehan void *vm_iommu_domain(struct vm *vm);
331366f6083SPeter Grehan 
33275dd3366SNeel Natu enum vcpu_state {
33375dd3366SNeel Natu 	VCPU_IDLE,
334318224bbSNeel Natu 	VCPU_FROZEN,
33575dd3366SNeel Natu 	VCPU_RUNNING,
336318224bbSNeel Natu 	VCPU_SLEEPING,
33775dd3366SNeel Natu };
338366f6083SPeter Grehan 
339f80330a8SNeel Natu int vcpu_set_state(struct vm *vm, int vcpu, enum vcpu_state state,
340f80330a8SNeel Natu     bool from_idle);
341d3c11f40SPeter Grehan enum vcpu_state vcpu_get_state(struct vm *vm, int vcpu, int *hostcpu);
342366f6083SPeter Grehan 
343366f6083SPeter Grehan static int __inline
344d3c11f40SPeter Grehan vcpu_is_running(struct vm *vm, int vcpu, int *hostcpu)
345366f6083SPeter Grehan {
346d3c11f40SPeter Grehan 	return (vcpu_get_state(vm, vcpu, hostcpu) == VCPU_RUNNING);
347366f6083SPeter Grehan }
348366f6083SPeter Grehan 
349f008d157SNeel Natu #ifdef _SYS_PROC_H_
350f008d157SNeel Natu static int __inline
351f008d157SNeel Natu vcpu_should_yield(struct vm *vm, int vcpu)
352f008d157SNeel Natu {
353ede04033SNeel Natu 
354ede04033SNeel Natu 	if (curthread->td_flags & (TDF_ASTPENDING | TDF_NEEDRESCHED))
355ede04033SNeel Natu 		return (1);
356ede04033SNeel Natu 	else if (curthread->td_owepreempt)
357ede04033SNeel Natu 		return (1);
358ede04033SNeel Natu 	else
359ede04033SNeel Natu 		return (0);
360f008d157SNeel Natu }
361f008d157SNeel Natu #endif
362f008d157SNeel Natu 
36375dd3366SNeel Natu void *vcpu_stats(struct vm *vm, int vcpu);
364de5ea6b6SNeel Natu void vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr);
365318224bbSNeel Natu struct vmspace *vm_get_vmspace(struct vm *vm);
366762fd208STycho Nightingale struct vatpic *vm_atpic(struct vm *vm);
367e883c9bbSTycho Nightingale struct vatpit *vm_atpit(struct vm *vm);
368160ef77aSNeel Natu struct vpmtmr *vm_pmtmr(struct vm *vm);
3690dafa5cdSNeel Natu struct vrtc *vm_rtc(struct vm *vm);
370dc506506SNeel Natu 
371dc506506SNeel Natu /*
372c9c75df4SNeel Natu  * Inject exception 'vector' into the guest vcpu. This function returns 0 on
373dc506506SNeel Natu  * success and non-zero on failure.
374dc506506SNeel Natu  *
375dc506506SNeel Natu  * Wrapper functions like 'vm_inject_gp()' should be preferred to calling
376dc506506SNeel Natu  * this function directly because they enforce the trap-like or fault-like
377dc506506SNeel Natu  * behavior of an exception.
378dc506506SNeel Natu  *
379dc506506SNeel Natu  * This function should only be called in the context of the thread that is
380dc506506SNeel Natu  * executing this vcpu.
381dc506506SNeel Natu  */
382c9c75df4SNeel Natu int vm_inject_exception(struct vm *vm, int vcpuid, int vector, int err_valid,
383c9c75df4SNeel Natu     uint32_t errcode, int restart_instruction);
384dc506506SNeel Natu 
385dc506506SNeel Natu /*
386091d4532SNeel Natu  * This function is called after a VM-exit that occurred during exception or
387091d4532SNeel Natu  * interrupt delivery through the IDT. The format of 'intinfo' is described
388091d4532SNeel Natu  * in Figure 15-1, "EXITINTINFO for All Intercepts", APM, Vol 2.
389dc506506SNeel Natu  *
390091d4532SNeel Natu  * If a VM-exit handler completes the event delivery successfully then it
391091d4532SNeel Natu  * should call vm_exit_intinfo() to extinguish the pending event. For e.g.,
392091d4532SNeel Natu  * if the task switch emulation is triggered via a task gate then it should
393091d4532SNeel Natu  * call this function with 'intinfo=0' to indicate that the external event
394091d4532SNeel Natu  * is not pending anymore.
395091d4532SNeel Natu  *
396091d4532SNeel Natu  * Return value is 0 on success and non-zero on failure.
397dc506506SNeel Natu  */
398091d4532SNeel Natu int vm_exit_intinfo(struct vm *vm, int vcpuid, uint64_t intinfo);
399091d4532SNeel Natu 
400091d4532SNeel Natu /*
401091d4532SNeel Natu  * This function is called before every VM-entry to retrieve a pending
402091d4532SNeel Natu  * event that should be injected into the guest. This function combines
403091d4532SNeel Natu  * nested events into a double or triple fault.
404091d4532SNeel Natu  *
405091d4532SNeel Natu  * Returns 0 if there are no events that need to be injected into the guest
406091d4532SNeel Natu  * and non-zero otherwise.
407091d4532SNeel Natu  */
408091d4532SNeel Natu int vm_entry_intinfo(struct vm *vm, int vcpuid, uint64_t *info);
409091d4532SNeel Natu 
410091d4532SNeel Natu int vm_get_intinfo(struct vm *vm, int vcpuid, uint64_t *info1, uint64_t *info2);
411dc506506SNeel Natu 
412d17b5104SNeel Natu enum vm_reg_name vm_segment_name(int seg_encoding);
413d17b5104SNeel Natu 
414d665d229SNeel Natu struct vm_copyinfo {
415d665d229SNeel Natu 	uint64_t	gpa;
416d665d229SNeel Natu 	size_t		len;
417d665d229SNeel Natu 	void		*hva;
418d665d229SNeel Natu 	void		*cookie;
419d665d229SNeel Natu };
420d665d229SNeel Natu 
421d665d229SNeel Natu /*
422d665d229SNeel Natu  * Set up 'copyinfo[]' to copy to/from guest linear address space starting
423d665d229SNeel Natu  * at 'gla' and 'len' bytes long. The 'prot' should be set to PROT_READ for
424d665d229SNeel Natu  * a copyin or PROT_WRITE for a copyout.
425d665d229SNeel Natu  *
426edafb5a3SPedro F. Giffuni  * retval	is_fault	Interpretation
4279c4d5478SNeel Natu  *   0		   0		Success
4289c4d5478SNeel Natu  *   0		   1		An exception was injected into the guest
4299c4d5478SNeel Natu  * EFAULT	  N/A		Unrecoverable error
430d665d229SNeel Natu  *
431d665d229SNeel Natu  * The 'copyinfo[]' can be passed to 'vm_copyin()' or 'vm_copyout()' only if
432d665d229SNeel Natu  * the return value is 0. The 'copyinfo[]' resources should be freed by calling
433d665d229SNeel Natu  * 'vm_copy_teardown()' after the copy is done.
434d665d229SNeel Natu  */
435d665d229SNeel Natu int vm_copy_setup(struct vm *vm, int vcpuid, struct vm_guest_paging *paging,
436d665d229SNeel Natu     uint64_t gla, size_t len, int prot, struct vm_copyinfo *copyinfo,
4379c4d5478SNeel Natu     int num_copyinfo, int *is_fault);
438d665d229SNeel Natu void vm_copy_teardown(struct vm *vm, int vcpuid, struct vm_copyinfo *copyinfo,
439d665d229SNeel Natu     int num_copyinfo);
440d665d229SNeel Natu void vm_copyin(struct vm *vm, int vcpuid, struct vm_copyinfo *copyinfo,
441d665d229SNeel Natu     void *kaddr, size_t len);
442d665d229SNeel Natu void vm_copyout(struct vm *vm, int vcpuid, const void *kaddr,
443d665d229SNeel Natu     struct vm_copyinfo *copyinfo, size_t len);
444b0538143SNeel Natu 
445b0538143SNeel Natu int vcpu_trace_exceptions(struct vm *vm, int vcpuid);
446366f6083SPeter Grehan #endif	/* KERNEL */
447366f6083SPeter Grehan 
4488d39ed16SPeter Grehan #define	VM_MAXCPU	16			/* maximum virtual cpus */
449366f6083SPeter Grehan 
450366f6083SPeter Grehan /*
451366f6083SPeter Grehan  * Identifiers for optional vmm capabilities
452366f6083SPeter Grehan  */
453366f6083SPeter Grehan enum vm_cap_type {
454366f6083SPeter Grehan 	VM_CAP_HALT_EXIT,
455366f6083SPeter Grehan 	VM_CAP_MTRAP_EXIT,
456366f6083SPeter Grehan 	VM_CAP_PAUSE_EXIT,
457366f6083SPeter Grehan 	VM_CAP_UNRESTRICTED_GUEST,
45849cc03daSNeel Natu 	VM_CAP_ENABLE_INVPCID,
459cbd03a9dSJohn Baldwin 	VM_CAP_BPT_EXIT,
460366f6083SPeter Grehan 	VM_CAP_MAX
461366f6083SPeter Grehan };
462366f6083SPeter Grehan 
463b3e9732aSJohn Baldwin enum vm_intr_trigger {
464b3e9732aSJohn Baldwin 	EDGE_TRIGGER,
465b3e9732aSJohn Baldwin 	LEVEL_TRIGGER
466b3e9732aSJohn Baldwin };
467b3e9732aSJohn Baldwin 
468366f6083SPeter Grehan /*
469366f6083SPeter Grehan  * The 'access' field has the format specified in Table 21-2 of the Intel
470366f6083SPeter Grehan  * Architecture Manual vol 3b.
471366f6083SPeter Grehan  *
472366f6083SPeter Grehan  * XXX The contents of the 'access' field are architecturally defined except
473366f6083SPeter Grehan  * bit 16 - Segment Unusable.
474366f6083SPeter Grehan  */
475366f6083SPeter Grehan struct seg_desc {
476366f6083SPeter Grehan 	uint64_t	base;
477366f6083SPeter Grehan 	uint32_t	limit;
478366f6083SPeter Grehan 	uint32_t	access;
479366f6083SPeter Grehan };
480f7a9f178SNeel Natu #define	SEG_DESC_TYPE(access)		((access) & 0x001f)
4813d5444c8SNeel Natu #define	SEG_DESC_DPL(access)		(((access) >> 5) & 0x3)
482f7a9f178SNeel Natu #define	SEG_DESC_PRESENT(access)	(((access) & 0x0080) ? 1 : 0)
483f7a9f178SNeel Natu #define	SEG_DESC_DEF32(access)		(((access) & 0x4000) ? 1 : 0)
484f7a9f178SNeel Natu #define	SEG_DESC_GRANULARITY(access)	(((access) & 0x8000) ? 1 : 0)
485f7a9f178SNeel Natu #define	SEG_DESC_UNUSABLE(access)	(((access) & 0x10000) ? 1 : 0)
486366f6083SPeter Grehan 
487e813a873SNeel Natu enum vm_cpu_mode {
488b301b9e2SNeel Natu 	CPU_MODE_REAL,
489b301b9e2SNeel Natu 	CPU_MODE_PROTECTED,
490e813a873SNeel Natu 	CPU_MODE_COMPATIBILITY,		/* IA-32E mode (CS.L = 0) */
491e813a873SNeel Natu 	CPU_MODE_64BIT,			/* IA-32E mode (CS.L = 1) */
492e813a873SNeel Natu };
493e813a873SNeel Natu 
494e813a873SNeel Natu enum vm_paging_mode {
495e813a873SNeel Natu 	PAGING_MODE_FLAT,
496e813a873SNeel Natu 	PAGING_MODE_32,
497e813a873SNeel Natu 	PAGING_MODE_PAE,
498e813a873SNeel Natu 	PAGING_MODE_64,
499e813a873SNeel Natu };
500e813a873SNeel Natu 
501e813a873SNeel Natu struct vm_guest_paging {
502e813a873SNeel Natu 	uint64_t	cr3;
503e813a873SNeel Natu 	int		cpl;
504e813a873SNeel Natu 	enum vm_cpu_mode cpu_mode;
505e813a873SNeel Natu 	enum vm_paging_mode paging_mode;
506e813a873SNeel Natu };
507e813a873SNeel Natu 
508e813a873SNeel Natu /*
509e813a873SNeel Natu  * The data structures 'vie' and 'vie_op' are meant to be opaque to the
510e813a873SNeel Natu  * consumers of instruction decoding. The only reason why their contents
511e813a873SNeel Natu  * need to be exposed is because they are part of the 'vm_exit' structure.
512e813a873SNeel Natu  */
513e813a873SNeel Natu struct vie_op {
514e813a873SNeel Natu 	uint8_t		op_byte;	/* actual opcode byte */
515e813a873SNeel Natu 	uint8_t		op_type;	/* type of operation (e.g. MOV) */
516e813a873SNeel Natu 	uint16_t	op_flags;
517e813a873SNeel Natu };
518497cb925SConrad Meyer _Static_assert(sizeof(struct vie_op) == 4, "ABI");
519497cb925SConrad Meyer _Static_assert(_Alignof(struct vie_op) == 2, "ABI");
520e813a873SNeel Natu 
521e813a873SNeel Natu #define	VIE_INST_SIZE	15
522e813a873SNeel Natu struct vie {
523e813a873SNeel Natu 	uint8_t		inst[VIE_INST_SIZE];	/* instruction bytes */
524e813a873SNeel Natu 	uint8_t		num_valid;		/* size of the instruction */
525e813a873SNeel Natu 	uint8_t		num_processed;
526e813a873SNeel Natu 
527f7a9f178SNeel Natu 	uint8_t		addrsize:4, opsize:4;	/* address and operand sizes */
528e813a873SNeel Natu 	uint8_t		rex_w:1,		/* REX prefix */
529e813a873SNeel Natu 			rex_r:1,
530e813a873SNeel Natu 			rex_x:1,
531e813a873SNeel Natu 			rex_b:1,
532f7a9f178SNeel Natu 			rex_present:1,
53375346353SNeel Natu 			repz_present:1,		/* REP/REPE/REPZ prefix */
53475346353SNeel Natu 			repnz_present:1,	/* REPNE/REPNZ prefix */
535f7a9f178SNeel Natu 			opsize_override:1,	/* Operand size override */
53675346353SNeel Natu 			addrsize_override:1,	/* Address size override */
53775346353SNeel Natu 			segment_override:1;	/* Segment override */
538e813a873SNeel Natu 
539e813a873SNeel Natu 	uint8_t		mod:2,			/* ModRM byte */
540e813a873SNeel Natu 			reg:4,
541e813a873SNeel Natu 			rm:4;
542e813a873SNeel Natu 
543e813a873SNeel Natu 	uint8_t		ss:2,			/* SIB byte */
544cfdea69dSConrad Meyer 			vex_present:1,		/* VEX prefixed */
545cfdea69dSConrad Meyer 			vex_l:1,		/* L bit */
546497cb925SConrad Meyer 			index:4,		/* SIB byte */
547497cb925SConrad Meyer 			base:4;			/* SIB byte */
548e813a873SNeel Natu 
549e813a873SNeel Natu 	uint8_t		disp_bytes;
550e813a873SNeel Natu 	uint8_t		imm_bytes;
551e813a873SNeel Natu 
552e813a873SNeel Natu 	uint8_t		scale;
553497cb925SConrad Meyer 
554cfdea69dSConrad Meyer 	uint8_t		vex_reg:4,		/* vvvv: first source register specifier */
555cfdea69dSConrad Meyer 			vex_pp:2,		/* pp */
556cfdea69dSConrad Meyer 			_sparebits:2;
557cfdea69dSConrad Meyer 
558cfdea69dSConrad Meyer 	uint8_t		_sparebytes[2];
559497cb925SConrad Meyer 
560e813a873SNeel Natu 	int		base_register;		/* VM_REG_GUEST_xyz */
561e813a873SNeel Natu 	int		index_register;		/* VM_REG_GUEST_xyz */
56275346353SNeel Natu 	int		segment_register;	/* VM_REG_GUEST_xyz */
563e813a873SNeel Natu 
564e813a873SNeel Natu 	int64_t		displacement;		/* optional addr displacement */
565e813a873SNeel Natu 	int64_t		immediate;		/* optional immediate operand */
566e813a873SNeel Natu 
567e813a873SNeel Natu 	uint8_t		decoded;	/* set to 1 if successfully decoded */
568e813a873SNeel Natu 
569497cb925SConrad Meyer 	uint8_t		_sparebyte;
570497cb925SConrad Meyer 
571e813a873SNeel Natu 	struct vie_op	op;			/* opcode description */
572e813a873SNeel Natu };
573497cb925SConrad Meyer _Static_assert(sizeof(struct vie) == 64, "ABI");
574497cb925SConrad Meyer _Static_assert(__offsetof(struct vie, disp_bytes) == 22, "ABI");
575497cb925SConrad Meyer _Static_assert(__offsetof(struct vie, scale) == 24, "ABI");
576497cb925SConrad Meyer _Static_assert(__offsetof(struct vie, base_register) == 28, "ABI");
577e813a873SNeel Natu 
578366f6083SPeter Grehan enum vm_exitcode {
579366f6083SPeter Grehan 	VM_EXITCODE_INOUT,
580366f6083SPeter Grehan 	VM_EXITCODE_VMX,
581366f6083SPeter Grehan 	VM_EXITCODE_BOGUS,
582366f6083SPeter Grehan 	VM_EXITCODE_RDMSR,
583366f6083SPeter Grehan 	VM_EXITCODE_WRMSR,
584366f6083SPeter Grehan 	VM_EXITCODE_HLT,
585366f6083SPeter Grehan 	VM_EXITCODE_MTRAP,
586366f6083SPeter Grehan 	VM_EXITCODE_PAUSE,
587cd942e0fSPeter Grehan 	VM_EXITCODE_PAGING,
588318224bbSNeel Natu 	VM_EXITCODE_INST_EMUL,
589edf89256SNeel Natu 	VM_EXITCODE_SPINUP_AP,
590c6a0cc2eSNeel Natu 	VM_EXITCODE_DEPRECATED1,	/* used to be SPINDOWN_CPU */
5915b8a8cd1SNeel Natu 	VM_EXITCODE_RENDEZVOUS,
59230b94db8SNeel Natu 	VM_EXITCODE_IOAPIC_EOI,
593b15a09c0SNeel Natu 	VM_EXITCODE_SUSPENDED,
594d17b5104SNeel Natu 	VM_EXITCODE_INOUT_STR,
5953d5444c8SNeel Natu 	VM_EXITCODE_TASK_SWITCH,
59665145c7fSNeel Natu 	VM_EXITCODE_MONITOR,
59765145c7fSNeel Natu 	VM_EXITCODE_MWAIT,
598bbadcde4SNeel Natu 	VM_EXITCODE_SVM,
599248e6799SNeel Natu 	VM_EXITCODE_REQIDLE,
600fc276d92SJohn Baldwin 	VM_EXITCODE_DEBUG,
60127d26457SAndrew Turner 	VM_EXITCODE_VMINSN,
602cbd03a9dSJohn Baldwin 	VM_EXITCODE_BPT,
603cd942e0fSPeter Grehan 	VM_EXITCODE_MAX
604366f6083SPeter Grehan };
605366f6083SPeter Grehan 
606d17b5104SNeel Natu struct vm_inout {
607d17b5104SNeel Natu 	uint16_t	bytes:3;	/* 1 or 2 or 4 */
608d17b5104SNeel Natu 	uint16_t	in:1;
609d17b5104SNeel Natu 	uint16_t	string:1;
610d17b5104SNeel Natu 	uint16_t	rep:1;
611d17b5104SNeel Natu 	uint16_t	port;
612d17b5104SNeel Natu 	uint32_t	eax;		/* valid for out */
613d17b5104SNeel Natu };
614d17b5104SNeel Natu 
615d17b5104SNeel Natu struct vm_inout_str {
616d17b5104SNeel Natu 	struct vm_inout	inout;		/* must be the first element */
617e813a873SNeel Natu 	struct vm_guest_paging paging;
618d17b5104SNeel Natu 	uint64_t	rflags;
619d17b5104SNeel Natu 	uint64_t	cr0;
620d17b5104SNeel Natu 	uint64_t	index;
621d17b5104SNeel Natu 	uint64_t	count;		/* rep=1 (%rcx), rep=0 (1) */
622d17b5104SNeel Natu 	int		addrsize;
623d17b5104SNeel Natu 	enum vm_reg_name seg_name;
624d17b5104SNeel Natu 	struct seg_desc seg_desc;
625d17b5104SNeel Natu };
626d17b5104SNeel Natu 
6273d5444c8SNeel Natu enum task_switch_reason {
6283d5444c8SNeel Natu 	TSR_CALL,
6293d5444c8SNeel Natu 	TSR_IRET,
6303d5444c8SNeel Natu 	TSR_JMP,
6313d5444c8SNeel Natu 	TSR_IDT_GATE,	/* task gate in IDT */
6323d5444c8SNeel Natu };
6333d5444c8SNeel Natu 
6343d5444c8SNeel Natu struct vm_task_switch {
6353d5444c8SNeel Natu 	uint16_t	tsssel;		/* new TSS selector */
6363d5444c8SNeel Natu 	int		ext;		/* task switch due to external event */
6373d5444c8SNeel Natu 	uint32_t	errcode;
6383d5444c8SNeel Natu 	int		errcode_valid;	/* push 'errcode' on the new stack */
6393d5444c8SNeel Natu 	enum task_switch_reason reason;
6403d5444c8SNeel Natu 	struct vm_guest_paging paging;
6413d5444c8SNeel Natu };
6423d5444c8SNeel Natu 
643366f6083SPeter Grehan struct vm_exit {
644366f6083SPeter Grehan 	enum vm_exitcode	exitcode;
645366f6083SPeter Grehan 	int			inst_length;	/* 0 means unknown */
646366f6083SPeter Grehan 	uint64_t		rip;
647366f6083SPeter Grehan 	union {
648d17b5104SNeel Natu 		struct vm_inout	inout;
649d17b5104SNeel Natu 		struct vm_inout_str inout_str;
650cd942e0fSPeter Grehan 		struct {
65113ec9371SPeter Grehan 			uint64_t	gpa;
652318224bbSNeel Natu 			int		fault_type;
653cd942e0fSPeter Grehan 		} paging;
654318224bbSNeel Natu 		struct {
655318224bbSNeel Natu 			uint64_t	gpa;
656318224bbSNeel Natu 			uint64_t	gla;
657e4f605eeSTycho Nightingale 			uint64_t	cs_base;
658f7a9f178SNeel Natu 			int		cs_d;		/* CS.D */
659e813a873SNeel Natu 			struct vm_guest_paging paging;
660318224bbSNeel Natu 			struct vie	vie;
661318224bbSNeel Natu 		} inst_emul;
662366f6083SPeter Grehan 		/*
663366f6083SPeter Grehan 		 * VMX specific payload. Used when there is no "better"
664366f6083SPeter Grehan 		 * exitcode to represent the VM-exit.
665366f6083SPeter Grehan 		 */
666366f6083SPeter Grehan 		struct {
6670492757cSNeel Natu 			int		status;		/* vmx inst status */
6680492757cSNeel Natu 			/*
6690492757cSNeel Natu 			 * 'exit_reason' and 'exit_qualification' are valid
6700492757cSNeel Natu 			 * only if 'status' is zero.
6710492757cSNeel Natu 			 */
672366f6083SPeter Grehan 			uint32_t	exit_reason;
673366f6083SPeter Grehan 			uint64_t	exit_qualification;
6740492757cSNeel Natu 			/*
6750492757cSNeel Natu 			 * 'inst_error' and 'inst_type' are valid
6760492757cSNeel Natu 			 * only if 'status' is non-zero.
6770492757cSNeel Natu 			 */
6780492757cSNeel Natu 			int		inst_type;
6790492757cSNeel Natu 			int		inst_error;
680366f6083SPeter Grehan 		} vmx;
681bbadcde4SNeel Natu 		/*
682bbadcde4SNeel Natu 		 * SVM specific payload.
683bbadcde4SNeel Natu 		 */
684bbadcde4SNeel Natu 		struct {
685bbadcde4SNeel Natu 			uint64_t	exitcode;
686bbadcde4SNeel Natu 			uint64_t	exitinfo1;
687bbadcde4SNeel Natu 			uint64_t	exitinfo2;
688bbadcde4SNeel Natu 		} svm;
689366f6083SPeter Grehan 		struct {
690cbd03a9dSJohn Baldwin 			int		inst_length;
691cbd03a9dSJohn Baldwin 		} bpt;
692cbd03a9dSJohn Baldwin 		struct {
693366f6083SPeter Grehan 			uint32_t	code;		/* ecx value */
694366f6083SPeter Grehan 			uint64_t	wval;
695366f6083SPeter Grehan 		} msr;
696edf89256SNeel Natu 		struct {
697edf89256SNeel Natu 			int		vcpu;
698edf89256SNeel Natu 			uint64_t	rip;
699edf89256SNeel Natu 		} spinup_ap;
7001c052192SNeel Natu 		struct {
7011c052192SNeel Natu 			uint64_t	rflags;
702490768e2STycho Nightingale 			uint64_t	intr_status;
7031c052192SNeel Natu 		} hlt;
70430b94db8SNeel Natu 		struct {
70530b94db8SNeel Natu 			int		vector;
70630b94db8SNeel Natu 		} ioapic_eoi;
707f0fdcfe2SNeel Natu 		struct {
708f0fdcfe2SNeel Natu 			enum vm_suspend_how how;
709f0fdcfe2SNeel Natu 		} suspended;
7103d5444c8SNeel Natu 		struct vm_task_switch task_switch;
711366f6083SPeter Grehan 	} u;
712366f6083SPeter Grehan };
713366f6083SPeter Grehan 
714d37f2adbSNeel Natu /* APIs to inject faults into the guest */
715d37f2adbSNeel Natu void vm_inject_fault(void *vm, int vcpuid, int vector, int errcode_valid,
716d37f2adbSNeel Natu     int errcode);
717d37f2adbSNeel Natu 
7187f21538bSPeter Grehan static __inline void
719d37f2adbSNeel Natu vm_inject_ud(void *vm, int vcpuid)
720d37f2adbSNeel Natu {
721d37f2adbSNeel Natu 	vm_inject_fault(vm, vcpuid, IDT_UD, 0, 0);
722d37f2adbSNeel Natu }
723d37f2adbSNeel Natu 
7247f21538bSPeter Grehan static __inline void
725d37f2adbSNeel Natu vm_inject_gp(void *vm, int vcpuid)
726d37f2adbSNeel Natu {
727d37f2adbSNeel Natu 	vm_inject_fault(vm, vcpuid, IDT_GP, 1, 0);
728d37f2adbSNeel Natu }
729d37f2adbSNeel Natu 
7307f21538bSPeter Grehan static __inline void
731d37f2adbSNeel Natu vm_inject_ac(void *vm, int vcpuid, int errcode)
732d37f2adbSNeel Natu {
733d37f2adbSNeel Natu 	vm_inject_fault(vm, vcpuid, IDT_AC, 1, errcode);
734d37f2adbSNeel Natu }
735d37f2adbSNeel Natu 
7367f21538bSPeter Grehan static __inline void
737d37f2adbSNeel Natu vm_inject_ss(void *vm, int vcpuid, int errcode)
738d37f2adbSNeel Natu {
739d37f2adbSNeel Natu 	vm_inject_fault(vm, vcpuid, IDT_SS, 1, errcode);
740d37f2adbSNeel Natu }
741d37f2adbSNeel Natu 
742d37f2adbSNeel Natu void vm_inject_pf(void *vm, int vcpuid, int error_code, uint64_t cr2);
743d37f2adbSNeel Natu 
744c9c75df4SNeel Natu int vm_restart_instruction(void *vm, int vcpuid);
745c9c75df4SNeel Natu 
746366f6083SPeter Grehan #endif	/* _VMM_H_ */
747