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