1b01c2033SNeel Natu /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3c49761ddSPedro F. Giffuni *
4b01c2033SNeel Natu * Copyright (c) 2012 NetApp, Inc.
5b01c2033SNeel Natu * All rights reserved.
6b01c2033SNeel Natu *
7b01c2033SNeel Natu * Redistribution and use in source and binary forms, with or without
8b01c2033SNeel Natu * modification, are permitted provided that the following conditions
9b01c2033SNeel Natu * are met:
10b01c2033SNeel Natu * 1. Redistributions of source code must retain the above copyright
11b01c2033SNeel Natu * notice, this list of conditions and the following disclaimer.
12b01c2033SNeel Natu * 2. Redistributions in binary form must reproduce the above copyright
13b01c2033SNeel Natu * notice, this list of conditions and the following disclaimer in the
14b01c2033SNeel Natu * documentation and/or other materials provided with the distribution.
15b01c2033SNeel Natu *
16b01c2033SNeel Natu * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
17b01c2033SNeel Natu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18b01c2033SNeel Natu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19b01c2033SNeel Natu * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
20b01c2033SNeel Natu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21b01c2033SNeel Natu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22b01c2033SNeel Natu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23b01c2033SNeel Natu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24b01c2033SNeel Natu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25b01c2033SNeel Natu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26b01c2033SNeel Natu * SUCH DAMAGE.
27b01c2033SNeel Natu */
28b01c2033SNeel Natu
29b01c2033SNeel Natu #include <sys/param.h>
30b01c2033SNeel Natu #include <sys/pcpu.h>
31b01c2033SNeel Natu
32b01c2033SNeel Natu #include <machine/cpufunc.h>
33b01c2033SNeel Natu #include <machine/segments.h>
34b01c2033SNeel Natu #include <machine/specialreg.h>
35b01c2033SNeel Natu
36b01c2033SNeel Natu #include "vmm_host.h"
37b01c2033SNeel Natu
38abb023fbSJohn Baldwin static uint64_t vmm_host_efer, vmm_host_pat, vmm_host_cr0, vmm_host_cr4,
39abb023fbSJohn Baldwin vmm_host_xcr0;
40abb023fbSJohn Baldwin static struct xsave_limits vmm_xsave_limits;
41b01c2033SNeel Natu
42b01c2033SNeel Natu void
vmm_host_state_init(void)43b01c2033SNeel Natu vmm_host_state_init(void)
44b01c2033SNeel Natu {
45abb023fbSJohn Baldwin int regs[4];
46b01c2033SNeel Natu
47b01c2033SNeel Natu vmm_host_efer = rdmsr(MSR_EFER);
48b01c2033SNeel Natu vmm_host_pat = rdmsr(MSR_PAT);
49b01c2033SNeel Natu
50b01c2033SNeel Natu /*
51b01c2033SNeel Natu * We always want CR0.TS to be set when the processor does a VM exit.
52b01c2033SNeel Natu *
53b01c2033SNeel Natu * With emulation turned on unconditionally after a VM exit, we are
54b01c2033SNeel Natu * able to trap inadvertent use of the FPU until the guest FPU state
55b01c2033SNeel Natu * has been safely squirreled away.
56b01c2033SNeel Natu */
57b01c2033SNeel Natu vmm_host_cr0 = rcr0() | CR0_TS;
58b01c2033SNeel Natu
59b7941dc9SKonstantin Belousov /*
60b7941dc9SKonstantin Belousov * On non-PCID or PCID but without INVPCID support machines,
61b7941dc9SKonstantin Belousov * we flush kernel i.e. global TLB entries, by temporary
62b7941dc9SKonstantin Belousov * clearing the CR4.PGE bit, see invltlb_glob(). If
63b7941dc9SKonstantin Belousov * preemption occurs at the wrong time, cached vmm_host_cr4
64b7941dc9SKonstantin Belousov * might store the value with CR4.PGE cleared. Since FreeBSD
65b7941dc9SKonstantin Belousov * requires support for PG_G on amd64, just set it
66b7941dc9SKonstantin Belousov * unconditionally.
67b7941dc9SKonstantin Belousov */
68b7941dc9SKonstantin Belousov vmm_host_cr4 = rcr4() | CR4_PGE;
69abb023fbSJohn Baldwin
70abb023fbSJohn Baldwin /*
71abb023fbSJohn Baldwin * Only permit a guest to use XSAVE if the host is using
72abb023fbSJohn Baldwin * XSAVE. Only permit a guest to use XSAVE features supported
73abb023fbSJohn Baldwin * by the host. This ensures that the FPU state used by the
74abb023fbSJohn Baldwin * guest is always a subset of the saved guest FPU state.
7544a68c4eSJohn Baldwin *
7644a68c4eSJohn Baldwin * In addition, only permit known XSAVE features where the
7744a68c4eSJohn Baldwin * rules for which features depend on other features is known
7844a68c4eSJohn Baldwin * to properly emulate xsetbv.
79abb023fbSJohn Baldwin */
80abb023fbSJohn Baldwin if (vmm_host_cr4 & CR4_XSAVE) {
81abb023fbSJohn Baldwin vmm_xsave_limits.xsave_enabled = 1;
82abb023fbSJohn Baldwin vmm_host_xcr0 = rxcr(0);
8344a68c4eSJohn Baldwin vmm_xsave_limits.xcr0_allowed = vmm_host_xcr0 &
8444a68c4eSJohn Baldwin (XFEATURE_AVX | XFEATURE_MPX | XFEATURE_AVX512);
85abb023fbSJohn Baldwin
86abb023fbSJohn Baldwin cpuid_count(0xd, 0x0, regs);
87abb023fbSJohn Baldwin vmm_xsave_limits.xsave_max_size = regs[1];
88abb023fbSJohn Baldwin }
89b01c2033SNeel Natu }
90b01c2033SNeel Natu
91b01c2033SNeel Natu uint64_t
vmm_get_host_pat(void)92b01c2033SNeel Natu vmm_get_host_pat(void)
93b01c2033SNeel Natu {
94b01c2033SNeel Natu
95b01c2033SNeel Natu return (vmm_host_pat);
96b01c2033SNeel Natu }
97b01c2033SNeel Natu
98b01c2033SNeel Natu uint64_t
vmm_get_host_efer(void)99b01c2033SNeel Natu vmm_get_host_efer(void)
100b01c2033SNeel Natu {
101b01c2033SNeel Natu
102b01c2033SNeel Natu return (vmm_host_efer);
103b01c2033SNeel Natu }
104b01c2033SNeel Natu
105b01c2033SNeel Natu uint64_t
vmm_get_host_cr0(void)106b01c2033SNeel Natu vmm_get_host_cr0(void)
107b01c2033SNeel Natu {
108b01c2033SNeel Natu
109b01c2033SNeel Natu return (vmm_host_cr0);
110b01c2033SNeel Natu }
111b01c2033SNeel Natu
112b01c2033SNeel Natu uint64_t
vmm_get_host_cr4(void)113b01c2033SNeel Natu vmm_get_host_cr4(void)
114b01c2033SNeel Natu {
115b01c2033SNeel Natu
116b01c2033SNeel Natu return (vmm_host_cr4);
117b01c2033SNeel Natu }
118b01c2033SNeel Natu
119b01c2033SNeel Natu uint64_t
vmm_get_host_xcr0(void)120abb023fbSJohn Baldwin vmm_get_host_xcr0(void)
121abb023fbSJohn Baldwin {
122abb023fbSJohn Baldwin
123abb023fbSJohn Baldwin return (vmm_host_xcr0);
124abb023fbSJohn Baldwin }
125abb023fbSJohn Baldwin
126abb023fbSJohn Baldwin uint64_t
vmm_get_host_datasel(void)127b01c2033SNeel Natu vmm_get_host_datasel(void)
128b01c2033SNeel Natu {
129b01c2033SNeel Natu
130b01c2033SNeel Natu return (GSEL(GDATA_SEL, SEL_KPL));
131b01c2033SNeel Natu
132b01c2033SNeel Natu }
133b01c2033SNeel Natu
134b01c2033SNeel Natu uint64_t
vmm_get_host_codesel(void)135b01c2033SNeel Natu vmm_get_host_codesel(void)
136b01c2033SNeel Natu {
137b01c2033SNeel Natu
138b01c2033SNeel Natu return (GSEL(GCODE_SEL, SEL_KPL));
139b01c2033SNeel Natu }
140b01c2033SNeel Natu
141b01c2033SNeel Natu uint64_t
vmm_get_host_tsssel(void)142b01c2033SNeel Natu vmm_get_host_tsssel(void)
143b01c2033SNeel Natu {
144b01c2033SNeel Natu
145b01c2033SNeel Natu return (GSEL(GPROC0_SEL, SEL_KPL));
146b01c2033SNeel Natu }
147b01c2033SNeel Natu
148b01c2033SNeel Natu uint64_t
vmm_get_host_fsbase(void)149b01c2033SNeel Natu vmm_get_host_fsbase(void)
150b01c2033SNeel Natu {
151b01c2033SNeel Natu
152b01c2033SNeel Natu return (0);
153b01c2033SNeel Natu }
154b01c2033SNeel Natu
155b01c2033SNeel Natu uint64_t
vmm_get_host_idtrbase(void)156b01c2033SNeel Natu vmm_get_host_idtrbase(void)
157b01c2033SNeel Natu {
158b01c2033SNeel Natu
159b01c2033SNeel Natu return (r_idt.rd_base);
160b01c2033SNeel Natu }
161abb023fbSJohn Baldwin
162abb023fbSJohn Baldwin const struct xsave_limits *
vmm_get_xsave_limits(void)163abb023fbSJohn Baldwin vmm_get_xsave_limits(void)
164abb023fbSJohn Baldwin {
165abb023fbSJohn Baldwin
166abb023fbSJohn Baldwin return (&vmm_xsave_limits);
167abb023fbSJohn Baldwin }
168