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