1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2011 NetApp, Inc. 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, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <sys/types.h> 35 36 #include <machine/cpufunc.h> 37 #include <machine/vmm.h> 38 #include <machine/specialreg.h> 39 40 #include <vmmapi.h> 41 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 46 #include "xmsr.h" 47 48 static int cpu_vendor_intel, cpu_vendor_amd; 49 50 int 51 emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t num, uint64_t val) 52 { 53 54 if (cpu_vendor_intel) { 55 switch (num) { 56 #ifndef __FreeBSD__ 57 case MSR_PERFCTR0: 58 case MSR_PERFCTR1: 59 case MSR_EVNTSEL0: 60 case MSR_EVNTSEL1: 61 return (0); 62 #endif 63 case 0xd04: /* Sandy Bridge uncore PMCs */ 64 case 0xc24: 65 return (0); 66 case MSR_BIOS_UPDT_TRIG: 67 return (0); 68 case MSR_BIOS_SIGN: 69 return (0); 70 default: 71 break; 72 } 73 } else if (cpu_vendor_amd) { 74 switch (num) { 75 case MSR_HWCR: 76 /* 77 * Ignore writes to hardware configuration MSR. 78 */ 79 return (0); 80 81 case MSR_NB_CFG1: 82 case MSR_LS_CFG: 83 case MSR_IC_CFG: 84 return (0); /* Ignore writes */ 85 86 case MSR_PERFEVSEL0: 87 case MSR_PERFEVSEL1: 88 case MSR_PERFEVSEL2: 89 case MSR_PERFEVSEL3: 90 /* Ignore writes to the PerfEvtSel MSRs */ 91 return (0); 92 93 case MSR_K7_PERFCTR0: 94 case MSR_K7_PERFCTR1: 95 case MSR_K7_PERFCTR2: 96 case MSR_K7_PERFCTR3: 97 /* Ignore writes to the PerfCtr MSRs */ 98 return (0); 99 100 case MSR_P_STATE_CONTROL: 101 /* Ignore write to change the P-state */ 102 return (0); 103 104 default: 105 break; 106 } 107 } 108 return (-1); 109 } 110 111 int 112 emulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t num, uint64_t *val) 113 { 114 int error = 0; 115 116 if (cpu_vendor_intel) { 117 switch (num) { 118 case MSR_BIOS_SIGN: 119 case MSR_IA32_PLATFORM_ID: 120 case MSR_PKG_ENERGY_STATUS: 121 case MSR_PP0_ENERGY_STATUS: 122 case MSR_PP1_ENERGY_STATUS: 123 case MSR_DRAM_ENERGY_STATUS: 124 *val = 0; 125 break; 126 case MSR_RAPL_POWER_UNIT: 127 /* 128 * Use the default value documented in section 129 * "RAPL Interfaces" in Intel SDM vol3. 130 */ 131 *val = 0x000a1003; 132 break; 133 default: 134 error = -1; 135 break; 136 } 137 } else if (cpu_vendor_amd) { 138 switch (num) { 139 case MSR_BIOS_SIGN: 140 *val = 0; 141 break; 142 case MSR_HWCR: 143 /* 144 * Bios and Kernel Developer's Guides for AMD Families 145 * 12H, 14H, 15H and 16H. 146 */ 147 *val = 0x01000010; /* Reset value */ 148 *val |= 1 << 9; /* MONITOR/MWAIT disable */ 149 break; 150 151 case MSR_NB_CFG1: 152 case MSR_LS_CFG: 153 case MSR_IC_CFG: 154 /* 155 * The reset value is processor family dependent so 156 * just return 0. 157 */ 158 *val = 0; 159 break; 160 161 case MSR_PERFEVSEL0: 162 case MSR_PERFEVSEL1: 163 case MSR_PERFEVSEL2: 164 case MSR_PERFEVSEL3: 165 /* 166 * PerfEvtSel MSRs are not properly virtualized so just 167 * return zero. 168 */ 169 *val = 0; 170 break; 171 172 case MSR_K7_PERFCTR0: 173 case MSR_K7_PERFCTR1: 174 case MSR_K7_PERFCTR2: 175 case MSR_K7_PERFCTR3: 176 /* 177 * PerfCtr MSRs are not properly virtualized so just 178 * return zero. 179 */ 180 *val = 0; 181 break; 182 183 case MSR_SMM_ADDR: 184 case MSR_SMM_MASK: 185 /* 186 * Return the reset value defined in the AMD Bios and 187 * Kernel Developer's Guide. 188 */ 189 *val = 0; 190 break; 191 192 case MSR_P_STATE_LIMIT: 193 case MSR_P_STATE_CONTROL: 194 case MSR_P_STATE_STATUS: 195 case MSR_P_STATE_CONFIG(0): /* P0 configuration */ 196 *val = 0; 197 break; 198 199 /* 200 * OpenBSD guests test bit 0 of this MSR to detect if the 201 * workaround for erratum 721 is already applied. 202 * https://support.amd.com/TechDocs/41322_10h_Rev_Gd.pdf 203 */ 204 case 0xC0011029: 205 *val = 1; 206 break; 207 208 #ifndef __FreeBSD__ 209 case MSR_VM_CR: 210 /* 211 * We currently don't support nested virt. 212 * Windows seems to ignore the cpuid bits and reads this 213 * MSR anyways. 214 */ 215 *val = VM_CR_SVMDIS; 216 break; 217 #endif 218 219 default: 220 error = -1; 221 break; 222 } 223 } else { 224 error = -1; 225 } 226 return (error); 227 } 228 229 int 230 init_msr(void) 231 { 232 int error; 233 u_int regs[4]; 234 char cpu_vendor[13]; 235 236 do_cpuid(0, regs); 237 ((u_int *)&cpu_vendor)[0] = regs[1]; 238 ((u_int *)&cpu_vendor)[1] = regs[3]; 239 ((u_int *)&cpu_vendor)[2] = regs[2]; 240 cpu_vendor[12] = '\0'; 241 242 error = 0; 243 if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { 244 cpu_vendor_amd = 1; 245 } else if (strcmp(cpu_vendor, "GenuineIntel") == 0) { 246 cpu_vendor_intel = 1; 247 } else { 248 fprintf(stderr, "Unknown cpu vendor \"%s\"\n", cpu_vendor); 249 error = -1; 250 } 251 return (error); 252 } 253