xref: /illumos-gate/usr/src/uts/intel/io/vmm/amd/vmcb.c (revision 1e56f352c1c208679012bca47d552e127f5b1072)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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  * Copyright 2020 Oxide Computer Company
40  */
41 
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD$");
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/x86_archext.h>
48 
49 #include <machine/specialreg.h>
50 #include <machine/vmm.h>
51 
52 #include "vmcb.h"
53 #include "svm.h"
54 
55 struct vmcb_segment *
56 vmcb_segptr(struct vmcb *vmcb, int type)
57 {
58 	struct vmcb_state *state = &vmcb->state;
59 
60 	switch (type) {
61 	case VM_REG_GUEST_CS:
62 		return (&state->cs);
63 	case VM_REG_GUEST_DS:
64 		return (&state->ds);
65 	case VM_REG_GUEST_ES:
66 		return (&state->es);
67 	case VM_REG_GUEST_FS:
68 		return (&state->fs);
69 	case VM_REG_GUEST_GS:
70 		return (&state->gs);
71 	case VM_REG_GUEST_SS:
72 		return (&state->ss);
73 	case VM_REG_GUEST_GDTR:
74 		return (&state->gdt);
75 	case VM_REG_GUEST_IDTR:
76 		return (&state->idt);
77 	case VM_REG_GUEST_LDTR:
78 		return (&state->ldt);
79 	case VM_REG_GUEST_TR:
80 		return (&state->tr);
81 	default:
82 		panic("unexpected seg %d", type);
83 	}
84 }
85 
86 uint64_t *
87 vmcb_regptr(struct vmcb *vmcb, int ident, uint32_t *dirtyp)
88 {
89 	struct vmcb_state *state;
90 	uint64_t *res = NULL;
91 	uint32_t dirty = VMCB_CACHE_NONE;
92 
93 	state = &vmcb->state;
94 
95 	switch (ident) {
96 	case VM_REG_GUEST_CR2:
97 		res = &state->cr2;
98 		dirty = VMCB_CACHE_CR2;
99 		break;
100 
101 	case VM_REG_GUEST_CR3:
102 		res = &state->cr3;
103 		dirty = VMCB_CACHE_CR;
104 		break;
105 
106 	case VM_REG_GUEST_CR4:
107 		res = &state->cr4;
108 		dirty = VMCB_CACHE_CR;
109 		break;
110 
111 	case VM_REG_GUEST_DR6:
112 		res = &state->dr6;
113 		dirty = VMCB_CACHE_DR;
114 		break;
115 
116 	case VM_REG_GUEST_DR7:
117 		res = &state->dr7;
118 		dirty = VMCB_CACHE_DR;
119 		break;
120 
121 	case VM_REG_GUEST_EFER:
122 		res = &state->efer;
123 		dirty = VMCB_CACHE_CR;
124 		break;
125 
126 	case VM_REG_GUEST_RAX:
127 		res = &state->rax;
128 		break;
129 
130 	case VM_REG_GUEST_RFLAGS:
131 		res = &state->rflags;
132 		break;
133 
134 	case VM_REG_GUEST_RIP:
135 		res = &state->rip;
136 		break;
137 
138 	case VM_REG_GUEST_RSP:
139 		res = &state->rsp;
140 		break;
141 
142 	default:
143 		panic("unexpected register %d", ident);
144 		break;
145 	}
146 
147 	ASSERT(res != NULL);
148 	if (dirtyp != NULL) {
149 		*dirtyp |= dirty;
150 	}
151 	return (res);
152 }
153 
154 uint64_t *
155 vmcb_msr_ptr(struct vmcb *vmcb, uint32_t msr, uint32_t *dirtyp)
156 {
157 	uint64_t *res = NULL;
158 	uint32_t dirty = 0;
159 	struct vmcb_state *state = &vmcb->state;
160 
161 	switch (msr) {
162 	case MSR_EFER:
163 		res = &state->efer;
164 		dirty = VMCB_CACHE_CR;
165 		break;
166 
167 	case MSR_GSBASE:
168 		res = &state->gs.base;
169 		dirty = VMCB_CACHE_SEG;
170 		break;
171 	case MSR_FSBASE:
172 		res = &state->fs.base;
173 		dirty = VMCB_CACHE_SEG;
174 		break;
175 	case MSR_KGSBASE:
176 		res = &state->kernelgsbase;
177 		break;
178 
179 	case MSR_STAR:
180 		res = &state->star;
181 		break;
182 	case MSR_LSTAR:
183 		res = &state->lstar;
184 		break;
185 	case MSR_CSTAR:
186 		res = &state->cstar;
187 		break;
188 	case MSR_SF_MASK:
189 		res = &state->sfmask;
190 		break;
191 
192 	case MSR_SYSENTER_CS_MSR:
193 		res = &state->sysenter_cs;
194 		break;
195 	case MSR_SYSENTER_ESP_MSR:
196 		res = &state->sysenter_esp;
197 		break;
198 	case MSR_SYSENTER_EIP_MSR:
199 		res = &state->sysenter_eip;
200 		break;
201 
202 	case MSR_PAT:
203 		res = &state->g_pat;
204 		dirty = VMCB_CACHE_NP;
205 		break;
206 
207 	case MSR_DEBUGCTL:
208 		res = &state->dbgctl;
209 		dirty = VMCB_CACHE_LBR;
210 		break;
211 	case MSR_LBR_FROM:
212 		res = &state->br_from;
213 		dirty = VMCB_CACHE_LBR;
214 		break;
215 	case MSR_LBR_TO:
216 		res = &state->br_to;
217 		dirty = VMCB_CACHE_LBR;
218 		break;
219 	case MSR_LEX_FROM:
220 		res = &state->int_from;
221 		dirty = VMCB_CACHE_LBR;
222 		break;
223 	case MSR_LEX_TO:
224 		res = &state->int_to;
225 		dirty = VMCB_CACHE_LBR;
226 		break;
227 	}
228 
229 	if (res != NULL && dirtyp != NULL) {
230 		*dirtyp = dirty;
231 	}
232 	return (res);
233 }
234