1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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 #ifdef SAN_NEEDS_INTERCEPTORS 33 #define SAN_RUNTIME 34 #endif 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 39 #include <machine/md_var.h> 40 #include <machine/specialreg.h> 41 #include <x86/ifunc.h> 42 43 int fubyte_nosmap(volatile const void *base); 44 int fubyte_smap(volatile const void *base); 45 DEFINE_IFUNC(, int, fubyte, (volatile const void *)) 46 { 47 48 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 49 fubyte_smap : fubyte_nosmap); 50 } 51 52 int fuword16_nosmap(volatile const void *base); 53 int fuword16_smap(volatile const void *base); 54 DEFINE_IFUNC(, int, fuword16, (volatile const void *)) 55 { 56 57 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 58 fuword16_smap : fuword16_nosmap); 59 } 60 61 int fueword_nosmap(volatile const void *base, long *val); 62 int fueword_smap(volatile const void *base, long *val); 63 DEFINE_IFUNC(, int, fueword, (volatile const void *, long *)) 64 { 65 66 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 67 fueword_smap : fueword_nosmap); 68 } 69 DEFINE_IFUNC(, int, fueword64, (volatile const void *, int64_t *)) 70 { 71 72 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 73 fueword_smap : fueword_nosmap); 74 } 75 76 int fueword32_nosmap(volatile const void *base, int32_t *val); 77 int fueword32_smap(volatile const void *base, int32_t *val); 78 DEFINE_IFUNC(, int, fueword32, (volatile const void *, int32_t *)) 79 { 80 81 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 82 fueword32_smap : fueword32_nosmap); 83 } 84 85 int subyte_nosmap(volatile void *base, int byte); 86 int subyte_smap(volatile void *base, int byte); 87 DEFINE_IFUNC(, int, subyte, (volatile void *, int)) 88 { 89 90 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 91 subyte_smap : subyte_nosmap); 92 } 93 94 int suword16_nosmap(volatile void *base, int word); 95 int suword16_smap(volatile void *base, int word); 96 DEFINE_IFUNC(, int, suword16, (volatile void *, int)) 97 { 98 99 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 100 suword16_smap : suword16_nosmap); 101 } 102 103 int suword32_nosmap(volatile void *base, int32_t word); 104 int suword32_smap(volatile void *base, int32_t word); 105 DEFINE_IFUNC(, int, suword32, (volatile void *, int32_t)) 106 { 107 108 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 109 suword32_smap : suword32_nosmap); 110 } 111 112 int suword_nosmap(volatile void *base, long word); 113 int suword_smap(volatile void *base, long word); 114 DEFINE_IFUNC(, int, suword, (volatile void *, long)) 115 { 116 117 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 118 suword_smap : suword_nosmap); 119 } 120 DEFINE_IFUNC(, int, suword64, (volatile void *, int64_t)) 121 { 122 123 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 124 suword_smap : suword_nosmap); 125 } 126 127 int casueword32_nosmap(volatile uint32_t *base, uint32_t oldval, 128 uint32_t *oldvalp, uint32_t newval); 129 int casueword32_smap(volatile uint32_t *base, uint32_t oldval, 130 uint32_t *oldvalp, uint32_t newval); 131 DEFINE_IFUNC(, int, casueword32, (volatile uint32_t *, uint32_t, uint32_t *, 132 uint32_t)) 133 { 134 135 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 136 casueword32_smap : casueword32_nosmap); 137 } 138 139 int casueword_nosmap(volatile u_long *p, u_long oldval, u_long *oldvalp, 140 u_long newval); 141 int casueword_smap(volatile u_long *p, u_long oldval, u_long *oldvalp, 142 u_long newval); 143 DEFINE_IFUNC(, int, casueword, (volatile u_long *, u_long, u_long *, u_long)) 144 { 145 146 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 147 casueword_smap : casueword_nosmap); 148 } 149 150 int copyinstr_nosmap(const void *udaddr, void *kaddr, size_t len, 151 size_t *lencopied); 152 int copyinstr_smap(const void *udaddr, void *kaddr, size_t len, 153 size_t *lencopied); 154 DEFINE_IFUNC(, int, copyinstr, (const void *, void *, size_t, size_t *)) 155 { 156 157 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 158 copyinstr_smap : copyinstr_nosmap); 159 } 160 161 int copyin_nosmap_std(const void *udaddr, void *kaddr, size_t len); 162 int copyin_smap_std(const void *udaddr, void *kaddr, size_t len); 163 int copyin_nosmap_erms(const void *udaddr, void *kaddr, size_t len); 164 int copyin_smap_erms(const void *udaddr, void *kaddr, size_t len); 165 DEFINE_IFUNC(, int, copyin, (const void *, void *, size_t)) 166 { 167 168 switch (cpu_stdext_feature & (CPUID_STDEXT_SMAP | CPUID_STDEXT_ERMS)) { 169 case CPUID_STDEXT_SMAP: 170 return (copyin_smap_std); 171 case CPUID_STDEXT_ERMS: 172 return (copyin_nosmap_erms); 173 case CPUID_STDEXT_SMAP | CPUID_STDEXT_ERMS: 174 return (copyin_smap_erms); 175 default: 176 return (copyin_nosmap_std); 177 } 178 } 179 180 int copyout_nosmap_std(const void *kaddr, void *udaddr, size_t len); 181 int copyout_smap_std(const void *kaddr, void *udaddr, size_t len); 182 int copyout_nosmap_erms(const void *kaddr, void *udaddr, size_t len); 183 int copyout_smap_erms(const void *kaddr, void *udaddr, size_t len); 184 DEFINE_IFUNC(, int, copyout, (const void *, void *, size_t)) 185 { 186 187 switch (cpu_stdext_feature & (CPUID_STDEXT_SMAP | CPUID_STDEXT_ERMS)) { 188 case CPUID_STDEXT_SMAP: 189 return (copyout_smap_std); 190 case CPUID_STDEXT_ERMS: 191 return (copyout_nosmap_erms); 192 case CPUID_STDEXT_SMAP | CPUID_STDEXT_ERMS: 193 return (copyout_smap_erms); 194 default: 195 return (copyout_nosmap_std); 196 } 197 } 198