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 * 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 * 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 * 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