xref: /freebsd/lib/libvmmapi/amd64/vmmapi_machdep.c (revision 967264cfcd6d1a42dc0c9f9916320afe90f1faa4)
1*967264cfSMark Johnston /*-
2*967264cfSMark Johnston  * SPDX-License-Identifier: BSD-2-Clause
3*967264cfSMark Johnston  *
4*967264cfSMark Johnston  * Copyright (c) 2011 NetApp, Inc.
5*967264cfSMark Johnston  * All rights reserved.
6*967264cfSMark Johnston  *
7*967264cfSMark Johnston  * Redistribution and use in source and binary forms, with or without
8*967264cfSMark Johnston  * modification, are permitted provided that the following conditions
9*967264cfSMark Johnston  * are met:
10*967264cfSMark Johnston  * 1. Redistributions of source code must retain the above copyright
11*967264cfSMark Johnston  *    notice, this list of conditions and the following disclaimer.
12*967264cfSMark Johnston  * 2. Redistributions in binary form must reproduce the above copyright
13*967264cfSMark Johnston  *    notice, this list of conditions and the following disclaimer in the
14*967264cfSMark Johnston  *    documentation and/or other materials provided with the distribution.
15*967264cfSMark Johnston  *
16*967264cfSMark Johnston  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
17*967264cfSMark Johnston  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*967264cfSMark Johnston  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*967264cfSMark Johnston  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
20*967264cfSMark Johnston  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*967264cfSMark Johnston  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*967264cfSMark Johnston  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*967264cfSMark Johnston  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*967264cfSMark Johnston  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*967264cfSMark Johnston  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*967264cfSMark Johnston  * SUCH DAMAGE.
27*967264cfSMark Johnston  */
28*967264cfSMark Johnston 
29*967264cfSMark Johnston #include <machine/specialreg.h>
30*967264cfSMark Johnston 
31*967264cfSMark Johnston #include "vmmapi.h"
32*967264cfSMark Johnston #include "internal.h"
33*967264cfSMark Johnston 
34*967264cfSMark Johnston /*
35*967264cfSMark Johnston  * From Intel Vol 3a:
36*967264cfSMark Johnston  * Table 9-1. IA-32 Processor States Following Power-up, Reset or INIT
37*967264cfSMark Johnston  */
38*967264cfSMark Johnston int
39*967264cfSMark Johnston vcpu_reset(struct vcpu *vcpu)
40*967264cfSMark Johnston {
41*967264cfSMark Johnston 	int error;
42*967264cfSMark Johnston 	uint64_t rflags, rip, cr0, cr4, zero, desc_base, rdx;
43*967264cfSMark Johnston 	uint32_t desc_access, desc_limit;
44*967264cfSMark Johnston 	uint16_t sel;
45*967264cfSMark Johnston 
46*967264cfSMark Johnston 	zero = 0;
47*967264cfSMark Johnston 
48*967264cfSMark Johnston 	rflags = 0x2;
49*967264cfSMark Johnston 	error = vm_set_register(vcpu, VM_REG_GUEST_RFLAGS, rflags);
50*967264cfSMark Johnston 	if (error)
51*967264cfSMark Johnston 		goto done;
52*967264cfSMark Johnston 
53*967264cfSMark Johnston 	rip = 0xfff0;
54*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RIP, rip)) != 0)
55*967264cfSMark Johnston 		goto done;
56*967264cfSMark Johnston 
57*967264cfSMark Johnston 	/*
58*967264cfSMark Johnston 	 * According to Intels Software Developer Manual CR0 should be
59*967264cfSMark Johnston 	 * initialized with CR0_ET | CR0_NW | CR0_CD but that crashes some
60*967264cfSMark Johnston 	 * guests like Windows.
61*967264cfSMark Johnston 	 */
62*967264cfSMark Johnston 	cr0 = CR0_NE;
63*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR0, cr0)) != 0)
64*967264cfSMark Johnston 		goto done;
65*967264cfSMark Johnston 
66*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR2, zero)) != 0)
67*967264cfSMark Johnston 		goto done;
68*967264cfSMark Johnston 
69*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR3, zero)) != 0)
70*967264cfSMark Johnston 		goto done;
71*967264cfSMark Johnston 
72*967264cfSMark Johnston 	cr4 = 0;
73*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR4, cr4)) != 0)
74*967264cfSMark Johnston 		goto done;
75*967264cfSMark Johnston 
76*967264cfSMark Johnston 	/*
77*967264cfSMark Johnston 	 * CS: present, r/w, accessed, 16-bit, byte granularity, usable
78*967264cfSMark Johnston 	 */
79*967264cfSMark Johnston 	desc_base = 0xffff0000;
80*967264cfSMark Johnston 	desc_limit = 0xffff;
81*967264cfSMark Johnston 	desc_access = 0x0093;
82*967264cfSMark Johnston 	error = vm_set_desc(vcpu, VM_REG_GUEST_CS,
83*967264cfSMark Johnston 			    desc_base, desc_limit, desc_access);
84*967264cfSMark Johnston 	if (error)
85*967264cfSMark Johnston 		goto done;
86*967264cfSMark Johnston 
87*967264cfSMark Johnston 	sel = 0xf000;
88*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_CS, sel)) != 0)
89*967264cfSMark Johnston 		goto done;
90*967264cfSMark Johnston 
91*967264cfSMark Johnston 	/*
92*967264cfSMark Johnston 	 * SS,DS,ES,FS,GS: present, r/w, accessed, 16-bit, byte granularity
93*967264cfSMark Johnston 	 */
94*967264cfSMark Johnston 	desc_base = 0;
95*967264cfSMark Johnston 	desc_limit = 0xffff;
96*967264cfSMark Johnston 	desc_access = 0x0093;
97*967264cfSMark Johnston 	error = vm_set_desc(vcpu, VM_REG_GUEST_SS,
98*967264cfSMark Johnston 			    desc_base, desc_limit, desc_access);
99*967264cfSMark Johnston 	if (error)
100*967264cfSMark Johnston 		goto done;
101*967264cfSMark Johnston 
102*967264cfSMark Johnston 	error = vm_set_desc(vcpu, VM_REG_GUEST_DS,
103*967264cfSMark Johnston 			    desc_base, desc_limit, desc_access);
104*967264cfSMark Johnston 	if (error)
105*967264cfSMark Johnston 		goto done;
106*967264cfSMark Johnston 
107*967264cfSMark Johnston 	error = vm_set_desc(vcpu, VM_REG_GUEST_ES,
108*967264cfSMark Johnston 			    desc_base, desc_limit, desc_access);
109*967264cfSMark Johnston 	if (error)
110*967264cfSMark Johnston 		goto done;
111*967264cfSMark Johnston 
112*967264cfSMark Johnston 	error = vm_set_desc(vcpu, VM_REG_GUEST_FS,
113*967264cfSMark Johnston 			    desc_base, desc_limit, desc_access);
114*967264cfSMark Johnston 	if (error)
115*967264cfSMark Johnston 		goto done;
116*967264cfSMark Johnston 
117*967264cfSMark Johnston 	error = vm_set_desc(vcpu, VM_REG_GUEST_GS,
118*967264cfSMark Johnston 			    desc_base, desc_limit, desc_access);
119*967264cfSMark Johnston 	if (error)
120*967264cfSMark Johnston 		goto done;
121*967264cfSMark Johnston 
122*967264cfSMark Johnston 	sel = 0;
123*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_SS, sel)) != 0)
124*967264cfSMark Johnston 		goto done;
125*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_DS, sel)) != 0)
126*967264cfSMark Johnston 		goto done;
127*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_ES, sel)) != 0)
128*967264cfSMark Johnston 		goto done;
129*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_FS, sel)) != 0)
130*967264cfSMark Johnston 		goto done;
131*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_GS, sel)) != 0)
132*967264cfSMark Johnston 		goto done;
133*967264cfSMark Johnston 
134*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_EFER, zero)) != 0)
135*967264cfSMark Johnston 		goto done;
136*967264cfSMark Johnston 
137*967264cfSMark Johnston 	/* General purpose registers */
138*967264cfSMark Johnston 	rdx = 0xf00;
139*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RAX, zero)) != 0)
140*967264cfSMark Johnston 		goto done;
141*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RBX, zero)) != 0)
142*967264cfSMark Johnston 		goto done;
143*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RCX, zero)) != 0)
144*967264cfSMark Johnston 		goto done;
145*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RDX, rdx)) != 0)
146*967264cfSMark Johnston 		goto done;
147*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RSI, zero)) != 0)
148*967264cfSMark Johnston 		goto done;
149*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RDI, zero)) != 0)
150*967264cfSMark Johnston 		goto done;
151*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RBP, zero)) != 0)
152*967264cfSMark Johnston 		goto done;
153*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RSP, zero)) != 0)
154*967264cfSMark Johnston 		goto done;
155*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_R8, zero)) != 0)
156*967264cfSMark Johnston 		goto done;
157*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_R9, zero)) != 0)
158*967264cfSMark Johnston 		goto done;
159*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_R10, zero)) != 0)
160*967264cfSMark Johnston 		goto done;
161*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_R11, zero)) != 0)
162*967264cfSMark Johnston 		goto done;
163*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_R12, zero)) != 0)
164*967264cfSMark Johnston 		goto done;
165*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_R13, zero)) != 0)
166*967264cfSMark Johnston 		goto done;
167*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_R14, zero)) != 0)
168*967264cfSMark Johnston 		goto done;
169*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_R15, zero)) != 0)
170*967264cfSMark Johnston 		goto done;
171*967264cfSMark Johnston 
172*967264cfSMark Johnston 	/* GDTR, IDTR */
173*967264cfSMark Johnston 	desc_base = 0;
174*967264cfSMark Johnston 	desc_limit = 0xffff;
175*967264cfSMark Johnston 	desc_access = 0;
176*967264cfSMark Johnston 	error = vm_set_desc(vcpu, VM_REG_GUEST_GDTR,
177*967264cfSMark Johnston 			    desc_base, desc_limit, desc_access);
178*967264cfSMark Johnston 	if (error != 0)
179*967264cfSMark Johnston 		goto done;
180*967264cfSMark Johnston 
181*967264cfSMark Johnston 	error = vm_set_desc(vcpu, VM_REG_GUEST_IDTR,
182*967264cfSMark Johnston 			    desc_base, desc_limit, desc_access);
183*967264cfSMark Johnston 	if (error != 0)
184*967264cfSMark Johnston 		goto done;
185*967264cfSMark Johnston 
186*967264cfSMark Johnston 	/* TR */
187*967264cfSMark Johnston 	desc_base = 0;
188*967264cfSMark Johnston 	desc_limit = 0xffff;
189*967264cfSMark Johnston 	desc_access = 0x0000008b;
190*967264cfSMark Johnston 	error = vm_set_desc(vcpu, VM_REG_GUEST_TR, 0, 0, desc_access);
191*967264cfSMark Johnston 	if (error)
192*967264cfSMark Johnston 		goto done;
193*967264cfSMark Johnston 
194*967264cfSMark Johnston 	sel = 0;
195*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_TR, sel)) != 0)
196*967264cfSMark Johnston 		goto done;
197*967264cfSMark Johnston 
198*967264cfSMark Johnston 	/* LDTR */
199*967264cfSMark Johnston 	desc_base = 0;
200*967264cfSMark Johnston 	desc_limit = 0xffff;
201*967264cfSMark Johnston 	desc_access = 0x00000082;
202*967264cfSMark Johnston 	error = vm_set_desc(vcpu, VM_REG_GUEST_LDTR, desc_base,
203*967264cfSMark Johnston 			    desc_limit, desc_access);
204*967264cfSMark Johnston 	if (error)
205*967264cfSMark Johnston 		goto done;
206*967264cfSMark Johnston 
207*967264cfSMark Johnston 	sel = 0;
208*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_LDTR, 0)) != 0)
209*967264cfSMark Johnston 		goto done;
210*967264cfSMark Johnston 
211*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_DR6,
212*967264cfSMark Johnston 		 0xffff0ff0)) != 0)
213*967264cfSMark Johnston 		goto done;
214*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_DR7, 0x400)) !=
215*967264cfSMark Johnston 	    0)
216*967264cfSMark Johnston 		goto done;
217*967264cfSMark Johnston 
218*967264cfSMark Johnston 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_INTR_SHADOW,
219*967264cfSMark Johnston 		 zero)) != 0)
220*967264cfSMark Johnston 		goto done;
221*967264cfSMark Johnston 
222*967264cfSMark Johnston 	error = 0;
223*967264cfSMark Johnston done:
224*967264cfSMark Johnston 	return (error);
225*967264cfSMark Johnston }
226