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