xref: /illumos-gate/usr/src/cmd/bhyve/amd64/xmsr.c (revision 5c4a5fe16715fb423db76577a6883b5bbecdbe45)
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