1548b1122SMark Johnston /*-
2548b1122SMark Johnston * SPDX-License-Identifier: BSD-2-Clause
3548b1122SMark Johnston *
4548b1122SMark Johnston * Copyright (c) 2011 NetApp, Inc.
5548b1122SMark Johnston * All rights reserved.
6548b1122SMark Johnston *
7548b1122SMark Johnston * Redistribution and use in source and binary forms, with or without
8548b1122SMark Johnston * modification, are permitted provided that the following conditions
9548b1122SMark Johnston * are met:
10548b1122SMark Johnston * 1. Redistributions of source code must retain the above copyright
11548b1122SMark Johnston * notice, this list of conditions and the following disclaimer.
12548b1122SMark Johnston * 2. Redistributions in binary form must reproduce the above copyright
13548b1122SMark Johnston * notice, this list of conditions and the following disclaimer in the
14548b1122SMark Johnston * documentation and/or other materials provided with the distribution.
15548b1122SMark Johnston *
16548b1122SMark Johnston * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
17548b1122SMark Johnston * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18548b1122SMark Johnston * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19548b1122SMark Johnston * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
20548b1122SMark Johnston * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21548b1122SMark Johnston * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22548b1122SMark Johnston * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23548b1122SMark Johnston * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24548b1122SMark Johnston * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25548b1122SMark Johnston * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26548b1122SMark Johnston * SUCH DAMAGE.
27548b1122SMark Johnston */
28548b1122SMark Johnston
29548b1122SMark Johnston #include <sys/types.h>
30548b1122SMark Johnston
31548b1122SMark Johnston #include <machine/cpufunc.h>
32548b1122SMark Johnston #include <machine/vmm.h>
33548b1122SMark Johnston #include <machine/specialreg.h>
34548b1122SMark Johnston
35*f82af74cSMark Johnston #include <errno.h>
36548b1122SMark Johnston #include <stdio.h>
37548b1122SMark Johnston #include <stdlib.h>
38548b1122SMark Johnston #include <string.h>
39548b1122SMark Johnston
40*f82af74cSMark Johnston #include <vmmapi.h>
41*f82af74cSMark Johnston
42548b1122SMark Johnston #include "debug.h"
43548b1122SMark Johnston #include "xmsr.h"
44548b1122SMark Johnston
45548b1122SMark Johnston static int cpu_vendor_intel, cpu_vendor_amd, cpu_vendor_hygon;
46548b1122SMark Johnston
47548b1122SMark Johnston int
emulate_wrmsr(struct vcpu * vcpu __unused,uint32_t num,uint64_t val __unused)48548b1122SMark Johnston emulate_wrmsr(struct vcpu *vcpu __unused, uint32_t num, uint64_t val __unused)
49548b1122SMark Johnston {
50548b1122SMark Johnston
51548b1122SMark Johnston if (cpu_vendor_intel) {
52548b1122SMark Johnston switch (num) {
53548b1122SMark Johnston case 0xd04: /* Sandy Bridge uncore PMCs */
54548b1122SMark Johnston case 0xc24:
55548b1122SMark Johnston return (0);
56548b1122SMark Johnston case MSR_BIOS_UPDT_TRIG:
57548b1122SMark Johnston return (0);
58548b1122SMark Johnston case MSR_BIOS_SIGN:
59548b1122SMark Johnston return (0);
60548b1122SMark Johnston default:
61548b1122SMark Johnston break;
62548b1122SMark Johnston }
63548b1122SMark Johnston } else if (cpu_vendor_amd || cpu_vendor_hygon) {
64548b1122SMark Johnston switch (num) {
65548b1122SMark Johnston case MSR_HWCR:
66548b1122SMark Johnston /*
67548b1122SMark Johnston * Ignore writes to hardware configuration MSR.
68548b1122SMark Johnston */
69548b1122SMark Johnston return (0);
70548b1122SMark Johnston
71548b1122SMark Johnston case MSR_NB_CFG1:
72548b1122SMark Johnston case MSR_LS_CFG:
73548b1122SMark Johnston case MSR_IC_CFG:
74548b1122SMark Johnston return (0); /* Ignore writes */
75548b1122SMark Johnston
76548b1122SMark Johnston case MSR_PERFEVSEL0:
77548b1122SMark Johnston case MSR_PERFEVSEL1:
78548b1122SMark Johnston case MSR_PERFEVSEL2:
79548b1122SMark Johnston case MSR_PERFEVSEL3:
80548b1122SMark Johnston /* Ignore writes to the PerfEvtSel MSRs */
81548b1122SMark Johnston return (0);
82548b1122SMark Johnston
83548b1122SMark Johnston case MSR_K7_PERFCTR0:
84548b1122SMark Johnston case MSR_K7_PERFCTR1:
85548b1122SMark Johnston case MSR_K7_PERFCTR2:
86548b1122SMark Johnston case MSR_K7_PERFCTR3:
87548b1122SMark Johnston /* Ignore writes to the PerfCtr MSRs */
88548b1122SMark Johnston return (0);
89548b1122SMark Johnston
90548b1122SMark Johnston case MSR_P_STATE_CONTROL:
91548b1122SMark Johnston /* Ignore write to change the P-state */
92548b1122SMark Johnston return (0);
93548b1122SMark Johnston
94548b1122SMark Johnston default:
95548b1122SMark Johnston break;
96548b1122SMark Johnston }
97548b1122SMark Johnston }
98548b1122SMark Johnston return (-1);
99548b1122SMark Johnston }
100548b1122SMark Johnston
101548b1122SMark Johnston int
emulate_rdmsr(struct vcpu * vcpu __unused,uint32_t num,uint64_t * val)102548b1122SMark Johnston emulate_rdmsr(struct vcpu *vcpu __unused, uint32_t num, uint64_t *val)
103548b1122SMark Johnston {
104548b1122SMark Johnston int error = 0;
105548b1122SMark Johnston
106548b1122SMark Johnston if (cpu_vendor_intel) {
107548b1122SMark Johnston switch (num) {
108548b1122SMark Johnston case MSR_BIOS_SIGN:
109548b1122SMark Johnston case MSR_IA32_PLATFORM_ID:
110548b1122SMark Johnston case MSR_PKG_ENERGY_STATUS:
111548b1122SMark Johnston case MSR_PP0_ENERGY_STATUS:
112548b1122SMark Johnston case MSR_PP1_ENERGY_STATUS:
113548b1122SMark Johnston case MSR_DRAM_ENERGY_STATUS:
114548b1122SMark Johnston case MSR_MISC_FEATURE_ENABLES:
115548b1122SMark Johnston *val = 0;
116548b1122SMark Johnston break;
117548b1122SMark Johnston case MSR_RAPL_POWER_UNIT:
118548b1122SMark Johnston /*
119548b1122SMark Johnston * Use the default value documented in section
120548b1122SMark Johnston * "RAPL Interfaces" in Intel SDM vol3.
121548b1122SMark Johnston */
122548b1122SMark Johnston *val = 0x000a1003;
123548b1122SMark Johnston break;
124548b1122SMark Johnston case MSR_IA32_FEATURE_CONTROL:
125548b1122SMark Johnston /*
126548b1122SMark Johnston * Windows guests check this MSR.
127548b1122SMark Johnston * Set the lock bit to avoid writes
128548b1122SMark Johnston * to this MSR.
129548b1122SMark Johnston */
130548b1122SMark Johnston *val = IA32_FEATURE_CONTROL_LOCK;
131548b1122SMark Johnston break;
132548b1122SMark Johnston default:
133548b1122SMark Johnston error = -1;
134548b1122SMark Johnston break;
135548b1122SMark Johnston }
136548b1122SMark Johnston } else if (cpu_vendor_amd || cpu_vendor_hygon) {
137548b1122SMark Johnston switch (num) {
138548b1122SMark Johnston case MSR_BIOS_SIGN:
139548b1122SMark Johnston *val = 0;
140548b1122SMark Johnston break;
141548b1122SMark Johnston case MSR_HWCR:
142548b1122SMark Johnston /*
143548b1122SMark Johnston * Bios and Kernel Developer's Guides for AMD Families
144548b1122SMark Johnston * 12H, 14H, 15H and 16H.
145548b1122SMark Johnston */
146548b1122SMark Johnston *val = 0x01000010; /* Reset value */
147548b1122SMark Johnston *val |= 1 << 9; /* MONITOR/MWAIT disable */
148548b1122SMark Johnston break;
149548b1122SMark Johnston
150548b1122SMark Johnston case MSR_NB_CFG1:
151548b1122SMark Johnston case MSR_LS_CFG:
152548b1122SMark Johnston case MSR_IC_CFG:
153548b1122SMark Johnston /*
154548b1122SMark Johnston * The reset value is processor family dependent so
155548b1122SMark Johnston * just return 0.
156548b1122SMark Johnston */
157548b1122SMark Johnston *val = 0;
158548b1122SMark Johnston break;
159548b1122SMark Johnston
160548b1122SMark Johnston case MSR_PERFEVSEL0:
161548b1122SMark Johnston case MSR_PERFEVSEL1:
162548b1122SMark Johnston case MSR_PERFEVSEL2:
163548b1122SMark Johnston case MSR_PERFEVSEL3:
164548b1122SMark Johnston /*
165548b1122SMark Johnston * PerfEvtSel MSRs are not properly virtualized so just
166548b1122SMark Johnston * return zero.
167548b1122SMark Johnston */
168548b1122SMark Johnston *val = 0;
169548b1122SMark Johnston break;
170548b1122SMark Johnston
171548b1122SMark Johnston case MSR_K7_PERFCTR0:
172548b1122SMark Johnston case MSR_K7_PERFCTR1:
173548b1122SMark Johnston case MSR_K7_PERFCTR2:
174548b1122SMark Johnston case MSR_K7_PERFCTR3:
175548b1122SMark Johnston /*
176548b1122SMark Johnston * PerfCtr MSRs are not properly virtualized so just
177548b1122SMark Johnston * return zero.
178548b1122SMark Johnston */
179548b1122SMark Johnston *val = 0;
180548b1122SMark Johnston break;
181548b1122SMark Johnston
182548b1122SMark Johnston case MSR_SMM_ADDR:
183548b1122SMark Johnston case MSR_SMM_MASK:
184548b1122SMark Johnston /*
185548b1122SMark Johnston * Return the reset value defined in the AMD Bios and
186548b1122SMark Johnston * Kernel Developer's Guide.
187548b1122SMark Johnston */
188548b1122SMark Johnston *val = 0;
189548b1122SMark Johnston break;
190548b1122SMark Johnston
191548b1122SMark Johnston case MSR_P_STATE_LIMIT:
192548b1122SMark Johnston case MSR_P_STATE_CONTROL:
193548b1122SMark Johnston case MSR_P_STATE_STATUS:
194548b1122SMark Johnston case MSR_P_STATE_CONFIG(0): /* P0 configuration */
195548b1122SMark Johnston *val = 0;
196548b1122SMark Johnston break;
197548b1122SMark Johnston
198548b1122SMark Johnston /*
199548b1122SMark Johnston * OpenBSD guests test bit 0 of this MSR to detect if the
200548b1122SMark Johnston * workaround for erratum 721 is already applied.
201548b1122SMark Johnston * https://support.amd.com/TechDocs/41322_10h_Rev_Gd.pdf
202548b1122SMark Johnston */
203548b1122SMark Johnston case 0xC0011029:
204548b1122SMark Johnston *val = 1;
205548b1122SMark Johnston break;
206548b1122SMark Johnston
207548b1122SMark Johnston default:
208548b1122SMark Johnston error = -1;
209548b1122SMark Johnston break;
210548b1122SMark Johnston }
211548b1122SMark Johnston } else {
212548b1122SMark Johnston error = -1;
213548b1122SMark Johnston }
214548b1122SMark Johnston return (error);
215548b1122SMark Johnston }
216548b1122SMark Johnston
217548b1122SMark Johnston int
init_msr(void)218548b1122SMark Johnston init_msr(void)
219548b1122SMark Johnston {
220548b1122SMark Johnston int error;
221548b1122SMark Johnston u_int regs[4];
222548b1122SMark Johnston char cpu_vendor[13];
223548b1122SMark Johnston
224548b1122SMark Johnston do_cpuid(0, regs);
225548b1122SMark Johnston ((u_int *)&cpu_vendor)[0] = regs[1];
226548b1122SMark Johnston ((u_int *)&cpu_vendor)[1] = regs[3];
227548b1122SMark Johnston ((u_int *)&cpu_vendor)[2] = regs[2];
228548b1122SMark Johnston cpu_vendor[12] = '\0';
229548b1122SMark Johnston
230548b1122SMark Johnston error = 0;
231548b1122SMark Johnston if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
232548b1122SMark Johnston cpu_vendor_amd = 1;
233548b1122SMark Johnston } else if (strcmp(cpu_vendor, "HygonGenuine") == 0) {
234548b1122SMark Johnston cpu_vendor_hygon = 1;
235548b1122SMark Johnston } else if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
236548b1122SMark Johnston cpu_vendor_intel = 1;
237548b1122SMark Johnston } else {
238548b1122SMark Johnston EPRINTLN("Unknown cpu vendor \"%s\"", cpu_vendor);
239*f82af74cSMark Johnston error = ENOENT;
240548b1122SMark Johnston }
241548b1122SMark Johnston return (error);
242548b1122SMark Johnston }
243