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