1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2013 Anish Gupta (akgupt3@gmail.com)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice unmodified, this list of conditions, and the following
12 * disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*
30 * This file and its contents are supplied under the terms of the
31 * Common Development and Distribution License ("CDDL"), version 1.0.
32 * You may only use this file in accordance with the terms of version
33 * 1.0 of the CDDL.
34 *
35 * A full copy of the text of the CDDL should have accompanied this
36 * source. A copy of the CDDL is also available via the Internet at
37 * http://www.illumos.org/license/CDDL.
38 */
39 /* This file is dual-licensed; see usr/src/contrib/bhyve/LICENSE */
40
41 /*
42 * Copyright 2020 Oxide Computer Company
43 */
44
45 #include <sys/cdefs.h>
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/x86_archext.h>
50
51 #include <machine/specialreg.h>
52 #include <machine/vmm.h>
53
54 #include "vmcb.h"
55 #include "svm.h"
56
57 struct vmcb_segment *
vmcb_segptr(struct vmcb * vmcb,int type)58 vmcb_segptr(struct vmcb *vmcb, int type)
59 {
60 struct vmcb_state *state = &vmcb->state;
61
62 switch (type) {
63 case VM_REG_GUEST_CS:
64 return (&state->cs);
65 case VM_REG_GUEST_DS:
66 return (&state->ds);
67 case VM_REG_GUEST_ES:
68 return (&state->es);
69 case VM_REG_GUEST_FS:
70 return (&state->fs);
71 case VM_REG_GUEST_GS:
72 return (&state->gs);
73 case VM_REG_GUEST_SS:
74 return (&state->ss);
75 case VM_REG_GUEST_GDTR:
76 return (&state->gdt);
77 case VM_REG_GUEST_IDTR:
78 return (&state->idt);
79 case VM_REG_GUEST_LDTR:
80 return (&state->ldt);
81 case VM_REG_GUEST_TR:
82 return (&state->tr);
83 default:
84 panic("unexpected seg %d", type);
85 }
86 }
87
88 uint64_t *
vmcb_regptr(struct vmcb * vmcb,int ident,uint32_t * dirtyp)89 vmcb_regptr(struct vmcb *vmcb, int ident, uint32_t *dirtyp)
90 {
91 struct vmcb_state *state;
92 uint64_t *res = NULL;
93 uint32_t dirty = VMCB_CACHE_NONE;
94
95 state = &vmcb->state;
96
97 switch (ident) {
98 case VM_REG_GUEST_CR2:
99 res = &state->cr2;
100 dirty = VMCB_CACHE_CR2;
101 break;
102
103 case VM_REG_GUEST_CR3:
104 res = &state->cr3;
105 dirty = VMCB_CACHE_CR;
106 break;
107
108 case VM_REG_GUEST_CR4:
109 res = &state->cr4;
110 dirty = VMCB_CACHE_CR;
111 break;
112
113 case VM_REG_GUEST_DR6:
114 res = &state->dr6;
115 dirty = VMCB_CACHE_DR;
116 break;
117
118 case VM_REG_GUEST_DR7:
119 res = &state->dr7;
120 dirty = VMCB_CACHE_DR;
121 break;
122
123 case VM_REG_GUEST_EFER:
124 res = &state->efer;
125 dirty = VMCB_CACHE_CR;
126 break;
127
128 case VM_REG_GUEST_RAX:
129 res = &state->rax;
130 break;
131
132 case VM_REG_GUEST_RFLAGS:
133 res = &state->rflags;
134 break;
135
136 case VM_REG_GUEST_RIP:
137 res = &state->rip;
138 break;
139
140 case VM_REG_GUEST_RSP:
141 res = &state->rsp;
142 break;
143
144 default:
145 panic("unexpected register %d", ident);
146 break;
147 }
148
149 ASSERT(res != NULL);
150 if (dirtyp != NULL) {
151 *dirtyp |= dirty;
152 }
153 return (res);
154 }
155
156 uint64_t *
vmcb_msr_ptr(struct vmcb * vmcb,uint32_t msr,uint32_t * dirtyp)157 vmcb_msr_ptr(struct vmcb *vmcb, uint32_t msr, uint32_t *dirtyp)
158 {
159 uint64_t *res = NULL;
160 uint32_t dirty = 0;
161 struct vmcb_state *state = &vmcb->state;
162
163 switch (msr) {
164 case MSR_EFER:
165 res = &state->efer;
166 dirty = VMCB_CACHE_CR;
167 break;
168
169 case MSR_GSBASE:
170 res = &state->gs.base;
171 dirty = VMCB_CACHE_SEG;
172 break;
173 case MSR_FSBASE:
174 res = &state->fs.base;
175 dirty = VMCB_CACHE_SEG;
176 break;
177 case MSR_KGSBASE:
178 res = &state->kernelgsbase;
179 break;
180
181 case MSR_STAR:
182 res = &state->star;
183 break;
184 case MSR_LSTAR:
185 res = &state->lstar;
186 break;
187 case MSR_CSTAR:
188 res = &state->cstar;
189 break;
190 case MSR_SF_MASK:
191 res = &state->sfmask;
192 break;
193
194 case MSR_SYSENTER_CS_MSR:
195 res = &state->sysenter_cs;
196 break;
197 case MSR_SYSENTER_ESP_MSR:
198 res = &state->sysenter_esp;
199 break;
200 case MSR_SYSENTER_EIP_MSR:
201 res = &state->sysenter_eip;
202 break;
203
204 case MSR_PAT:
205 res = &state->g_pat;
206 dirty = VMCB_CACHE_NP;
207 break;
208
209 case MSR_DEBUGCTL:
210 res = &state->dbgctl;
211 dirty = VMCB_CACHE_LBR;
212 break;
213 case MSR_LBR_FROM:
214 res = &state->br_from;
215 dirty = VMCB_CACHE_LBR;
216 break;
217 case MSR_LBR_TO:
218 res = &state->br_to;
219 dirty = VMCB_CACHE_LBR;
220 break;
221 case MSR_LEX_FROM:
222 res = &state->int_from;
223 dirty = VMCB_CACHE_LBR;
224 break;
225 case MSR_LEX_TO:
226 res = &state->int_to;
227 dirty = VMCB_CACHE_LBR;
228 break;
229 }
230
231 if (res != NULL && dirtyp != NULL) {
232 *dirtyp = dirty;
233 }
234 return (res);
235 }
236