xref: /freebsd/sys/amd64/vmm/intel/vmx_msr.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
1366f6083SPeter Grehan /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3c49761ddSPedro F. Giffuni  *
4366f6083SPeter Grehan  * Copyright (c) 2011 NetApp, Inc.
5366f6083SPeter Grehan  * All rights reserved.
6366f6083SPeter Grehan  *
7366f6083SPeter Grehan  * Redistribution and use in source and binary forms, with or without
8366f6083SPeter Grehan  * modification, are permitted provided that the following conditions
9366f6083SPeter Grehan  * are met:
10366f6083SPeter Grehan  * 1. Redistributions of source code must retain the above copyright
11366f6083SPeter Grehan  *    notice, this list of conditions and the following disclaimer.
12366f6083SPeter Grehan  * 2. Redistributions in binary form must reproduce the above copyright
13366f6083SPeter Grehan  *    notice, this list of conditions and the following disclaimer in the
14366f6083SPeter Grehan  *    documentation and/or other materials provided with the distribution.
15366f6083SPeter Grehan  *
16366f6083SPeter Grehan  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
17366f6083SPeter Grehan  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18366f6083SPeter Grehan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19366f6083SPeter Grehan  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
20366f6083SPeter Grehan  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21366f6083SPeter Grehan  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22366f6083SPeter Grehan  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23366f6083SPeter Grehan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24366f6083SPeter Grehan  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25366f6083SPeter Grehan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26366f6083SPeter Grehan  * SUCH DAMAGE.
27366f6083SPeter Grehan  */
28366f6083SPeter Grehan 
29366f6083SPeter Grehan #include <sys/param.h>
30366f6083SPeter Grehan #include <sys/systm.h>
319fc84713SKonstantin Belousov #include <sys/proc.h>
32366f6083SPeter Grehan 
335295c3e6SNeel Natu #include <machine/clock.h>
34366f6083SPeter Grehan #include <machine/cpufunc.h>
355295c3e6SNeel Natu #include <machine/md_var.h>
369fc84713SKonstantin Belousov #include <machine/pcb.h>
3706fc6db9SJohn Baldwin #include <machine/specialreg.h>
38c3498942SNeel Natu #include <machine/vmm.h>
39366f6083SPeter Grehan 
40c3498942SNeel Natu #include "vmx.h"
41366f6083SPeter Grehan #include "vmx_msr.h"
42f5f5f1e7SPeter Grehan #include "x86.h"
43366f6083SPeter Grehan 
44490d56c5SEd Maste static bool
vmx_ctl_allows_one_setting(uint64_t msr_val,int bitpos)45366f6083SPeter Grehan vmx_ctl_allows_one_setting(uint64_t msr_val, int bitpos)
46366f6083SPeter Grehan {
47366f6083SPeter Grehan 
48490d56c5SEd Maste 	return ((msr_val & (1UL << (bitpos + 32))) != 0);
49366f6083SPeter Grehan }
50366f6083SPeter Grehan 
51490d56c5SEd Maste static bool
vmx_ctl_allows_zero_setting(uint64_t msr_val,int bitpos)52366f6083SPeter Grehan vmx_ctl_allows_zero_setting(uint64_t msr_val, int bitpos)
53366f6083SPeter Grehan {
54366f6083SPeter Grehan 
55490d56c5SEd Maste 	return ((msr_val & (1UL << bitpos)) == 0);
56366f6083SPeter Grehan }
57366f6083SPeter Grehan 
58366f6083SPeter Grehan uint32_t
vmx_revision(void)59366f6083SPeter Grehan vmx_revision(void)
60366f6083SPeter Grehan {
61366f6083SPeter Grehan 
62366f6083SPeter Grehan 	return (rdmsr(MSR_VMX_BASIC) & 0xffffffff);
63366f6083SPeter Grehan }
64366f6083SPeter Grehan 
65366f6083SPeter Grehan /*
66366f6083SPeter Grehan  * Generate a bitmask to be used for the VMCS execution control fields.
67366f6083SPeter Grehan  *
68366f6083SPeter Grehan  * The caller specifies what bits should be set to one in 'ones_mask'
69366f6083SPeter Grehan  * and what bits should be set to zero in 'zeros_mask'. The don't-care
70366f6083SPeter Grehan  * bits are set to the default value. The default values are obtained
71366f6083SPeter Grehan  * based on "Algorithm 3" in Section 27.5.1 "Algorithms for Determining
72366f6083SPeter Grehan  * VMX Capabilities".
73366f6083SPeter Grehan  *
74366f6083SPeter Grehan  * Returns zero on success and non-zero on error.
75366f6083SPeter Grehan  */
76366f6083SPeter Grehan int
vmx_set_ctlreg(int ctl_reg,int true_ctl_reg,uint32_t ones_mask,uint32_t zeros_mask,uint32_t * retval)77366f6083SPeter Grehan vmx_set_ctlreg(int ctl_reg, int true_ctl_reg, uint32_t ones_mask,
78366f6083SPeter Grehan 	       uint32_t zeros_mask, uint32_t *retval)
79366f6083SPeter Grehan {
80366f6083SPeter Grehan 	int i;
81366f6083SPeter Grehan 	uint64_t val, trueval;
82490d56c5SEd Maste 	bool true_ctls_avail, one_allowed, zero_allowed;
83366f6083SPeter Grehan 
84366f6083SPeter Grehan 	/* We cannot ask the same bit to be set to both '1' and '0' */
85366f6083SPeter Grehan 	if ((ones_mask ^ zeros_mask) != (ones_mask | zeros_mask))
86366f6083SPeter Grehan 		return (EINVAL);
87366f6083SPeter Grehan 
88490d56c5SEd Maste 	true_ctls_avail = (rdmsr(MSR_VMX_BASIC) & (1UL << 55)) != 0;
89366f6083SPeter Grehan 
90366f6083SPeter Grehan 	val = rdmsr(ctl_reg);
91366f6083SPeter Grehan 	if (true_ctls_avail)
92366f6083SPeter Grehan 		trueval = rdmsr(true_ctl_reg);		/* step c */
93366f6083SPeter Grehan 	else
94366f6083SPeter Grehan 		trueval = val;				/* step a */
95366f6083SPeter Grehan 
96366f6083SPeter Grehan 	for (i = 0; i < 32; i++) {
97366f6083SPeter Grehan 		one_allowed = vmx_ctl_allows_one_setting(trueval, i);
98366f6083SPeter Grehan 		zero_allowed = vmx_ctl_allows_zero_setting(trueval, i);
99366f6083SPeter Grehan 
100366f6083SPeter Grehan 		KASSERT(one_allowed || zero_allowed,
101366f6083SPeter Grehan 			("invalid zero/one setting for bit %d of ctl 0x%0x, "
102366f6083SPeter Grehan 			 "truectl 0x%0x\n", i, ctl_reg, true_ctl_reg));
103366f6083SPeter Grehan 
104366f6083SPeter Grehan 		if (zero_allowed && !one_allowed) {		/* b(i),c(i) */
105366f6083SPeter Grehan 			if (ones_mask & (1 << i))
106366f6083SPeter Grehan 				return (EINVAL);
107366f6083SPeter Grehan 			*retval &= ~(1 << i);
108366f6083SPeter Grehan 		} else if (one_allowed && !zero_allowed) {	/* b(i),c(i) */
109366f6083SPeter Grehan 			if (zeros_mask & (1 << i))
110366f6083SPeter Grehan 				return (EINVAL);
111366f6083SPeter Grehan 			*retval |= 1 << i;
112366f6083SPeter Grehan 		} else {
113366f6083SPeter Grehan 			if (zeros_mask & (1 << i))	/* b(ii),c(ii) */
114366f6083SPeter Grehan 				*retval &= ~(1 << i);
115366f6083SPeter Grehan 			else if (ones_mask & (1 << i)) /* b(ii), c(ii) */
116366f6083SPeter Grehan 				*retval |= 1 << i;
117366f6083SPeter Grehan 			else if (!true_ctls_avail)
118366f6083SPeter Grehan 				*retval &= ~(1 << i);	/* b(iii) */
119366f6083SPeter Grehan 			else if (vmx_ctl_allows_zero_setting(val, i))/* c(iii)*/
120366f6083SPeter Grehan 				*retval &= ~(1 << i);
121366f6083SPeter Grehan 			else if (vmx_ctl_allows_one_setting(val, i)) /* c(iv) */
122366f6083SPeter Grehan 				*retval |= 1 << i;
123366f6083SPeter Grehan 			else {
124366f6083SPeter Grehan 				panic("vmx_set_ctlreg: unable to determine "
125366f6083SPeter Grehan 				      "correct value of ctl bit %d for msr "
126366f6083SPeter Grehan 				      "0x%0x and true msr 0x%0x", i, ctl_reg,
127366f6083SPeter Grehan 				      true_ctl_reg);
128366f6083SPeter Grehan 			}
129366f6083SPeter Grehan 		}
130366f6083SPeter Grehan 	}
131366f6083SPeter Grehan 
132366f6083SPeter Grehan 	return (0);
133366f6083SPeter Grehan }
134366f6083SPeter Grehan 
135366f6083SPeter Grehan void
msr_bitmap_initialize(char * bitmap)136366f6083SPeter Grehan msr_bitmap_initialize(char *bitmap)
137366f6083SPeter Grehan {
138366f6083SPeter Grehan 
139366f6083SPeter Grehan 	memset(bitmap, 0xff, PAGE_SIZE);
140366f6083SPeter Grehan }
141366f6083SPeter Grehan 
142366f6083SPeter Grehan int
msr_bitmap_change_access(char * bitmap,u_int msr,int access)143366f6083SPeter Grehan msr_bitmap_change_access(char *bitmap, u_int msr, int access)
144366f6083SPeter Grehan {
145366f6083SPeter Grehan 	int byte, bit;
146366f6083SPeter Grehan 
147288aeb85SNeel Natu 	if (msr <= 0x00001FFF)
148366f6083SPeter Grehan 		byte = msr / 8;
149366f6083SPeter Grehan 	else if (msr >= 0xC0000000 && msr <= 0xC0001FFF)
150366f6083SPeter Grehan 		byte = 1024 + (msr - 0xC0000000) / 8;
151366f6083SPeter Grehan 	else
152366f6083SPeter Grehan 		return (EINVAL);
153366f6083SPeter Grehan 
154366f6083SPeter Grehan 	bit = msr & 0x7;
155366f6083SPeter Grehan 
156366f6083SPeter Grehan 	if (access & MSR_BITMAP_ACCESS_READ)
157366f6083SPeter Grehan 		bitmap[byte] &= ~(1 << bit);
158366f6083SPeter Grehan 	else
159366f6083SPeter Grehan 		bitmap[byte] |= 1 << bit;
160366f6083SPeter Grehan 
161366f6083SPeter Grehan 	byte += 2048;
162366f6083SPeter Grehan 	if (access & MSR_BITMAP_ACCESS_WRITE)
163366f6083SPeter Grehan 		bitmap[byte] &= ~(1 << bit);
164366f6083SPeter Grehan 	else
165366f6083SPeter Grehan 		bitmap[byte] |= 1 << bit;
166366f6083SPeter Grehan 
167366f6083SPeter Grehan 	return (0);
168366f6083SPeter Grehan }
169c3498942SNeel Natu 
170c3498942SNeel Natu static uint64_t misc_enable;
1715295c3e6SNeel Natu static uint64_t platform_info;
1725295c3e6SNeel Natu static uint64_t turbo_ratio_limit;
173c3498942SNeel Natu static uint64_t host_msrs[GUEST_MSR_NUM];
174c3498942SNeel Natu 
1755295c3e6SNeel Natu static bool
nehalem_cpu(void)1765295c3e6SNeel Natu nehalem_cpu(void)
1775295c3e6SNeel Natu {
1785295c3e6SNeel Natu 	u_int family, model;
1795295c3e6SNeel Natu 
1805295c3e6SNeel Natu 	/*
1815295c3e6SNeel Natu 	 * The family:model numbers belonging to the Nehalem microarchitecture
1825295c3e6SNeel Natu 	 * are documented in Section 35.5, Intel SDM dated Feb 2014.
1835295c3e6SNeel Natu 	 */
1845295c3e6SNeel Natu 	family = CPUID_TO_FAMILY(cpu_id);
1855295c3e6SNeel Natu 	model = CPUID_TO_MODEL(cpu_id);
1865295c3e6SNeel Natu 	if (family == 0x6) {
1875295c3e6SNeel Natu 		switch (model) {
1885295c3e6SNeel Natu 		case 0x1A:
1895295c3e6SNeel Natu 		case 0x1E:
1905295c3e6SNeel Natu 		case 0x1F:
1915295c3e6SNeel Natu 		case 0x2E:
1925295c3e6SNeel Natu 			return (true);
1935295c3e6SNeel Natu 		default:
1945295c3e6SNeel Natu 			break;
1955295c3e6SNeel Natu 		}
1965295c3e6SNeel Natu 	}
1975295c3e6SNeel Natu 	return (false);
1985295c3e6SNeel Natu }
1995295c3e6SNeel Natu 
2005295c3e6SNeel Natu static bool
westmere_cpu(void)2015295c3e6SNeel Natu westmere_cpu(void)
2025295c3e6SNeel Natu {
2035295c3e6SNeel Natu 	u_int family, model;
2045295c3e6SNeel Natu 
2055295c3e6SNeel Natu 	/*
2065295c3e6SNeel Natu 	 * The family:model numbers belonging to the Westmere microarchitecture
2075295c3e6SNeel Natu 	 * are documented in Section 35.6, Intel SDM dated Feb 2014.
2085295c3e6SNeel Natu 	 */
2095295c3e6SNeel Natu 	family = CPUID_TO_FAMILY(cpu_id);
2105295c3e6SNeel Natu 	model = CPUID_TO_MODEL(cpu_id);
2115295c3e6SNeel Natu 	if (family == 0x6) {
2125295c3e6SNeel Natu 		switch (model) {
2135295c3e6SNeel Natu 		case 0x25:
2145295c3e6SNeel Natu 		case 0x2C:
2155295c3e6SNeel Natu 			return (true);
2165295c3e6SNeel Natu 		default:
2175295c3e6SNeel Natu 			break;
2185295c3e6SNeel Natu 		}
2195295c3e6SNeel Natu 	}
2205295c3e6SNeel Natu 	return (false);
2215295c3e6SNeel Natu }
2225295c3e6SNeel Natu 
223a318f7ddSNeel Natu static bool
pat_valid(uint64_t val)224a318f7ddSNeel Natu pat_valid(uint64_t val)
225a318f7ddSNeel Natu {
226a318f7ddSNeel Natu 	int i, pa;
227a318f7ddSNeel Natu 
228a318f7ddSNeel Natu 	/*
229a318f7ddSNeel Natu 	 * From Intel SDM: Table "Memory Types That Can Be Encoded With PAT"
230a318f7ddSNeel Natu 	 *
231a318f7ddSNeel Natu 	 * Extract PA0 through PA7 and validate that each one encodes a
232a318f7ddSNeel Natu 	 * valid memory type.
233a318f7ddSNeel Natu 	 */
234a318f7ddSNeel Natu 	for (i = 0; i < 8; i++) {
235a318f7ddSNeel Natu 		pa = (val >> (i * 8)) & 0xff;
236a318f7ddSNeel Natu 		if (pa == 2 || pa == 3 || pa >= 8)
237a318f7ddSNeel Natu 			return (false);
238a318f7ddSNeel Natu 	}
239a318f7ddSNeel Natu 	return (true);
240a318f7ddSNeel Natu }
241a318f7ddSNeel Natu 
242c3498942SNeel Natu void
vmx_msr_init(void)243c3498942SNeel Natu vmx_msr_init(void)
244c3498942SNeel Natu {
2455295c3e6SNeel Natu 	uint64_t bus_freq, ratio;
2465295c3e6SNeel Natu 	int i;
2475295c3e6SNeel Natu 
248c3498942SNeel Natu 	/*
249c3498942SNeel Natu 	 * It is safe to cache the values of the following MSRs because
250c3498942SNeel Natu 	 * they don't change based on curcpu, curproc or curthread.
251c3498942SNeel Natu 	 */
252c3498942SNeel Natu 	host_msrs[IDX_MSR_LSTAR] = rdmsr(MSR_LSTAR);
253c3498942SNeel Natu 	host_msrs[IDX_MSR_CSTAR] = rdmsr(MSR_CSTAR);
254c3498942SNeel Natu 	host_msrs[IDX_MSR_STAR] = rdmsr(MSR_STAR);
255c3498942SNeel Natu 	host_msrs[IDX_MSR_SF_MASK] = rdmsr(MSR_SF_MASK);
256c3498942SNeel Natu 
257c3498942SNeel Natu 	/*
258c3498942SNeel Natu 	 * Initialize emulated MSRs
259c3498942SNeel Natu 	 */
260c3498942SNeel Natu 	misc_enable = rdmsr(MSR_IA32_MISC_ENABLE);
261c3498942SNeel Natu 	/*
262c3498942SNeel Natu 	 * Set mandatory bits
263c3498942SNeel Natu 	 *  11:   branch trace disabled
264c3498942SNeel Natu 	 *  12:   PEBS unavailable
265c3498942SNeel Natu 	 * Clear unsupported features
266c3498942SNeel Natu 	 *  16:   SpeedStep enable
267c3498942SNeel Natu 	 *  18:   enable MONITOR FSM
268c3498942SNeel Natu 	 */
269c3498942SNeel Natu 	misc_enable |= (1 << 12) | (1 << 11);
270c3498942SNeel Natu 	misc_enable &= ~((1 << 18) | (1 << 16));
2715295c3e6SNeel Natu 
2725295c3e6SNeel Natu 	if (nehalem_cpu() || westmere_cpu())
2735295c3e6SNeel Natu 		bus_freq = 133330000;		/* 133Mhz */
2745295c3e6SNeel Natu 	else
2755295c3e6SNeel Natu 		bus_freq = 100000000;		/* 100Mhz */
2765295c3e6SNeel Natu 
2775295c3e6SNeel Natu 	/*
2785295c3e6SNeel Natu 	 * XXXtime
2795295c3e6SNeel Natu 	 * The ratio should really be based on the virtual TSC frequency as
2805295c3e6SNeel Natu 	 * opposed to the host TSC.
2815295c3e6SNeel Natu 	 */
2825295c3e6SNeel Natu 	ratio = (tsc_freq / bus_freq) & 0xff;
2835295c3e6SNeel Natu 
2845295c3e6SNeel Natu 	/*
2855295c3e6SNeel Natu 	 * The register definition is based on the micro-architecture
2865295c3e6SNeel Natu 	 * but the following bits are always the same:
2875295c3e6SNeel Natu 	 * [15:8]  Maximum Non-Turbo Ratio
2885295c3e6SNeel Natu 	 * [28]    Programmable Ratio Limit for Turbo Mode
2895295c3e6SNeel Natu 	 * [29]    Programmable TDC-TDP Limit for Turbo Mode
2905295c3e6SNeel Natu 	 * [47:40] Maximum Efficiency Ratio
2915295c3e6SNeel Natu 	 *
2925295c3e6SNeel Natu 	 * The other bits can be safely set to 0 on all
2935295c3e6SNeel Natu 	 * micro-architectures up to Haswell.
2945295c3e6SNeel Natu 	 */
2955295c3e6SNeel Natu 	platform_info = (ratio << 8) | (ratio << 40);
2965295c3e6SNeel Natu 
2975295c3e6SNeel Natu 	/*
2985295c3e6SNeel Natu 	 * The number of valid bits in the MSR_TURBO_RATIO_LIMITx register is
2995295c3e6SNeel Natu 	 * dependent on the maximum cores per package supported by the micro-
3005295c3e6SNeel Natu 	 * architecture. For e.g., Westmere supports 6 cores per package and
3015295c3e6SNeel Natu 	 * uses the low 48 bits. Sandybridge support 8 cores per package and
3025295c3e6SNeel Natu 	 * uses up all 64 bits.
3035295c3e6SNeel Natu 	 *
3045295c3e6SNeel Natu 	 * However, the unused bits are reserved so we pretend that all bits
3055295c3e6SNeel Natu 	 * in this MSR are valid.
3065295c3e6SNeel Natu 	 */
3075295c3e6SNeel Natu 	for (i = 0; i < 8; i++)
3085295c3e6SNeel Natu 		turbo_ratio_limit = (turbo_ratio_limit << 8) | ratio;
309c3498942SNeel Natu }
310c3498942SNeel Natu 
311c3498942SNeel Natu void
vmx_msr_guest_init(struct vmx * vmx,struct vmx_vcpu * vcpu)3121aa51504SJohn Baldwin vmx_msr_guest_init(struct vmx *vmx, struct vmx_vcpu *vcpu)
313c3498942SNeel Natu {
314c3498942SNeel Natu 	/*
315c3498942SNeel Natu 	 * The permissions bitmap is shared between all vcpus so initialize it
316c3498942SNeel Natu 	 * once when initializing the vBSP.
317c3498942SNeel Natu 	 */
3181aa51504SJohn Baldwin 	if (vcpu->vcpuid == 0) {
319c3498942SNeel Natu 		guest_msr_rw(vmx, MSR_LSTAR);
320c3498942SNeel Natu 		guest_msr_rw(vmx, MSR_CSTAR);
321c3498942SNeel Natu 		guest_msr_rw(vmx, MSR_STAR);
322c3498942SNeel Natu 		guest_msr_rw(vmx, MSR_SF_MASK);
323c3498942SNeel Natu 		guest_msr_rw(vmx, MSR_KGSBASE);
324c3498942SNeel Natu 	}
325a318f7ddSNeel Natu 
326a318f7ddSNeel Natu 	/*
327a318f7ddSNeel Natu 	 * Initialize guest IA32_PAT MSR with default value after reset.
328a318f7ddSNeel Natu 	 */
3291aa51504SJohn Baldwin 	vcpu->guest_msrs[IDX_MSR_PAT] = PAT_VALUE(0, PAT_WRITE_BACK) |
330a318f7ddSNeel Natu 	    PAT_VALUE(1, PAT_WRITE_THROUGH)	|
331a318f7ddSNeel Natu 	    PAT_VALUE(2, PAT_UNCACHED)		|
332a318f7ddSNeel Natu 	    PAT_VALUE(3, PAT_UNCACHEABLE)	|
333a318f7ddSNeel Natu 	    PAT_VALUE(4, PAT_WRITE_BACK)	|
334a318f7ddSNeel Natu 	    PAT_VALUE(5, PAT_WRITE_THROUGH)	|
335a318f7ddSNeel Natu 	    PAT_VALUE(6, PAT_UNCACHED)		|
336a318f7ddSNeel Natu 	    PAT_VALUE(7, PAT_UNCACHEABLE);
337a318f7ddSNeel Natu 
338c3498942SNeel Natu 	return;
339c3498942SNeel Natu }
340c3498942SNeel Natu 
341c3498942SNeel Natu void
vmx_msr_guest_enter(struct vmx_vcpu * vcpu)34280cb5d84SJohn Baldwin vmx_msr_guest_enter(struct vmx_vcpu *vcpu)
343c3498942SNeel Natu {
344c3498942SNeel Natu 
3459fc84713SKonstantin Belousov 	/* Save host MSRs (in particular, KGSBASE) and restore guest MSRs */
3469fc84713SKonstantin Belousov 	update_pcb_bases(curpcb);
3471aa51504SJohn Baldwin 	wrmsr(MSR_LSTAR, vcpu->guest_msrs[IDX_MSR_LSTAR]);
3481aa51504SJohn Baldwin 	wrmsr(MSR_CSTAR, vcpu->guest_msrs[IDX_MSR_CSTAR]);
3491aa51504SJohn Baldwin 	wrmsr(MSR_STAR, vcpu->guest_msrs[IDX_MSR_STAR]);
3501aa51504SJohn Baldwin 	wrmsr(MSR_SF_MASK, vcpu->guest_msrs[IDX_MSR_SF_MASK]);
3511aa51504SJohn Baldwin 	wrmsr(MSR_KGSBASE, vcpu->guest_msrs[IDX_MSR_KGSBASE]);
352c3498942SNeel Natu }
353c3498942SNeel Natu 
354c3498942SNeel Natu void
vmx_msr_guest_enter_tsc_aux(struct vmx * vmx,struct vmx_vcpu * vcpu)3551aa51504SJohn Baldwin vmx_msr_guest_enter_tsc_aux(struct vmx *vmx, struct vmx_vcpu *vcpu)
356f5f5f1e7SPeter Grehan {
3571aa51504SJohn Baldwin 	uint64_t guest_tsc_aux = vcpu->guest_msrs[IDX_MSR_TSC_AUX];
3583a3f1e9dSPeter Grehan 	uint32_t host_aux = cpu_auxmsr();
359f5f5f1e7SPeter Grehan 
36073abae44SJohn Baldwin 	if (vmx_have_msr_tsc_aux && guest_tsc_aux != host_aux)
361f5f5f1e7SPeter Grehan 		wrmsr(MSR_TSC_AUX, guest_tsc_aux);
362f5f5f1e7SPeter Grehan }
363f5f5f1e7SPeter Grehan 
364f5f5f1e7SPeter Grehan void
vmx_msr_guest_exit(struct vmx_vcpu * vcpu)36580cb5d84SJohn Baldwin vmx_msr_guest_exit(struct vmx_vcpu *vcpu)
366c3498942SNeel Natu {
367c3498942SNeel Natu 
368c3498942SNeel Natu 	/* Save guest MSRs */
3691aa51504SJohn Baldwin 	vcpu->guest_msrs[IDX_MSR_LSTAR] = rdmsr(MSR_LSTAR);
3701aa51504SJohn Baldwin 	vcpu->guest_msrs[IDX_MSR_CSTAR] = rdmsr(MSR_CSTAR);
3711aa51504SJohn Baldwin 	vcpu->guest_msrs[IDX_MSR_STAR] = rdmsr(MSR_STAR);
3721aa51504SJohn Baldwin 	vcpu->guest_msrs[IDX_MSR_SF_MASK] = rdmsr(MSR_SF_MASK);
3731aa51504SJohn Baldwin 	vcpu->guest_msrs[IDX_MSR_KGSBASE] = rdmsr(MSR_KGSBASE);
374c3498942SNeel Natu 
375c3498942SNeel Natu 	/* Restore host MSRs */
376c3498942SNeel Natu 	wrmsr(MSR_LSTAR, host_msrs[IDX_MSR_LSTAR]);
377c3498942SNeel Natu 	wrmsr(MSR_CSTAR, host_msrs[IDX_MSR_CSTAR]);
378c3498942SNeel Natu 	wrmsr(MSR_STAR, host_msrs[IDX_MSR_STAR]);
379c3498942SNeel Natu 	wrmsr(MSR_SF_MASK, host_msrs[IDX_MSR_SF_MASK]);
380c3498942SNeel Natu 
381c3498942SNeel Natu 	/* MSR_KGSBASE will be restored on the way back to userspace */
382c3498942SNeel Natu }
383c3498942SNeel Natu 
384f5f5f1e7SPeter Grehan void
vmx_msr_guest_exit_tsc_aux(struct vmx * vmx,struct vmx_vcpu * vcpu)3851aa51504SJohn Baldwin vmx_msr_guest_exit_tsc_aux(struct vmx *vmx, struct vmx_vcpu *vcpu)
386f5f5f1e7SPeter Grehan {
3871aa51504SJohn Baldwin 	uint64_t guest_tsc_aux = vcpu->guest_msrs[IDX_MSR_TSC_AUX];
3883a3f1e9dSPeter Grehan 	uint32_t host_aux = cpu_auxmsr();
389f5f5f1e7SPeter Grehan 
39073abae44SJohn Baldwin 	if (vmx_have_msr_tsc_aux && guest_tsc_aux != host_aux)
391f5f5f1e7SPeter Grehan 		/*
392f5f5f1e7SPeter Grehan 		 * Note that it is not necessary to save the guest value
3931aa51504SJohn Baldwin 		 * here; vcpu->guest_msrs[IDX_MSR_TSC_AUX] always
394f5f5f1e7SPeter Grehan 		 * contains the current value since it is updated whenever
395f5f5f1e7SPeter Grehan 		 * the guest writes to it (which is expected to be very
396f5f5f1e7SPeter Grehan 		 * rare).
397f5f5f1e7SPeter Grehan 		 */
3983a3f1e9dSPeter Grehan 		wrmsr(MSR_TSC_AUX, host_aux);
399f5f5f1e7SPeter Grehan }
400f5f5f1e7SPeter Grehan 
401c3498942SNeel Natu int
vmx_rdmsr(struct vmx_vcpu * vcpu,u_int num,uint64_t * val,bool * retu)40280cb5d84SJohn Baldwin vmx_rdmsr(struct vmx_vcpu *vcpu, u_int num, uint64_t *val, bool *retu)
403c3498942SNeel Natu {
404a318f7ddSNeel Natu 	int error;
405a318f7ddSNeel Natu 
406a318f7ddSNeel Natu 	error = 0;
407c3498942SNeel Natu 
408c3498942SNeel Natu 	switch (num) {
4091d29bfc1SNeel Natu 	case MSR_MCG_CAP:
4101d29bfc1SNeel Natu 	case MSR_MCG_STATUS:
4111d29bfc1SNeel Natu 		*val = 0;
4121d29bfc1SNeel Natu 		break;
4137d786ee2SNeel Natu 	case MSR_MTRRcap:
4147d786ee2SNeel Natu 	case MSR_MTRRdefType:
4156171e026SCorvin Köhne 	case MSR_MTRR4kBase ... MSR_MTRR4kBase + 7:
4167d786ee2SNeel Natu 	case MSR_MTRR16kBase ... MSR_MTRR16kBase + 1:
4177d786ee2SNeel Natu 	case MSR_MTRR64kBase:
4186171e026SCorvin Köhne 	case MSR_MTRRVarBase ... MSR_MTRRVarBase + (VMM_MTRR_VAR_MAX * 2) - 1:
4191aa51504SJohn Baldwin 		if (vm_rdmtrr(&vcpu->mtrr, num, val) != 0) {
420d3956e46SJohn Baldwin 			vm_inject_gp(vcpu->vcpu);
4216171e026SCorvin Köhne 		}
4227d786ee2SNeel Natu 		break;
423c3498942SNeel Natu 	case MSR_IA32_MISC_ENABLE:
424c3498942SNeel Natu 		*val = misc_enable;
425c3498942SNeel Natu 		break;
4265295c3e6SNeel Natu 	case MSR_PLATFORM_INFO:
4275295c3e6SNeel Natu 		*val = platform_info;
4285295c3e6SNeel Natu 		break;
4295295c3e6SNeel Natu 	case MSR_TURBO_RATIO_LIMIT:
4305295c3e6SNeel Natu 	case MSR_TURBO_RATIO_LIMIT1:
4315295c3e6SNeel Natu 		*val = turbo_ratio_limit;
4325295c3e6SNeel Natu 		break;
433a318f7ddSNeel Natu 	case MSR_PAT:
4341aa51504SJohn Baldwin 		*val = vcpu->guest_msrs[IDX_MSR_PAT];
435a318f7ddSNeel Natu 		break;
436c3498942SNeel Natu 	default:
437c3498942SNeel Natu 		error = EINVAL;
438c3498942SNeel Natu 		break;
439c3498942SNeel Natu 	}
440c3498942SNeel Natu 	return (error);
441c3498942SNeel Natu }
442c3498942SNeel Natu 
443c3498942SNeel Natu int
vmx_wrmsr(struct vmx_vcpu * vcpu,u_int num,uint64_t val,bool * retu)44480cb5d84SJohn Baldwin vmx_wrmsr(struct vmx_vcpu *vcpu, u_int num, uint64_t val, bool *retu)
445c3498942SNeel Natu {
446d66bcddcSNeel Natu 	uint64_t changed;
447d66bcddcSNeel Natu 	int error;
448c3498942SNeel Natu 
449d66bcddcSNeel Natu 	error = 0;
450a318f7ddSNeel Natu 
451c3498942SNeel Natu 	switch (num) {
4521d29bfc1SNeel Natu 	case MSR_MCG_CAP:
4531d29bfc1SNeel Natu 	case MSR_MCG_STATUS:
4541d29bfc1SNeel Natu 		break;		/* ignore writes */
4557d786ee2SNeel Natu 	case MSR_MTRRcap:
4567d786ee2SNeel Natu 	case MSR_MTRRdefType:
4576171e026SCorvin Köhne 	case MSR_MTRR4kBase ... MSR_MTRR4kBase + 7:
4587d786ee2SNeel Natu 	case MSR_MTRR16kBase ... MSR_MTRR16kBase + 1:
4597d786ee2SNeel Natu 	case MSR_MTRR64kBase:
4606171e026SCorvin Köhne 	case MSR_MTRRVarBase ... MSR_MTRRVarBase + (VMM_MTRR_VAR_MAX * 2) - 1:
4611aa51504SJohn Baldwin 		if (vm_wrmtrr(&vcpu->mtrr, num, val) != 0) {
462d3956e46SJohn Baldwin 			vm_inject_gp(vcpu->vcpu);
4636171e026SCorvin Köhne 		}
4646171e026SCorvin Köhne 		break;
465d66bcddcSNeel Natu 	case MSR_IA32_MISC_ENABLE:
466d66bcddcSNeel Natu 		changed = val ^ misc_enable;
467d66bcddcSNeel Natu 		/*
468d66bcddcSNeel Natu 		 * If the host has disabled the NX feature then the guest
469d66bcddcSNeel Natu 		 * also cannot use it. However, a Linux guest will try to
470d66bcddcSNeel Natu 		 * enable the NX feature by writing to the MISC_ENABLE MSR.
471d66bcddcSNeel Natu 		 *
472d66bcddcSNeel Natu 		 * This can be safely ignored because the memory management
473d66bcddcSNeel Natu 		 * code looks at CPUID.80000001H:EDX.NX to check if the
474d66bcddcSNeel Natu 		 * functionality is actually enabled.
475d66bcddcSNeel Natu 		 */
476d66bcddcSNeel Natu 		changed &= ~(1UL << 34);
477d66bcddcSNeel Natu 
478d66bcddcSNeel Natu 		/*
479d66bcddcSNeel Natu 		 * Punt to userspace if any other bits are being modified.
480d66bcddcSNeel Natu 		 */
481d66bcddcSNeel Natu 		if (changed)
482d66bcddcSNeel Natu 			error = EINVAL;
483d66bcddcSNeel Natu 
484d66bcddcSNeel Natu 		break;
485a318f7ddSNeel Natu 	case MSR_PAT:
486a318f7ddSNeel Natu 		if (pat_valid(val))
4871aa51504SJohn Baldwin 			vcpu->guest_msrs[IDX_MSR_PAT] = val;
488a318f7ddSNeel Natu 		else
489d3956e46SJohn Baldwin 			vm_inject_gp(vcpu->vcpu);
490a318f7ddSNeel Natu 		break;
491277bdd99STycho Nightingale 	case MSR_TSC:
49280cb5d84SJohn Baldwin 		error = vmx_set_tsc_offset(vcpu, val - rdtsc());
493277bdd99STycho Nightingale 		break;
494f5f5f1e7SPeter Grehan 	case MSR_TSC_AUX:
49573abae44SJohn Baldwin 		if (vmx_have_msr_tsc_aux)
496f5f5f1e7SPeter Grehan 			/*
497f5f5f1e7SPeter Grehan 			 * vmx_msr_guest_enter_tsc_aux() will apply this
498f5f5f1e7SPeter Grehan 			 * value when it is called immediately before guest
499f5f5f1e7SPeter Grehan 			 * entry.
500f5f5f1e7SPeter Grehan 			 */
5011aa51504SJohn Baldwin 			vcpu->guest_msrs[IDX_MSR_TSC_AUX] = val;
502f5f5f1e7SPeter Grehan 		else
503d3956e46SJohn Baldwin 			vm_inject_gp(vcpu->vcpu);
504f5f5f1e7SPeter Grehan 		break;
505c3498942SNeel Natu 	default:
506c3498942SNeel Natu 		error = EINVAL;
507c3498942SNeel Natu 		break;
508c3498942SNeel Natu 	}
509c3498942SNeel Natu 
510c3498942SNeel Natu 	return (error);
511c3498942SNeel Natu }
512