1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2018 The FreeBSD Foundation 5 * 6 * This software was developed by Konstantin Belousov <kib@FreeBSD.org> 7 * under sponsorship from the FreeBSD Foundation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #ifdef SAN_NEEDS_INTERCEPTORS 35 #define SAN_RUNTIME 36 #endif 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 41 #include <machine/md_var.h> 42 #include <machine/specialreg.h> 43 #include <x86/ifunc.h> 44 45 int fubyte_nosmap(volatile const void *base); 46 int fubyte_smap(volatile const void *base); 47 DEFINE_IFUNC(, int, fubyte, (volatile const void *)) 48 { 49 50 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 51 fubyte_smap : fubyte_nosmap); 52 } 53 54 int fuword16_nosmap(volatile const void *base); 55 int fuword16_smap(volatile const void *base); 56 DEFINE_IFUNC(, int, fuword16, (volatile const void *)) 57 { 58 59 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 60 fuword16_smap : fuword16_nosmap); 61 } 62 63 int fueword_nosmap(volatile const void *base, long *val); 64 int fueword_smap(volatile const void *base, long *val); 65 DEFINE_IFUNC(, int, fueword, (volatile const void *, long *)) 66 { 67 68 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 69 fueword_smap : fueword_nosmap); 70 } 71 DEFINE_IFUNC(, int, fueword64, (volatile const void *, int64_t *)) 72 { 73 74 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 75 fueword_smap : fueword_nosmap); 76 } 77 78 int fueword32_nosmap(volatile const void *base, int32_t *val); 79 int fueword32_smap(volatile const void *base, int32_t *val); 80 DEFINE_IFUNC(, int, fueword32, (volatile const void *, int32_t *)) 81 { 82 83 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 84 fueword32_smap : fueword32_nosmap); 85 } 86 87 int subyte_nosmap(volatile void *base, int byte); 88 int subyte_smap(volatile void *base, int byte); 89 DEFINE_IFUNC(, int, subyte, (volatile void *, int)) 90 { 91 92 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 93 subyte_smap : subyte_nosmap); 94 } 95 96 int suword16_nosmap(volatile void *base, int word); 97 int suword16_smap(volatile void *base, int word); 98 DEFINE_IFUNC(, int, suword16, (volatile void *, int)) 99 { 100 101 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 102 suword16_smap : suword16_nosmap); 103 } 104 105 int suword32_nosmap(volatile void *base, int32_t word); 106 int suword32_smap(volatile void *base, int32_t word); 107 DEFINE_IFUNC(, int, suword32, (volatile void *, int32_t)) 108 { 109 110 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 111 suword32_smap : suword32_nosmap); 112 } 113 114 int suword_nosmap(volatile void *base, long word); 115 int suword_smap(volatile void *base, long word); 116 DEFINE_IFUNC(, int, suword, (volatile void *, long)) 117 { 118 119 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 120 suword_smap : suword_nosmap); 121 } 122 DEFINE_IFUNC(, int, suword64, (volatile void *, int64_t)) 123 { 124 125 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 126 suword_smap : suword_nosmap); 127 } 128 129 int casueword32_nosmap(volatile uint32_t *base, uint32_t oldval, 130 uint32_t *oldvalp, uint32_t newval); 131 int casueword32_smap(volatile uint32_t *base, uint32_t oldval, 132 uint32_t *oldvalp, uint32_t newval); 133 DEFINE_IFUNC(, int, casueword32, (volatile uint32_t *, uint32_t, uint32_t *, 134 uint32_t)) 135 { 136 137 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 138 casueword32_smap : casueword32_nosmap); 139 } 140 141 int casueword_nosmap(volatile u_long *p, u_long oldval, u_long *oldvalp, 142 u_long newval); 143 int casueword_smap(volatile u_long *p, u_long oldval, u_long *oldvalp, 144 u_long newval); 145 DEFINE_IFUNC(, int, casueword, (volatile u_long *, u_long, u_long *, u_long)) 146 { 147 148 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 149 casueword_smap : casueword_nosmap); 150 } 151 152 int copyinstr_nosmap(const void *udaddr, void *kaddr, size_t len, 153 size_t *lencopied); 154 int copyinstr_smap(const void *udaddr, void *kaddr, size_t len, 155 size_t *lencopied); 156 DEFINE_IFUNC(, int, copyinstr, (const void *, void *, size_t, size_t *)) 157 { 158 159 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 160 copyinstr_smap : copyinstr_nosmap); 161 } 162 163 int copyin_nosmap_std(const void *udaddr, void *kaddr, size_t len); 164 int copyin_smap_std(const void *udaddr, void *kaddr, size_t len); 165 int copyin_nosmap_erms(const void *udaddr, void *kaddr, size_t len); 166 int copyin_smap_erms(const void *udaddr, void *kaddr, size_t len); 167 DEFINE_IFUNC(, int, copyin, (const void *, void *, size_t)) 168 { 169 170 switch (cpu_stdext_feature & (CPUID_STDEXT_SMAP | CPUID_STDEXT_ERMS)) { 171 case CPUID_STDEXT_SMAP: 172 return (copyin_smap_std); 173 case CPUID_STDEXT_ERMS: 174 return (copyin_nosmap_erms); 175 case CPUID_STDEXT_SMAP | CPUID_STDEXT_ERMS: 176 return (copyin_smap_erms); 177 default: 178 return (copyin_nosmap_std); 179 } 180 } 181 182 int copyout_nosmap_std(const void *kaddr, void *udaddr, size_t len); 183 int copyout_smap_std(const void *kaddr, void *udaddr, size_t len); 184 int copyout_nosmap_erms(const void *kaddr, void *udaddr, size_t len); 185 int copyout_smap_erms(const void *kaddr, void *udaddr, size_t len); 186 DEFINE_IFUNC(, int, copyout, (const void *, void *, size_t)) 187 { 188 189 switch (cpu_stdext_feature & (CPUID_STDEXT_SMAP | CPUID_STDEXT_ERMS)) { 190 case CPUID_STDEXT_SMAP: 191 return (copyout_smap_std); 192 case CPUID_STDEXT_ERMS: 193 return (copyout_nosmap_erms); 194 case CPUID_STDEXT_SMAP | CPUID_STDEXT_ERMS: 195 return (copyout_smap_erms); 196 default: 197 return (copyout_nosmap_std); 198 } 199 } 200