1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
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
29
30 #include <sys/types.h>
31
32 #include <machine/cpufunc.h>
33 #include <machine/vmm.h>
34 #include <machine/specialreg.h>
35
36 #include <errno.h>
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41
42 #include <vmmapi.h>
43
44 #include "debug.h"
45 #include "xmsr.h"
46
47 static int cpu_vendor_intel, cpu_vendor_amd, cpu_vendor_hygon;
48
49 int
emulate_wrmsr(struct vcpu * vcpu __unused,uint32_t num,uint64_t val __unused)50 emulate_wrmsr(struct vcpu *vcpu __unused, uint32_t num, uint64_t val __unused)
51 {
52
53 if (cpu_vendor_intel) {
54 switch (num) {
55 #ifndef __FreeBSD__
56 case MSR_PERFCTR0:
57 case MSR_PERFCTR1:
58 case MSR_EVNTSEL0:
59 case MSR_EVNTSEL1:
60 return (0);
61 #endif
62 case 0xd04: /* Sandy Bridge uncore PMCs */
63 case 0xc24:
64 return (0);
65 case MSR_BIOS_UPDT_TRIG:
66 return (0);
67 case MSR_BIOS_SIGN:
68 return (0);
69 default:
70 break;
71 }
72 } else if (cpu_vendor_amd || cpu_vendor_hygon) {
73 switch (num) {
74 case MSR_HWCR:
75 /*
76 * Ignore writes to hardware configuration MSR.
77 */
78 return (0);
79
80 case MSR_NB_CFG1:
81 case MSR_LS_CFG:
82 case MSR_IC_CFG:
83 return (0); /* Ignore writes */
84
85 case MSR_PERFEVSEL0:
86 case MSR_PERFEVSEL1:
87 case MSR_PERFEVSEL2:
88 case MSR_PERFEVSEL3:
89 /* Ignore writes to the PerfEvtSel MSRs */
90 return (0);
91
92 case MSR_K7_PERFCTR0:
93 case MSR_K7_PERFCTR1:
94 case MSR_K7_PERFCTR2:
95 case MSR_K7_PERFCTR3:
96 /* Ignore writes to the PerfCtr MSRs */
97 return (0);
98
99 case MSR_P_STATE_CONTROL:
100 /* Ignore write to change the P-state */
101 return (0);
102
103 default:
104 break;
105 }
106 }
107 return (-1);
108 }
109
110 int
emulate_rdmsr(struct vcpu * vcpu __unused,uint32_t num,uint64_t * val)111 emulate_rdmsr(struct vcpu *vcpu __unused, uint32_t num, uint64_t *val)
112 {
113 int error = 0;
114
115 if (cpu_vendor_intel) {
116 switch (num) {
117 case MSR_BIOS_SIGN:
118 case MSR_IA32_PLATFORM_ID:
119 case MSR_PKG_ENERGY_STATUS:
120 case MSR_PP0_ENERGY_STATUS:
121 case MSR_PP1_ENERGY_STATUS:
122 case MSR_DRAM_ENERGY_STATUS:
123 case MSR_MISC_FEATURE_ENABLES:
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 case MSR_IA32_FEATURE_CONTROL:
134 /*
135 * Windows guests check this MSR.
136 * Set the lock bit to avoid writes
137 * to this MSR.
138 */
139 *val = IA32_FEATURE_CONTROL_LOCK;
140 break;
141 default:
142 error = -1;
143 break;
144 }
145 } else if (cpu_vendor_amd || cpu_vendor_hygon) {
146 switch (num) {
147 case MSR_BIOS_SIGN:
148 *val = 0;
149 break;
150 case MSR_HWCR:
151 /*
152 * Bios and Kernel Developer's Guides for AMD Families
153 * 12H, 14H, 15H and 16H.
154 */
155 *val = 0x01000010; /* Reset value */
156 *val |= 1 << 9; /* MONITOR/MWAIT disable */
157 break;
158
159 case MSR_NB_CFG1:
160 case MSR_LS_CFG:
161 case MSR_IC_CFG:
162 /*
163 * The reset value is processor family dependent so
164 * just return 0.
165 */
166 *val = 0;
167 break;
168
169 case MSR_PERFEVSEL0:
170 case MSR_PERFEVSEL1:
171 case MSR_PERFEVSEL2:
172 case MSR_PERFEVSEL3:
173 /*
174 * PerfEvtSel MSRs are not properly virtualized so just
175 * return zero.
176 */
177 *val = 0;
178 break;
179
180 case MSR_K7_PERFCTR0:
181 case MSR_K7_PERFCTR1:
182 case MSR_K7_PERFCTR2:
183 case MSR_K7_PERFCTR3:
184 /*
185 * PerfCtr MSRs are not properly virtualized so just
186 * return zero.
187 */
188 *val = 0;
189 break;
190
191 case MSR_SMM_ADDR:
192 case MSR_SMM_MASK:
193 /*
194 * Return the reset value defined in the AMD Bios and
195 * Kernel Developer's Guide.
196 */
197 *val = 0;
198 break;
199
200 case MSR_P_STATE_LIMIT:
201 case MSR_P_STATE_CONTROL:
202 case MSR_P_STATE_STATUS:
203 case MSR_P_STATE_CONFIG(0): /* P0 configuration */
204 *val = 0;
205 break;
206
207 /*
208 * OpenBSD guests test bit 0 of this MSR to detect if the
209 * workaround for erratum 721 is already applied.
210 * https://support.amd.com/TechDocs/41322_10h_Rev_Gd.pdf
211 */
212 case 0xC0011029:
213 *val = 1;
214 break;
215
216 #ifndef __FreeBSD__
217 case MSR_VM_CR:
218 /*
219 * We currently don't support nested virt.
220 * Windows seems to ignore the cpuid bits and reads this
221 * MSR anyways.
222 */
223 *val = VM_CR_SVMDIS;
224 break;
225 #endif
226
227 default:
228 error = -1;
229 break;
230 }
231 } else {
232 error = -1;
233 }
234 return (error);
235 }
236
237 int
init_msr(void)238 init_msr(void)
239 {
240 int error;
241 u_int regs[4];
242 char cpu_vendor[13];
243
244 do_cpuid(0, regs);
245 ((u_int *)&cpu_vendor)[0] = regs[1];
246 ((u_int *)&cpu_vendor)[1] = regs[3];
247 ((u_int *)&cpu_vendor)[2] = regs[2];
248 cpu_vendor[12] = '\0';
249
250 error = 0;
251 if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
252 cpu_vendor_amd = 1;
253 } else if (strcmp(cpu_vendor, "HygonGenuine") == 0) {
254 cpu_vendor_hygon = 1;
255 } else if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
256 cpu_vendor_intel = 1;
257 } else {
258 EPRINTLN("Unknown cpu vendor \"%s\"", cpu_vendor);
259 error = ENOENT;
260 }
261 return (error);
262 }
263