1 /*- 2 * Copyright (c) 2011 NetApp, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/cpuset.h> 35 36 #include <machine/cpufunc.h> 37 #include <machine/specialreg.h> 38 #include <machine/vmm.h> 39 40 #include "vmx.h" 41 #include "vmx_msr.h" 42 43 static boolean_t 44 vmx_ctl_allows_one_setting(uint64_t msr_val, int bitpos) 45 { 46 47 if (msr_val & (1UL << (bitpos + 32))) 48 return (TRUE); 49 else 50 return (FALSE); 51 } 52 53 static boolean_t 54 vmx_ctl_allows_zero_setting(uint64_t msr_val, int bitpos) 55 { 56 57 if ((msr_val & (1UL << bitpos)) == 0) 58 return (TRUE); 59 else 60 return (FALSE); 61 } 62 63 uint32_t 64 vmx_revision(void) 65 { 66 67 return (rdmsr(MSR_VMX_BASIC) & 0xffffffff); 68 } 69 70 /* 71 * Generate a bitmask to be used for the VMCS execution control fields. 72 * 73 * The caller specifies what bits should be set to one in 'ones_mask' 74 * and what bits should be set to zero in 'zeros_mask'. The don't-care 75 * bits are set to the default value. The default values are obtained 76 * based on "Algorithm 3" in Section 27.5.1 "Algorithms for Determining 77 * VMX Capabilities". 78 * 79 * Returns zero on success and non-zero on error. 80 */ 81 int 82 vmx_set_ctlreg(int ctl_reg, int true_ctl_reg, uint32_t ones_mask, 83 uint32_t zeros_mask, uint32_t *retval) 84 { 85 int i; 86 uint64_t val, trueval; 87 boolean_t true_ctls_avail, one_allowed, zero_allowed; 88 89 /* We cannot ask the same bit to be set to both '1' and '0' */ 90 if ((ones_mask ^ zeros_mask) != (ones_mask | zeros_mask)) 91 return (EINVAL); 92 93 if (rdmsr(MSR_VMX_BASIC) & (1UL << 55)) 94 true_ctls_avail = TRUE; 95 else 96 true_ctls_avail = FALSE; 97 98 val = rdmsr(ctl_reg); 99 if (true_ctls_avail) 100 trueval = rdmsr(true_ctl_reg); /* step c */ 101 else 102 trueval = val; /* step a */ 103 104 for (i = 0; i < 32; i++) { 105 one_allowed = vmx_ctl_allows_one_setting(trueval, i); 106 zero_allowed = vmx_ctl_allows_zero_setting(trueval, i); 107 108 KASSERT(one_allowed || zero_allowed, 109 ("invalid zero/one setting for bit %d of ctl 0x%0x, " 110 "truectl 0x%0x\n", i, ctl_reg, true_ctl_reg)); 111 112 if (zero_allowed && !one_allowed) { /* b(i),c(i) */ 113 if (ones_mask & (1 << i)) 114 return (EINVAL); 115 *retval &= ~(1 << i); 116 } else if (one_allowed && !zero_allowed) { /* b(i),c(i) */ 117 if (zeros_mask & (1 << i)) 118 return (EINVAL); 119 *retval |= 1 << i; 120 } else { 121 if (zeros_mask & (1 << i)) /* b(ii),c(ii) */ 122 *retval &= ~(1 << i); 123 else if (ones_mask & (1 << i)) /* b(ii), c(ii) */ 124 *retval |= 1 << i; 125 else if (!true_ctls_avail) 126 *retval &= ~(1 << i); /* b(iii) */ 127 else if (vmx_ctl_allows_zero_setting(val, i))/* c(iii)*/ 128 *retval &= ~(1 << i); 129 else if (vmx_ctl_allows_one_setting(val, i)) /* c(iv) */ 130 *retval |= 1 << i; 131 else { 132 panic("vmx_set_ctlreg: unable to determine " 133 "correct value of ctl bit %d for msr " 134 "0x%0x and true msr 0x%0x", i, ctl_reg, 135 true_ctl_reg); 136 } 137 } 138 } 139 140 return (0); 141 } 142 143 void 144 msr_bitmap_initialize(char *bitmap) 145 { 146 147 memset(bitmap, 0xff, PAGE_SIZE); 148 } 149 150 int 151 msr_bitmap_change_access(char *bitmap, u_int msr, int access) 152 { 153 int byte, bit; 154 155 if (msr <= 0x00001FFF) 156 byte = msr / 8; 157 else if (msr >= 0xC0000000 && msr <= 0xC0001FFF) 158 byte = 1024 + (msr - 0xC0000000) / 8; 159 else 160 return (EINVAL); 161 162 bit = msr & 0x7; 163 164 if (access & MSR_BITMAP_ACCESS_READ) 165 bitmap[byte] &= ~(1 << bit); 166 else 167 bitmap[byte] |= 1 << bit; 168 169 byte += 2048; 170 if (access & MSR_BITMAP_ACCESS_WRITE) 171 bitmap[byte] &= ~(1 << bit); 172 else 173 bitmap[byte] |= 1 << bit; 174 175 return (0); 176 } 177 178 static uint64_t misc_enable; 179 static uint64_t host_msrs[GUEST_MSR_NUM]; 180 181 void 182 vmx_msr_init(void) 183 { 184 /* 185 * It is safe to cache the values of the following MSRs because 186 * they don't change based on curcpu, curproc or curthread. 187 */ 188 host_msrs[IDX_MSR_LSTAR] = rdmsr(MSR_LSTAR); 189 host_msrs[IDX_MSR_CSTAR] = rdmsr(MSR_CSTAR); 190 host_msrs[IDX_MSR_STAR] = rdmsr(MSR_STAR); 191 host_msrs[IDX_MSR_SF_MASK] = rdmsr(MSR_SF_MASK); 192 193 /* 194 * Initialize emulated MSRs 195 */ 196 misc_enable = rdmsr(MSR_IA32_MISC_ENABLE); 197 /* 198 * Set mandatory bits 199 * 11: branch trace disabled 200 * 12: PEBS unavailable 201 * Clear unsupported features 202 * 16: SpeedStep enable 203 * 18: enable MONITOR FSM 204 */ 205 misc_enable |= (1 << 12) | (1 << 11); 206 misc_enable &= ~((1 << 18) | (1 << 16)); 207 } 208 209 void 210 vmx_msr_guest_init(struct vmx *vmx, int vcpuid) 211 { 212 /* 213 * The permissions bitmap is shared between all vcpus so initialize it 214 * once when initializing the vBSP. 215 */ 216 if (vcpuid == 0) { 217 guest_msr_rw(vmx, MSR_LSTAR); 218 guest_msr_rw(vmx, MSR_CSTAR); 219 guest_msr_rw(vmx, MSR_STAR); 220 guest_msr_rw(vmx, MSR_SF_MASK); 221 guest_msr_rw(vmx, MSR_KGSBASE); 222 } 223 return; 224 } 225 226 void 227 vmx_msr_guest_enter(struct vmx *vmx, int vcpuid) 228 { 229 uint64_t *guest_msrs = vmx->guest_msrs[vcpuid]; 230 231 /* Save host MSRs (if any) and restore guest MSRs */ 232 wrmsr(MSR_LSTAR, guest_msrs[IDX_MSR_LSTAR]); 233 wrmsr(MSR_CSTAR, guest_msrs[IDX_MSR_CSTAR]); 234 wrmsr(MSR_STAR, guest_msrs[IDX_MSR_STAR]); 235 wrmsr(MSR_SF_MASK, guest_msrs[IDX_MSR_SF_MASK]); 236 wrmsr(MSR_KGSBASE, guest_msrs[IDX_MSR_KGSBASE]); 237 } 238 239 void 240 vmx_msr_guest_exit(struct vmx *vmx, int vcpuid) 241 { 242 uint64_t *guest_msrs = vmx->guest_msrs[vcpuid]; 243 244 /* Save guest MSRs */ 245 guest_msrs[IDX_MSR_LSTAR] = rdmsr(MSR_LSTAR); 246 guest_msrs[IDX_MSR_CSTAR] = rdmsr(MSR_CSTAR); 247 guest_msrs[IDX_MSR_STAR] = rdmsr(MSR_STAR); 248 guest_msrs[IDX_MSR_SF_MASK] = rdmsr(MSR_SF_MASK); 249 guest_msrs[IDX_MSR_KGSBASE] = rdmsr(MSR_KGSBASE); 250 251 /* Restore host MSRs */ 252 wrmsr(MSR_LSTAR, host_msrs[IDX_MSR_LSTAR]); 253 wrmsr(MSR_CSTAR, host_msrs[IDX_MSR_CSTAR]); 254 wrmsr(MSR_STAR, host_msrs[IDX_MSR_STAR]); 255 wrmsr(MSR_SF_MASK, host_msrs[IDX_MSR_SF_MASK]); 256 257 /* MSR_KGSBASE will be restored on the way back to userspace */ 258 } 259 260 int 261 vmx_rdmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t *val, bool *retu) 262 { 263 int error = 0; 264 265 switch (num) { 266 case MSR_IA32_MISC_ENABLE: 267 *val = misc_enable; 268 break; 269 default: 270 error = EINVAL; 271 break; 272 } 273 return (error); 274 } 275 276 int 277 vmx_wrmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t val, bool *retu) 278 { 279 int error = 0; 280 281 switch (num) { 282 default: 283 error = EINVAL; 284 break; 285 } 286 287 return (error); 288 } 289