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