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 *)) 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 *)) 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 *)) 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 *)) 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 *)) 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)) 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)) 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)) 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)) 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)) 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)) 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 { 144 145 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 146 casueword_smap : casueword_nosmap); 147 } 148 149 #undef copyinstr 150 #undef copyin 151 #undef copyout 152 153 int copyinstr_nosmap(const void *udaddr, void *kaddr, size_t len, 154 size_t *lencopied); 155 int copyinstr_smap(const void *udaddr, void *kaddr, size_t len, 156 size_t *lencopied); 157 DEFINE_IFUNC(, int, copyinstr, (const void *, void *, size_t, size_t *)) 158 { 159 160 return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ? 161 copyinstr_smap : copyinstr_nosmap); 162 } 163 164 int copyin_nosmap_std(const void *udaddr, void *kaddr, size_t len); 165 int copyin_smap_std(const void *udaddr, void *kaddr, size_t len); 166 int copyin_nosmap_erms(const void *udaddr, void *kaddr, size_t len); 167 int copyin_smap_erms(const void *udaddr, void *kaddr, size_t len); 168 DEFINE_IFUNC(, int, copyin, (const void *, void *, size_t)) 169 { 170 171 switch (cpu_stdext_feature & (CPUID_STDEXT_SMAP | CPUID_STDEXT_ERMS)) { 172 case CPUID_STDEXT_SMAP: 173 return (copyin_smap_std); 174 case CPUID_STDEXT_ERMS: 175 return (copyin_nosmap_erms); 176 case CPUID_STDEXT_SMAP | CPUID_STDEXT_ERMS: 177 return (copyin_smap_erms); 178 default: 179 return (copyin_nosmap_std); 180 181 } 182 } 183 184 int copyout_nosmap_std(const void *kaddr, void *udaddr, size_t len); 185 int copyout_smap_std(const void *kaddr, void *udaddr, size_t len); 186 int copyout_nosmap_erms(const void *kaddr, void *udaddr, size_t len); 187 int copyout_smap_erms(const void *kaddr, void *udaddr, size_t len); 188 DEFINE_IFUNC(, int, copyout, (const void *, void *, size_t)) 189 { 190 191 switch (cpu_stdext_feature & (CPUID_STDEXT_SMAP | CPUID_STDEXT_ERMS)) { 192 case CPUID_STDEXT_SMAP: 193 return (copyout_smap_std); 194 case CPUID_STDEXT_ERMS: 195 return (copyout_nosmap_erms); 196 case CPUID_STDEXT_SMAP | CPUID_STDEXT_ERMS: 197 return (copyout_smap_erms); 198 default: 199 return (copyout_nosmap_std); 200 } 201 } 202