xref: /freebsd/usr.sbin/bhyve/amd64/xmsr.c (revision 4d65a7c6)
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 
35f82af74cSMark Johnston #include <errno.h>
36548b1122SMark Johnston #include <stdio.h>
37548b1122SMark Johnston #include <stdlib.h>
38548b1122SMark Johnston #include <string.h>
39548b1122SMark Johnston 
40f82af74cSMark Johnston #include <vmmapi.h>
41f82af74cSMark 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);
239f82af74cSMark Johnston 		error = ENOENT;
240548b1122SMark Johnston 	}
241548b1122SMark Johnston 	return (error);
242548b1122SMark Johnston }
243