1366f6083SPeter Grehan /*- 2c49761ddSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 * $FreeBSD$ 29366f6083SPeter Grehan */ 30366f6083SPeter Grehan 31366f6083SPeter Grehan #include <sys/cdefs.h> 32366f6083SPeter Grehan __FBSDID("$FreeBSD$"); 33366f6083SPeter Grehan 34318224bbSNeel Natu #include <sys/param.h> 35318224bbSNeel Natu #include <sys/kernel.h> 36366f6083SPeter Grehan #include <sys/types.h> 37366f6083SPeter Grehan #include <sys/systm.h> 38366f6083SPeter Grehan #include <sys/smp.h> 39318224bbSNeel Natu #include <sys/sysctl.h> 40366f6083SPeter Grehan 41366f6083SPeter Grehan #include <vm/vm.h> 42366f6083SPeter Grehan #include <vm/pmap.h> 43318224bbSNeel Natu #include <vm/vm_extern.h> 44366f6083SPeter Grehan 45366f6083SPeter Grehan #include <machine/vmm.h> 46318224bbSNeel Natu 47366f6083SPeter Grehan #include "vmx_cpufunc.h" 48366f6083SPeter Grehan #include "ept.h" 49366f6083SPeter Grehan 50318224bbSNeel Natu #define EPT_SUPPORTS_EXEC_ONLY(cap) ((cap) & (1UL << 0)) 51366f6083SPeter Grehan #define EPT_PWL4(cap) ((cap) & (1UL << 6)) 52366f6083SPeter Grehan #define EPT_MEMORY_TYPE_WB(cap) ((cap) & (1UL << 14)) 53366f6083SPeter Grehan #define EPT_PDE_SUPERPAGE(cap) ((cap) & (1UL << 16)) /* 2MB pages */ 54366f6083SPeter Grehan #define EPT_PDPTE_SUPERPAGE(cap) ((cap) & (1UL << 17)) /* 1GB pages */ 55366f6083SPeter Grehan #define INVEPT_SUPPORTED(cap) ((cap) & (1UL << 20)) 56318224bbSNeel Natu #define AD_BITS_SUPPORTED(cap) ((cap) & (1UL << 21)) 57318224bbSNeel Natu #define INVVPID_SUPPORTED(cap) ((cap) & (1UL << 32)) 58366f6083SPeter Grehan 59366f6083SPeter Grehan #define INVVPID_ALL_TYPES_MASK 0xF0000000000UL 60366f6083SPeter Grehan #define INVVPID_ALL_TYPES_SUPPORTED(cap) \ 61366f6083SPeter Grehan (((cap) & INVVPID_ALL_TYPES_MASK) == INVVPID_ALL_TYPES_MASK) 62366f6083SPeter Grehan 63366f6083SPeter Grehan #define INVEPT_ALL_TYPES_MASK 0x6000000UL 64366f6083SPeter Grehan #define INVEPT_ALL_TYPES_SUPPORTED(cap) \ 65366f6083SPeter Grehan (((cap) & INVEPT_ALL_TYPES_MASK) == INVEPT_ALL_TYPES_MASK) 66366f6083SPeter Grehan 67318224bbSNeel Natu #define EPT_PWLEVELS 4 /* page walk levels */ 68318224bbSNeel Natu #define EPT_ENABLE_AD_BITS (1 << 6) 69366f6083SPeter Grehan 70318224bbSNeel Natu SYSCTL_DECL(_hw_vmm); 71*b40598c5SPawel Biernacki SYSCTL_NODE(_hw_vmm, OID_AUTO, ept, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, 72*b40598c5SPawel Biernacki NULL); 73366f6083SPeter Grehan 74318224bbSNeel Natu static int ept_enable_ad_bits; 75366f6083SPeter Grehan 76318224bbSNeel Natu static int ept_pmap_flags; 77318224bbSNeel Natu SYSCTL_INT(_hw_vmm_ept, OID_AUTO, pmap_flags, CTLFLAG_RD, 78318224bbSNeel Natu &ept_pmap_flags, 0, NULL); 79e60f5d77SPeter Grehan 80366f6083SPeter Grehan int 81add611fdSNeel Natu ept_init(int ipinum) 82366f6083SPeter Grehan { 83318224bbSNeel Natu int use_hw_ad_bits, use_superpages, use_exec_only; 84366f6083SPeter Grehan uint64_t cap; 85366f6083SPeter Grehan 86366f6083SPeter Grehan cap = rdmsr(MSR_VMX_EPT_VPID_CAP); 87366f6083SPeter Grehan 88366f6083SPeter Grehan /* 89366f6083SPeter Grehan * Verify that: 90366f6083SPeter Grehan * - page walk length is 4 steps 91366f6083SPeter Grehan * - extended page tables can be laid out in write-back memory 92366f6083SPeter Grehan * - invvpid instruction with all possible types is supported 93366f6083SPeter Grehan * - invept instruction with all possible types is supported 94366f6083SPeter Grehan */ 95366f6083SPeter Grehan if (!EPT_PWL4(cap) || 96366f6083SPeter Grehan !EPT_MEMORY_TYPE_WB(cap) || 97366f6083SPeter Grehan !INVVPID_SUPPORTED(cap) || 98366f6083SPeter Grehan !INVVPID_ALL_TYPES_SUPPORTED(cap) || 99366f6083SPeter Grehan !INVEPT_SUPPORTED(cap) || 100366f6083SPeter Grehan !INVEPT_ALL_TYPES_SUPPORTED(cap)) 101366f6083SPeter Grehan return (EINVAL); 102366f6083SPeter Grehan 103add611fdSNeel Natu ept_pmap_flags = ipinum & PMAP_NESTED_IPIMASK; 1045515bb73SNeel Natu 105318224bbSNeel Natu use_superpages = 1; 106318224bbSNeel Natu TUNABLE_INT_FETCH("hw.vmm.ept.use_superpages", &use_superpages); 107318224bbSNeel Natu if (use_superpages && EPT_PDE_SUPERPAGE(cap)) 108318224bbSNeel Natu ept_pmap_flags |= PMAP_PDE_SUPERPAGE; /* 2MB superpage */ 109366f6083SPeter Grehan 110318224bbSNeel Natu use_hw_ad_bits = 1; 111318224bbSNeel Natu TUNABLE_INT_FETCH("hw.vmm.ept.use_hw_ad_bits", &use_hw_ad_bits); 112318224bbSNeel Natu if (use_hw_ad_bits && AD_BITS_SUPPORTED(cap)) 113318224bbSNeel Natu ept_enable_ad_bits = 1; 114318224bbSNeel Natu else 115318224bbSNeel Natu ept_pmap_flags |= PMAP_EMULATE_AD_BITS; 116366f6083SPeter Grehan 117318224bbSNeel Natu use_exec_only = 1; 118318224bbSNeel Natu TUNABLE_INT_FETCH("hw.vmm.ept.use_exec_only", &use_exec_only); 119318224bbSNeel Natu if (use_exec_only && EPT_SUPPORTS_EXEC_ONLY(cap)) 120318224bbSNeel Natu ept_pmap_flags |= PMAP_SUPPORTS_EXEC_ONLY; 121366f6083SPeter Grehan 122366f6083SPeter Grehan return (0); 123366f6083SPeter Grehan } 124366f6083SPeter Grehan 125bda273f2SNeel Natu #if 0 126bda273f2SNeel Natu static void 127bda273f2SNeel Natu ept_dump(uint64_t *ptp, int nlevels) 128bda273f2SNeel Natu { 129bda273f2SNeel Natu int i, t, tabs; 130bda273f2SNeel Natu uint64_t *ptpnext, ptpval; 131bda273f2SNeel Natu 132bda273f2SNeel Natu if (--nlevels < 0) 133bda273f2SNeel Natu return; 134bda273f2SNeel Natu 135bda273f2SNeel Natu tabs = 3 - nlevels; 136bda273f2SNeel Natu for (t = 0; t < tabs; t++) 137bda273f2SNeel Natu printf("\t"); 138bda273f2SNeel Natu printf("PTP = %p\n", ptp); 139bda273f2SNeel Natu 140bda273f2SNeel Natu for (i = 0; i < 512; i++) { 141bda273f2SNeel Natu ptpval = ptp[i]; 142bda273f2SNeel Natu 143bda273f2SNeel Natu if (ptpval == 0) 144bda273f2SNeel Natu continue; 145bda273f2SNeel Natu 146bda273f2SNeel Natu for (t = 0; t < tabs; t++) 147bda273f2SNeel Natu printf("\t"); 148bda273f2SNeel Natu printf("%3d 0x%016lx\n", i, ptpval); 149bda273f2SNeel Natu 150bda273f2SNeel Natu if (nlevels != 0 && (ptpval & EPT_PG_SUPERPAGE) == 0) { 151bda273f2SNeel Natu ptpnext = (uint64_t *) 152bda273f2SNeel Natu PHYS_TO_DMAP(ptpval & EPT_ADDR_MASK); 153bda273f2SNeel Natu ept_dump(ptpnext, nlevels); 154bda273f2SNeel Natu } 155bda273f2SNeel Natu } 156bda273f2SNeel Natu } 157bda273f2SNeel Natu #endif 158bda273f2SNeel Natu 159366f6083SPeter Grehan static void 160366f6083SPeter Grehan invept_single_context(void *arg) 161366f6083SPeter Grehan { 162366f6083SPeter Grehan struct invept_desc desc = *(struct invept_desc *)arg; 163366f6083SPeter Grehan 164366f6083SPeter Grehan invept(INVEPT_TYPE_SINGLE_CONTEXT, desc); 165366f6083SPeter Grehan } 166366f6083SPeter Grehan 167366f6083SPeter Grehan void 168318224bbSNeel Natu ept_invalidate_mappings(u_long eptp) 169366f6083SPeter Grehan { 170366f6083SPeter Grehan struct invept_desc invept_desc = { 0 }; 171366f6083SPeter Grehan 172318224bbSNeel Natu invept_desc.eptp = eptp; 173366f6083SPeter Grehan 174366f6083SPeter Grehan smp_rendezvous(NULL, invept_single_context, NULL, &invept_desc); 175366f6083SPeter Grehan } 176318224bbSNeel Natu 177318224bbSNeel Natu static int 178318224bbSNeel Natu ept_pinit(pmap_t pmap) 179318224bbSNeel Natu { 180318224bbSNeel Natu 181318224bbSNeel Natu return (pmap_pinit_type(pmap, PT_EPT, ept_pmap_flags)); 182318224bbSNeel Natu } 183318224bbSNeel Natu 184318224bbSNeel Natu struct vmspace * 185318224bbSNeel Natu ept_vmspace_alloc(vm_offset_t min, vm_offset_t max) 186318224bbSNeel Natu { 187318224bbSNeel Natu 188318224bbSNeel Natu return (vmspace_alloc(min, max, ept_pinit)); 189318224bbSNeel Natu } 190318224bbSNeel Natu 191318224bbSNeel Natu void 192318224bbSNeel Natu ept_vmspace_free(struct vmspace *vmspace) 193318224bbSNeel Natu { 194318224bbSNeel Natu 195318224bbSNeel Natu vmspace_free(vmspace); 196318224bbSNeel Natu } 197318224bbSNeel Natu 198318224bbSNeel Natu uint64_t 199318224bbSNeel Natu eptp(uint64_t pml4) 200318224bbSNeel Natu { 201318224bbSNeel Natu uint64_t eptp_val; 202318224bbSNeel Natu 203318224bbSNeel Natu eptp_val = pml4 | (EPT_PWLEVELS - 1) << 3 | PAT_WRITE_BACK; 204318224bbSNeel Natu if (ept_enable_ad_bits) 205318224bbSNeel Natu eptp_val |= EPT_ENABLE_AD_BITS; 206318224bbSNeel Natu 207318224bbSNeel Natu return (eptp_val); 208318224bbSNeel Natu } 209