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