1221828Sgrehan/*-
2221828Sgrehan * Copyright (c) 2011 NetApp, Inc.
3221828Sgrehan * All rights reserved.
4221828Sgrehan *
5221828Sgrehan * Redistribution and use in source and binary forms, with or without
6221828Sgrehan * modification, are permitted provided that the following conditions
7221828Sgrehan * are met:
8221828Sgrehan * 1. Redistributions of source code must retain the above copyright
9221828Sgrehan *    notice, this list of conditions and the following disclaimer.
10221828Sgrehan * 2. Redistributions in binary form must reproduce the above copyright
11221828Sgrehan *    notice, this list of conditions and the following disclaimer in the
12221828Sgrehan *    documentation and/or other materials provided with the distribution.
13221828Sgrehan *
14221828Sgrehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
15221828Sgrehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16221828Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17221828Sgrehan * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
18221828Sgrehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19221828Sgrehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20221828Sgrehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21221828Sgrehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22221828Sgrehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23221828Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24221828Sgrehan * SUCH DAMAGE.
25221828Sgrehan *
26221828Sgrehan * $FreeBSD: releng/10.3/usr.sbin/bhyve/xmsr.c 284894 2015-06-27 22:48:22Z neel $
27221828Sgrehan */
28221828Sgrehan
29221828Sgrehan#include <sys/cdefs.h>
30221828Sgrehan__FBSDID("$FreeBSD: releng/10.3/usr.sbin/bhyve/xmsr.c 284894 2015-06-27 22:48:22Z neel $");
31221828Sgrehan
32240912Sneel#include <sys/types.h>
33221828Sgrehan
34276349Sneel#include <machine/cpufunc.h>
35221828Sgrehan#include <machine/vmm.h>
36276349Sneel#include <machine/specialreg.h>
37276349Sneel
38221828Sgrehan#include <vmmapi.h>
39221828Sgrehan
40240912Sneel#include <stdio.h>
41240912Sneel#include <stdlib.h>
42276349Sneel#include <string.h>
43240912Sneel
44221828Sgrehan#include "xmsr.h"
45221828Sgrehan
46276349Sneelstatic int cpu_vendor_intel, cpu_vendor_amd;
47276349Sneel
48221828Sgrehanint
49276403Sneelemulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t num, uint64_t val)
50221828Sgrehan{
51221828Sgrehan
52276349Sneel	if (cpu_vendor_intel) {
53276403Sneel		switch (num) {
54276349Sneel		case 0xd04:		/* Sandy Bridge uncore PMCs */
55276349Sneel		case 0xc24:
56276349Sneel			return (0);
57276349Sneel		case MSR_BIOS_UPDT_TRIG:
58276349Sneel			return (0);
59276349Sneel		case MSR_BIOS_SIGN:
60276349Sneel			return (0);
61276349Sneel		default:
62276349Sneel			break;
63276349Sneel		}
64276403Sneel	} else if (cpu_vendor_amd) {
65276403Sneel		switch (num) {
66276403Sneel		case MSR_HWCR:
67276403Sneel			/*
68276403Sneel			 * Ignore writes to hardware configuration MSR.
69276403Sneel			 */
70276403Sneel			return (0);
71276403Sneel
72276403Sneel		case MSR_NB_CFG1:
73276403Sneel		case MSR_IC_CFG:
74276403Sneel			return (0);	/* Ignore writes */
75276403Sneel
76276403Sneel		case MSR_PERFEVSEL0:
77276403Sneel		case MSR_PERFEVSEL1:
78276403Sneel		case MSR_PERFEVSEL2:
79276403Sneel		case MSR_PERFEVSEL3:
80276403Sneel			/* Ignore writes to the PerfEvtSel MSRs */
81276403Sneel			return (0);
82276403Sneel
83276403Sneel		case MSR_K7_PERFCTR0:
84276403Sneel		case MSR_K7_PERFCTR1:
85276403Sneel		case MSR_K7_PERFCTR2:
86276403Sneel		case MSR_K7_PERFCTR3:
87276403Sneel			/* Ignore writes to the PerfCtr MSRs */
88276403Sneel			return (0);
89276403Sneel
90276403Sneel		case MSR_P_STATE_CONTROL:
91276403Sneel			/* Ignore write to change the P-state */
92276403Sneel			return (0);
93276403Sneel
94276403Sneel		default:
95276403Sneel			break;
96276403Sneel		}
97264273Sjhb	}
98264273Sjhb	return (-1);
99221828Sgrehan}
100264273Sjhb
101264273Sjhbint
102276349Sneelemulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t num, uint64_t *val)
103264273Sjhb{
104276349Sneel	int error = 0;
105264273Sjhb
106276349Sneel	if (cpu_vendor_intel) {
107276349Sneel		switch (num) {
108276349Sneel		case MSR_BIOS_SIGN:
109276349Sneel		case MSR_IA32_PLATFORM_ID:
110276349Sneel		case MSR_PKG_ENERGY_STATUS:
111276349Sneel		case MSR_PP0_ENERGY_STATUS:
112276349Sneel		case MSR_PP1_ENERGY_STATUS:
113276349Sneel		case MSR_DRAM_ENERGY_STATUS:
114276349Sneel			*val = 0;
115276349Sneel			break;
116276349Sneel		case MSR_RAPL_POWER_UNIT:
117276349Sneel			/*
118276349Sneel			 * Use the default value documented in section
119276349Sneel			 * "RAPL Interfaces" in Intel SDM vol3.
120276349Sneel			 */
121276349Sneel			*val = 0x000a1003;
122276349Sneel			break;
123276349Sneel		default:
124276349Sneel			error = -1;
125276349Sneel			break;
126276349Sneel		}
127276403Sneel	} else if (cpu_vendor_amd) {
128276403Sneel		switch (num) {
129276403Sneel		case MSR_BIOS_SIGN:
130276403Sneel			*val = 0;
131276403Sneel			break;
132276403Sneel		case MSR_HWCR:
133276403Sneel			/*
134276403Sneel			 * Bios and Kernel Developer's Guides for AMD Families
135276403Sneel			 * 12H, 14H, 15H and 16H.
136276403Sneel			 */
137276403Sneel			*val = 0x01000010;	/* Reset value */
138276403Sneel			*val |= 1 << 9;		/* MONITOR/MWAIT disable */
139276403Sneel			break;
140276403Sneel
141276403Sneel		case MSR_NB_CFG1:
142276403Sneel		case MSR_IC_CFG:
143276403Sneel			/*
144276403Sneel			 * The reset value is processor family dependent so
145276403Sneel			 * just return 0.
146276403Sneel			 */
147276403Sneel			*val = 0;
148276403Sneel			break;
149276403Sneel
150276403Sneel		case MSR_PERFEVSEL0:
151276403Sneel		case MSR_PERFEVSEL1:
152276403Sneel		case MSR_PERFEVSEL2:
153276403Sneel		case MSR_PERFEVSEL3:
154276403Sneel			/*
155276403Sneel			 * PerfEvtSel MSRs are not properly virtualized so just
156276403Sneel			 * return zero.
157276403Sneel			 */
158276403Sneel			*val = 0;
159276403Sneel			break;
160276403Sneel
161276403Sneel		case MSR_K7_PERFCTR0:
162276403Sneel		case MSR_K7_PERFCTR1:
163276403Sneel		case MSR_K7_PERFCTR2:
164276403Sneel		case MSR_K7_PERFCTR3:
165276403Sneel			/*
166276403Sneel			 * PerfCtr MSRs are not properly virtualized so just
167276403Sneel			 * return zero.
168276403Sneel			 */
169276403Sneel			*val = 0;
170276403Sneel			break;
171276403Sneel
172276403Sneel		case MSR_SMM_ADDR:
173276403Sneel		case MSR_SMM_MASK:
174276403Sneel			/*
175276403Sneel			 * Return the reset value defined in the AMD Bios and
176276403Sneel			 * Kernel Developer's Guide.
177276403Sneel			 */
178276403Sneel			*val = 0;
179276403Sneel			break;
180276403Sneel
181276403Sneel		case MSR_P_STATE_LIMIT:
182276403Sneel		case MSR_P_STATE_CONTROL:
183276403Sneel		case MSR_P_STATE_STATUS:
184276403Sneel		case MSR_P_STATE_CONFIG(0):	/* P0 configuration */
185276403Sneel			*val = 0;
186276403Sneel			break;
187276403Sneel
188284894Sneel		/*
189284894Sneel		 * OpenBSD guests test bit 0 of this MSR to detect if the
190284894Sneel		 * workaround for erratum 721 is already applied.
191284894Sneel		 * http://support.amd.com/TechDocs/41322_10h_Rev_Gd.pdf
192284894Sneel		 */
193284894Sneel		case 0xC0011029:
194284894Sneel			*val = 1;
195284894Sneel			break;
196284894Sneel
197276403Sneel		default:
198276403Sneel			error = -1;
199276403Sneel			break;
200276403Sneel		}
201276403Sneel	} else {
202276403Sneel		error = -1;
203276349Sneel	}
204276349Sneel	return (error);
205264273Sjhb}
206276349Sneel
207276349Sneelint
208276349Sneelinit_msr(void)
209276349Sneel{
210276349Sneel	int error;
211276349Sneel	u_int regs[4];
212276349Sneel	char cpu_vendor[13];
213276349Sneel
214276349Sneel	do_cpuid(0, regs);
215276349Sneel	((u_int *)&cpu_vendor)[0] = regs[1];
216276349Sneel	((u_int *)&cpu_vendor)[1] = regs[3];
217276349Sneel	((u_int *)&cpu_vendor)[2] = regs[2];
218276349Sneel	cpu_vendor[12] = '\0';
219276349Sneel
220276349Sneel	error = 0;
221276349Sneel	if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
222276349Sneel		cpu_vendor_amd = 1;
223276349Sneel	} else if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
224276349Sneel		cpu_vendor_intel = 1;
225276349Sneel	} else {
226276349Sneel		fprintf(stderr, "Unknown cpu vendor \"%s\"\n", cpu_vendor);
227276349Sneel		error = -1;
228276349Sneel	}
229276349Sneel	return (error);
230276349Sneel}
231