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/11.0/usr.sbin/bhyve/xmsr.c 279227 2015-02-24 05:15:40Z neel $
27221828Sgrehan */
28221828Sgrehan
29221828Sgrehan#include <sys/cdefs.h>
30221828Sgrehan__FBSDID("$FreeBSD: releng/11.0/usr.sbin/bhyve/xmsr.c 279227 2015-02-24 05:15:40Z neel $");
31221828Sgrehan
32240912Sneel#include <sys/types.h>
33221828Sgrehan
34271888Sneel#include <machine/cpufunc.h>
35221828Sgrehan#include <machine/vmm.h>
36271888Sneel#include <machine/specialreg.h>
37271888Sneel
38221828Sgrehan#include <vmmapi.h>
39221828Sgrehan
40240912Sneel#include <stdio.h>
41240912Sneel#include <stdlib.h>
42271888Sneel#include <string.h>
43240912Sneel
44221828Sgrehan#include "xmsr.h"
45221828Sgrehan
46271888Sneelstatic int cpu_vendor_intel, cpu_vendor_amd;
47271888Sneel
48221828Sgrehanint
49273375Sneelemulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t num, uint64_t val)
50221828Sgrehan{
51221828Sgrehan
52271888Sneel	if (cpu_vendor_intel) {
53273375Sneel		switch (num) {
54271888Sneel		case 0xd04:		/* Sandy Bridge uncore PMCs */
55271888Sneel		case 0xc24:
56271888Sneel			return (0);
57271888Sneel		case MSR_BIOS_UPDT_TRIG:
58271888Sneel			return (0);
59271888Sneel		case MSR_BIOS_SIGN:
60271888Sneel			return (0);
61271888Sneel		default:
62271888Sneel			break;
63271888Sneel		}
64273375Sneel	} else if (cpu_vendor_amd) {
65273375Sneel		switch (num) {
66273375Sneel		case MSR_HWCR:
67273375Sneel			/*
68273375Sneel			 * Ignore writes to hardware configuration MSR.
69273375Sneel			 */
70273375Sneel			return (0);
71273375Sneel
72273375Sneel		case MSR_NB_CFG1:
73273375Sneel		case MSR_IC_CFG:
74273375Sneel			return (0);	/* Ignore writes */
75273375Sneel
76273375Sneel		case MSR_PERFEVSEL0:
77273375Sneel		case MSR_PERFEVSEL1:
78273375Sneel		case MSR_PERFEVSEL2:
79273375Sneel		case MSR_PERFEVSEL3:
80273375Sneel			/* Ignore writes to the PerfEvtSel MSRs */
81273375Sneel			return (0);
82273375Sneel
83273375Sneel		case MSR_K7_PERFCTR0:
84273375Sneel		case MSR_K7_PERFCTR1:
85273375Sneel		case MSR_K7_PERFCTR2:
86273375Sneel		case MSR_K7_PERFCTR3:
87273375Sneel			/* Ignore writes to the PerfCtr MSRs */
88273375Sneel			return (0);
89273375Sneel
90273375Sneel		case MSR_P_STATE_CONTROL:
91273375Sneel			/* Ignore write to change the P-state */
92273375Sneel			return (0);
93273375Sneel
94273375Sneel		default:
95273375Sneel			break;
96273375Sneel		}
97259635Sneel	}
98259635Sneel	return (-1);
99221828Sgrehan}
100259635Sneel
101259635Sneelint
102271888Sneelemulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t num, uint64_t *val)
103259635Sneel{
104271888Sneel	int error = 0;
105259635Sneel
106271888Sneel	if (cpu_vendor_intel) {
107271888Sneel		switch (num) {
108271888Sneel		case MSR_BIOS_SIGN:
109271888Sneel		case MSR_IA32_PLATFORM_ID:
110271888Sneel		case MSR_PKG_ENERGY_STATUS:
111271888Sneel		case MSR_PP0_ENERGY_STATUS:
112271888Sneel		case MSR_PP1_ENERGY_STATUS:
113271888Sneel		case MSR_DRAM_ENERGY_STATUS:
114271888Sneel			*val = 0;
115271888Sneel			break;
116272839Sneel		case MSR_RAPL_POWER_UNIT:
117272839Sneel			/*
118272839Sneel			 * Use the default value documented in section
119272839Sneel			 * "RAPL Interfaces" in Intel SDM vol3.
120272839Sneel			 */
121272839Sneel			*val = 0x000a1003;
122272839Sneel			break;
123271888Sneel		default:
124271888Sneel			error = -1;
125271888Sneel			break;
126271888Sneel		}
127273375Sneel	} else if (cpu_vendor_amd) {
128273375Sneel		switch (num) {
129273375Sneel		case MSR_BIOS_SIGN:
130273375Sneel			*val = 0;
131273375Sneel			break;
132273375Sneel		case MSR_HWCR:
133273375Sneel			/*
134273375Sneel			 * Bios and Kernel Developer's Guides for AMD Families
135273375Sneel			 * 12H, 14H, 15H and 16H.
136273375Sneel			 */
137273375Sneel			*val = 0x01000010;	/* Reset value */
138273375Sneel			*val |= 1 << 9;		/* MONITOR/MWAIT disable */
139273375Sneel			break;
140273375Sneel
141273375Sneel		case MSR_NB_CFG1:
142273375Sneel		case MSR_IC_CFG:
143273375Sneel			/*
144273375Sneel			 * The reset value is processor family dependent so
145273375Sneel			 * just return 0.
146273375Sneel			 */
147273375Sneel			*val = 0;
148273375Sneel			break;
149273375Sneel
150273375Sneel		case MSR_PERFEVSEL0:
151273375Sneel		case MSR_PERFEVSEL1:
152273375Sneel		case MSR_PERFEVSEL2:
153273375Sneel		case MSR_PERFEVSEL3:
154273375Sneel			/*
155273375Sneel			 * PerfEvtSel MSRs are not properly virtualized so just
156273375Sneel			 * return zero.
157273375Sneel			 */
158273375Sneel			*val = 0;
159273375Sneel			break;
160273375Sneel
161273375Sneel		case MSR_K7_PERFCTR0:
162273375Sneel		case MSR_K7_PERFCTR1:
163273375Sneel		case MSR_K7_PERFCTR2:
164273375Sneel		case MSR_K7_PERFCTR3:
165273375Sneel			/*
166273375Sneel			 * PerfCtr MSRs are not properly virtualized so just
167273375Sneel			 * return zero.
168273375Sneel			 */
169273375Sneel			*val = 0;
170273375Sneel			break;
171273375Sneel
172273375Sneel		case MSR_SMM_ADDR:
173273375Sneel		case MSR_SMM_MASK:
174273375Sneel			/*
175273375Sneel			 * Return the reset value defined in the AMD Bios and
176273375Sneel			 * Kernel Developer's Guide.
177273375Sneel			 */
178273375Sneel			*val = 0;
179273375Sneel			break;
180273375Sneel
181273375Sneel		case MSR_P_STATE_LIMIT:
182273375Sneel		case MSR_P_STATE_CONTROL:
183273375Sneel		case MSR_P_STATE_STATUS:
184273375Sneel		case MSR_P_STATE_CONFIG(0):	/* P0 configuration */
185273375Sneel			*val = 0;
186273375Sneel			break;
187273375Sneel
188279227Sneel		/*
189279227Sneel		 * OpenBSD guests test bit 0 of this MSR to detect if the
190279227Sneel		 * workaround for erratum 721 is already applied.
191279227Sneel		 * http://support.amd.com/TechDocs/41322_10h_Rev_Gd.pdf
192279227Sneel		 */
193279227Sneel		case 0xC0011029:
194279227Sneel			*val = 1;
195279227Sneel			break;
196279227Sneel
197273375Sneel		default:
198273375Sneel			error = -1;
199273375Sneel			break;
200273375Sneel		}
201273375Sneel	} else {
202273375Sneel		error = -1;
203271888Sneel	}
204271888Sneel	return (error);
205259635Sneel}
206271888Sneel
207271888Sneelint
208271888Sneelinit_msr(void)
209271888Sneel{
210271888Sneel	int error;
211271888Sneel	u_int regs[4];
212271888Sneel	char cpu_vendor[13];
213271888Sneel
214271888Sneel	do_cpuid(0, regs);
215271888Sneel	((u_int *)&cpu_vendor)[0] = regs[1];
216271888Sneel	((u_int *)&cpu_vendor)[1] = regs[3];
217271888Sneel	((u_int *)&cpu_vendor)[2] = regs[2];
218271888Sneel	cpu_vendor[12] = '\0';
219271888Sneel
220271888Sneel	error = 0;
221271888Sneel	if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
222271888Sneel		cpu_vendor_amd = 1;
223271888Sneel	} else if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
224271888Sneel		cpu_vendor_intel = 1;
225271888Sneel	} else {
226271888Sneel		fprintf(stderr, "Unknown cpu vendor \"%s\"\n", cpu_vendor);
227271888Sneel		error = -1;
228271888Sneel	}
229271888Sneel	return (error);
230271888Sneel}
231