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 *
26221828Sgrehan * $FreeBSD$
27221828Sgrehan */
28221828Sgrehan
29221828Sgrehan#ifndef _VMX_H_
30221828Sgrehan#define	_VMX_H_
31221828Sgrehan
32221828Sgrehan#include "vmcs.h"
33221828Sgrehan
34256072Sneelstruct pmap;
35256072Sneel
36221828Sgrehan#define	GUEST_MSR_MAX_ENTRIES	64		/* arbitrary */
37221828Sgrehan
38221828Sgrehanstruct vmxctx {
39222112Sneel	register_t	tmpstk[32];		/* vmx_return() stack */
40222112Sneel	register_t	tmpstktop;
41222112Sneel
42221828Sgrehan	register_t	guest_rdi;		/* Guest state */
43221828Sgrehan	register_t	guest_rsi;
44221828Sgrehan	register_t	guest_rdx;
45221828Sgrehan	register_t	guest_rcx;
46221828Sgrehan	register_t	guest_r8;
47221828Sgrehan	register_t	guest_r9;
48221828Sgrehan	register_t	guest_rax;
49221828Sgrehan	register_t	guest_rbx;
50221828Sgrehan	register_t	guest_rbp;
51221828Sgrehan	register_t	guest_r10;
52221828Sgrehan	register_t	guest_r11;
53221828Sgrehan	register_t	guest_r12;
54221828Sgrehan	register_t	guest_r13;
55221828Sgrehan	register_t	guest_r14;
56221828Sgrehan	register_t	guest_r15;
57221828Sgrehan	register_t	guest_cr2;
58221828Sgrehan
59221828Sgrehan	register_t	host_r15;		/* Host state */
60221828Sgrehan	register_t	host_r14;
61221828Sgrehan	register_t	host_r13;
62221828Sgrehan	register_t	host_r12;
63221828Sgrehan	register_t	host_rbp;
64221828Sgrehan	register_t	host_rsp;
65221828Sgrehan	register_t	host_rbx;
66221828Sgrehan	register_t	host_rip;
67221828Sgrehan	/*
68221828Sgrehan	 * XXX todo debug registers and fpu state
69221828Sgrehan	 */
70221828Sgrehan
71222112Sneel	int		launched;		/* vmcs launch state */
72221828Sgrehan	int		launch_error;
73256072Sneel
74256072Sneel	long		eptgen[MAXCPU];		/* cached pmap->pm_eptgen */
75256072Sneel
76256072Sneel	/*
77256072Sneel	 * The 'eptp' and the 'pmap' do not change during the lifetime of
78256072Sneel	 * the VM so it is safe to keep a copy in each vcpu's vmxctx.
79256072Sneel	 */
80256072Sneel	vm_paddr_t	eptp;
81256072Sneel	struct pmap	*pmap;
82221828Sgrehan};
83221828Sgrehan
84221828Sgrehanstruct vmxcap {
85221828Sgrehan	int	set;
86221828Sgrehan	uint32_t proc_ctls;
87256869Sneel	uint32_t proc_ctls2;
88221828Sgrehan};
89221828Sgrehan
90221828Sgrehanstruct vmxstate {
91221828Sgrehan	int	lastcpu;	/* host cpu that this 'vcpu' last ran on */
92221828Sgrehan	uint16_t vpid;
93221828Sgrehan};
94221828Sgrehan
95221828Sgrehan/* virtual machine softc */
96221828Sgrehanstruct vmx {
97221828Sgrehan	struct vmcs	vmcs[VM_MAXCPU];	/* one vmcs per virtual cpu */
98221828Sgrehan	char		msr_bitmap[PAGE_SIZE];
99221828Sgrehan	struct msr_entry guest_msrs[VM_MAXCPU][GUEST_MSR_MAX_ENTRIES];
100221828Sgrehan	struct vmxctx	ctx[VM_MAXCPU];
101221828Sgrehan	struct vmxcap	cap[VM_MAXCPU];
102221828Sgrehan	struct vmxstate	state[VM_MAXCPU];
103256072Sneel	uint64_t	eptp;
104221828Sgrehan	struct vm	*vm;
105221828Sgrehan};
106221828SgrehanCTASSERT((offsetof(struct vmx, vmcs) & PAGE_MASK) == 0);
107221828SgrehanCTASSERT((offsetof(struct vmx, msr_bitmap) & PAGE_MASK) == 0);
108221828SgrehanCTASSERT((offsetof(struct vmx, guest_msrs) & 15) == 0);
109221828Sgrehan
110221828Sgrehan#define	VMX_RETURN_DIRECT	0
111221828Sgrehan#define	VMX_RETURN_LONGJMP	1
112221828Sgrehan#define	VMX_RETURN_VMRESUME	2
113221828Sgrehan#define	VMX_RETURN_VMLAUNCH	3
114241921Sneel#define	VMX_RETURN_AST		4
115256072Sneel#define	VMX_RETURN_INVEPT	5
116221828Sgrehan/*
117221828Sgrehan * vmx_setjmp() returns:
118221828Sgrehan * - 0 when it returns directly
119221828Sgrehan * - 1 when it returns from vmx_longjmp
120221828Sgrehan * - 2 when it returns from vmx_resume (which would only be in the error case)
121221828Sgrehan * - 3 when it returns from vmx_launch (which would only be in the error case)
122241921Sneel * - 4 when it returns from vmx_resume or vmx_launch because of AST pending
123256072Sneel * - 5 when it returns from vmx_launch/vmx_resume because of invept error
124221828Sgrehan */
125221828Sgrehanint	vmx_setjmp(struct vmxctx *ctx);
126221828Sgrehanvoid	vmx_longjmp(void);			/* returns via vmx_setjmp */
127221828Sgrehanvoid	vmx_launch(struct vmxctx *ctx) __dead2;	/* may return via vmx_setjmp */
128221828Sgrehanvoid	vmx_resume(struct vmxctx *ctx) __dead2;	/* may return via vmx_setjmp */
129221828Sgrehan
130221828Sgrehanu_long	vmx_fix_cr0(u_long cr0);
131221828Sgrehanu_long	vmx_fix_cr4(u_long cr4);
132221828Sgrehan
133221828Sgrehan#endif
134