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