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