1 1.14 riastrad /* $NetBSD: subr_csan.c,v 1.14 2022/07/30 14:13:27 riastradh Exp $ */ 2 1.1 maxv 3 1.1 maxv /* 4 1.10 maxv * Copyright (c) 2019-2020 Maxime Villard, m00nbsd.net 5 1.1 maxv * All rights reserved. 6 1.1 maxv * 7 1.10 maxv * This code is part of the KCSAN subsystem of the NetBSD kernel. 8 1.1 maxv * 9 1.1 maxv * Redistribution and use in source and binary forms, with or without 10 1.1 maxv * modification, are permitted provided that the following conditions 11 1.1 maxv * are met: 12 1.1 maxv * 1. Redistributions of source code must retain the above copyright 13 1.1 maxv * notice, this list of conditions and the following disclaimer. 14 1.1 maxv * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 maxv * notice, this list of conditions and the following disclaimer in the 16 1.1 maxv * documentation and/or other materials provided with the distribution. 17 1.1 maxv * 18 1.10 maxv * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 1.10 maxv * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 1.10 maxv * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 1.10 maxv * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 1.10 maxv * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 1.10 maxv * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 1.10 maxv * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 1.10 maxv * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 1.10 maxv * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 1.10 maxv * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 1.10 maxv * SUCH DAMAGE. 29 1.1 maxv */ 30 1.1 maxv 31 1.1 maxv #include <sys/cdefs.h> 32 1.14 riastrad __KERNEL_RCSID(0, "$NetBSD: subr_csan.c,v 1.14 2022/07/30 14:13:27 riastradh Exp $"); 33 1.1 maxv 34 1.1 maxv #include <sys/param.h> 35 1.1 maxv #include <sys/device.h> 36 1.1 maxv #include <sys/kernel.h> 37 1.1 maxv #include <sys/param.h> 38 1.1 maxv #include <sys/conf.h> 39 1.1 maxv #include <sys/systm.h> 40 1.1 maxv #include <sys/types.h> 41 1.1 maxv #include <sys/csan.h> 42 1.1 maxv #include <sys/cpu.h> 43 1.13 riastrad #include <sys/pserialize.h> 44 1.1 maxv 45 1.1 maxv #ifdef KCSAN_PANIC 46 1.1 maxv #define REPORT panic 47 1.1 maxv #else 48 1.1 maxv #define REPORT printf 49 1.1 maxv #endif 50 1.1 maxv 51 1.1 maxv typedef struct { 52 1.1 maxv uintptr_t addr; 53 1.1 maxv uint32_t size; 54 1.1 maxv bool write:1; 55 1.1 maxv bool atomic:1; 56 1.1 maxv uintptr_t pc; 57 1.1 maxv } csan_cell_t; 58 1.1 maxv 59 1.1 maxv typedef struct { 60 1.1 maxv bool inited; 61 1.1 maxv uint32_t cnt; 62 1.1 maxv csan_cell_t cell; 63 1.1 maxv } csan_cpu_t; 64 1.1 maxv 65 1.1 maxv static csan_cpu_t kcsan_cpus[MAXCPUS]; 66 1.1 maxv static bool kcsan_enabled __read_mostly; 67 1.1 maxv 68 1.1 maxv #define __RET_ADDR (uintptr_t)__builtin_return_address(0) 69 1.1 maxv 70 1.2 maxv #define KCSAN_NACCESSES 1024 71 1.2 maxv #define KCSAN_DELAY 10 /* 10 microseconds */ 72 1.1 maxv 73 1.1 maxv /* -------------------------------------------------------------------------- */ 74 1.1 maxv 75 1.1 maxv /* The MD code. */ 76 1.1 maxv #include <machine/csan.h> 77 1.1 maxv 78 1.1 maxv /* -------------------------------------------------------------------------- */ 79 1.1 maxv 80 1.1 maxv void 81 1.1 maxv kcsan_init(void) 82 1.1 maxv { 83 1.1 maxv kcsan_enabled = true; 84 1.1 maxv } 85 1.1 maxv 86 1.1 maxv void 87 1.1 maxv kcsan_cpu_init(struct cpu_info *ci) 88 1.1 maxv { 89 1.1 maxv kcsan_cpus[cpu_index(ci)].inited = true; 90 1.1 maxv } 91 1.1 maxv 92 1.1 maxv /* -------------------------------------------------------------------------- */ 93 1.1 maxv 94 1.1 maxv static inline void 95 1.1 maxv kcsan_report(csan_cell_t *new, cpuid_t newcpu, csan_cell_t *old, cpuid_t oldcpu) 96 1.1 maxv { 97 1.1 maxv const char *newsym, *oldsym; 98 1.13 riastrad int s; 99 1.1 maxv 100 1.13 riastrad s = pserialize_read_enter(); 101 1.1 maxv if (ksyms_getname(NULL, &newsym, (vaddr_t)new->pc, KSYMS_PROC) != 0) { 102 1.1 maxv newsym = "Unknown"; 103 1.1 maxv } 104 1.1 maxv if (ksyms_getname(NULL, &oldsym, (vaddr_t)old->pc, KSYMS_PROC) != 0) { 105 1.1 maxv oldsym = "Unknown"; 106 1.1 maxv } 107 1.1 maxv REPORT("CSan: Racy Access " 108 1.1 maxv "[Cpu%lu %s%s Addr=%p Size=%u PC=%p<%s>] " 109 1.1 maxv "[Cpu%lu %s%s Addr=%p Size=%u PC=%p<%s>]\n", 110 1.1 maxv newcpu, 111 1.1 maxv (new->atomic ? "Atomic " : ""), (new->write ? "Write" : "Read"), 112 1.1 maxv (void *)new->addr, new->size, (void *)new->pc, newsym, 113 1.1 maxv oldcpu, 114 1.1 maxv (old->atomic ? "Atomic " : ""), (old->write ? "Write" : "Read"), 115 1.1 maxv (void *)old->addr, old->size, (void *)old->pc, oldsym); 116 1.13 riastrad pserialize_read_exit(s); 117 1.1 maxv kcsan_md_unwind(); 118 1.1 maxv } 119 1.1 maxv 120 1.1 maxv static inline bool 121 1.1 maxv kcsan_access_is_atomic(csan_cell_t *new, csan_cell_t *old) 122 1.1 maxv { 123 1.1 maxv if (new->write && !new->atomic) 124 1.1 maxv return false; 125 1.1 maxv if (old->write && !old->atomic) 126 1.1 maxv return false; 127 1.1 maxv return true; 128 1.1 maxv } 129 1.1 maxv 130 1.1 maxv static inline void 131 1.1 maxv kcsan_access(uintptr_t addr, size_t size, bool write, bool atomic, uintptr_t pc) 132 1.1 maxv { 133 1.1 maxv csan_cell_t old, new; 134 1.1 maxv csan_cpu_t *cpu; 135 1.1 maxv uint64_t intr; 136 1.1 maxv size_t i; 137 1.1 maxv 138 1.1 maxv if (__predict_false(!kcsan_enabled)) 139 1.1 maxv return; 140 1.3 maxv if (__predict_false(kcsan_md_unsupported((vaddr_t)addr))) 141 1.3 maxv return; 142 1.1 maxv 143 1.1 maxv new.addr = addr; 144 1.1 maxv new.size = size; 145 1.1 maxv new.write = write; 146 1.1 maxv new.atomic = atomic; 147 1.1 maxv new.pc = pc; 148 1.1 maxv 149 1.1 maxv for (i = 0; i < ncpu; i++) { 150 1.1 maxv __builtin_memcpy(&old, &kcsan_cpus[i].cell, sizeof(old)); 151 1.1 maxv 152 1.1 maxv if (old.addr + old.size <= new.addr) 153 1.1 maxv continue; 154 1.1 maxv if (new.addr + new.size <= old.addr) 155 1.1 maxv continue; 156 1.1 maxv if (__predict_true(!old.write && !new.write)) 157 1.1 maxv continue; 158 1.1 maxv if (__predict_true(kcsan_access_is_atomic(&new, &old))) 159 1.1 maxv continue; 160 1.1 maxv 161 1.1 maxv kcsan_report(&new, cpu_number(), &old, i); 162 1.1 maxv break; 163 1.1 maxv } 164 1.1 maxv 165 1.1 maxv if (__predict_false(!kcsan_md_is_avail())) 166 1.1 maxv return; 167 1.1 maxv 168 1.1 maxv kcsan_md_disable_intrs(&intr); 169 1.1 maxv 170 1.1 maxv cpu = &kcsan_cpus[cpu_number()]; 171 1.1 maxv if (__predict_false(!cpu->inited)) 172 1.1 maxv goto out; 173 1.1 maxv cpu->cnt = (cpu->cnt + 1) % KCSAN_NACCESSES; 174 1.1 maxv if (__predict_true(cpu->cnt != 0)) 175 1.1 maxv goto out; 176 1.1 maxv 177 1.1 maxv __builtin_memcpy(&cpu->cell, &new, sizeof(new)); 178 1.1 maxv kcsan_md_delay(KCSAN_DELAY); 179 1.1 maxv __builtin_memset(&cpu->cell, 0, sizeof(new)); 180 1.1 maxv 181 1.1 maxv out: 182 1.1 maxv kcsan_md_enable_intrs(&intr); 183 1.1 maxv } 184 1.1 maxv 185 1.1 maxv #define CSAN_READ(size) \ 186 1.1 maxv void __tsan_read##size(uintptr_t); \ 187 1.1 maxv void __tsan_read##size(uintptr_t addr) \ 188 1.1 maxv { \ 189 1.1 maxv kcsan_access(addr, size, false, false, __RET_ADDR); \ 190 1.1 maxv } 191 1.1 maxv 192 1.1 maxv CSAN_READ(1) 193 1.1 maxv CSAN_READ(2) 194 1.1 maxv CSAN_READ(4) 195 1.1 maxv CSAN_READ(8) 196 1.1 maxv CSAN_READ(16) 197 1.1 maxv 198 1.1 maxv #define CSAN_WRITE(size) \ 199 1.1 maxv void __tsan_write##size(uintptr_t); \ 200 1.1 maxv void __tsan_write##size(uintptr_t addr) \ 201 1.1 maxv { \ 202 1.1 maxv kcsan_access(addr, size, true, false, __RET_ADDR); \ 203 1.1 maxv } 204 1.1 maxv 205 1.1 maxv CSAN_WRITE(1) 206 1.1 maxv CSAN_WRITE(2) 207 1.1 maxv CSAN_WRITE(4) 208 1.1 maxv CSAN_WRITE(8) 209 1.1 maxv CSAN_WRITE(16) 210 1.1 maxv 211 1.1 maxv void __tsan_read_range(uintptr_t, size_t); 212 1.1 maxv void __tsan_write_range(uintptr_t, size_t); 213 1.1 maxv 214 1.1 maxv void 215 1.1 maxv __tsan_read_range(uintptr_t addr, size_t size) 216 1.1 maxv { 217 1.1 maxv kcsan_access(addr, size, false, false, __RET_ADDR); 218 1.1 maxv } 219 1.1 maxv 220 1.1 maxv void 221 1.1 maxv __tsan_write_range(uintptr_t addr, size_t size) 222 1.1 maxv { 223 1.1 maxv kcsan_access(addr, size, true, false, __RET_ADDR); 224 1.1 maxv } 225 1.1 maxv 226 1.1 maxv void __tsan_init(void); 227 1.1 maxv void __tsan_func_entry(void *); 228 1.1 maxv void __tsan_func_exit(void); 229 1.1 maxv 230 1.1 maxv void 231 1.1 maxv __tsan_init(void) 232 1.1 maxv { 233 1.1 maxv } 234 1.1 maxv 235 1.1 maxv void 236 1.1 maxv __tsan_func_entry(void *call_pc) 237 1.1 maxv { 238 1.1 maxv } 239 1.1 maxv 240 1.1 maxv void 241 1.1 maxv __tsan_func_exit(void) 242 1.1 maxv { 243 1.1 maxv } 244 1.1 maxv 245 1.1 maxv /* -------------------------------------------------------------------------- */ 246 1.1 maxv 247 1.1 maxv void * 248 1.1 maxv kcsan_memcpy(void *dst, const void *src, size_t len) 249 1.1 maxv { 250 1.1 maxv kcsan_access((uintptr_t)src, len, false, false, __RET_ADDR); 251 1.1 maxv kcsan_access((uintptr_t)dst, len, true, false, __RET_ADDR); 252 1.1 maxv return __builtin_memcpy(dst, src, len); 253 1.1 maxv } 254 1.1 maxv 255 1.1 maxv int 256 1.1 maxv kcsan_memcmp(const void *b1, const void *b2, size_t len) 257 1.1 maxv { 258 1.1 maxv kcsan_access((uintptr_t)b1, len, false, false, __RET_ADDR); 259 1.1 maxv kcsan_access((uintptr_t)b2, len, false, false, __RET_ADDR); 260 1.1 maxv return __builtin_memcmp(b1, b2, len); 261 1.1 maxv } 262 1.1 maxv 263 1.1 maxv void * 264 1.1 maxv kcsan_memset(void *b, int c, size_t len) 265 1.1 maxv { 266 1.1 maxv kcsan_access((uintptr_t)b, len, true, false, __RET_ADDR); 267 1.1 maxv return __builtin_memset(b, c, len); 268 1.1 maxv } 269 1.1 maxv 270 1.1 maxv void * 271 1.1 maxv kcsan_memmove(void *dst, const void *src, size_t len) 272 1.1 maxv { 273 1.1 maxv kcsan_access((uintptr_t)src, len, false, false, __RET_ADDR); 274 1.1 maxv kcsan_access((uintptr_t)dst, len, true, false, __RET_ADDR); 275 1.1 maxv return __builtin_memmove(dst, src, len); 276 1.1 maxv } 277 1.1 maxv 278 1.1 maxv char * 279 1.1 maxv kcsan_strcpy(char *dst, const char *src) 280 1.1 maxv { 281 1.1 maxv char *save = dst; 282 1.1 maxv 283 1.1 maxv while (1) { 284 1.1 maxv kcsan_access((uintptr_t)src, 1, false, false, __RET_ADDR); 285 1.1 maxv kcsan_access((uintptr_t)dst, 1, true, false, __RET_ADDR); 286 1.1 maxv *dst = *src; 287 1.1 maxv if (*src == '\0') 288 1.1 maxv break; 289 1.1 maxv src++, dst++; 290 1.1 maxv } 291 1.1 maxv 292 1.1 maxv return save; 293 1.1 maxv } 294 1.1 maxv 295 1.1 maxv int 296 1.1 maxv kcsan_strcmp(const char *s1, const char *s2) 297 1.1 maxv { 298 1.1 maxv while (1) { 299 1.1 maxv kcsan_access((uintptr_t)s1, 1, false, false, __RET_ADDR); 300 1.1 maxv kcsan_access((uintptr_t)s2, 1, false, false, __RET_ADDR); 301 1.1 maxv if (*s1 != *s2) 302 1.1 maxv break; 303 1.1 maxv if (*s1 == '\0') 304 1.1 maxv return 0; 305 1.1 maxv s1++, s2++; 306 1.1 maxv } 307 1.1 maxv 308 1.1 maxv return (*(const unsigned char *)s1 - *(const unsigned char *)s2); 309 1.1 maxv } 310 1.1 maxv 311 1.1 maxv size_t 312 1.1 maxv kcsan_strlen(const char *str) 313 1.1 maxv { 314 1.1 maxv const char *s; 315 1.1 maxv 316 1.1 maxv s = str; 317 1.1 maxv while (1) { 318 1.1 maxv kcsan_access((uintptr_t)s, 1, false, false, __RET_ADDR); 319 1.1 maxv if (*s == '\0') 320 1.1 maxv break; 321 1.1 maxv s++; 322 1.1 maxv } 323 1.1 maxv 324 1.1 maxv return (s - str); 325 1.1 maxv } 326 1.1 maxv 327 1.1 maxv #undef kcopy 328 1.1 maxv #undef copyinstr 329 1.1 maxv #undef copyoutstr 330 1.1 maxv #undef copyin 331 1.5 maxv #undef copyout 332 1.1 maxv 333 1.1 maxv int kcsan_kcopy(const void *, void *, size_t); 334 1.1 maxv int kcsan_copyinstr(const void *, void *, size_t, size_t *); 335 1.1 maxv int kcsan_copyoutstr(const void *, void *, size_t, size_t *); 336 1.1 maxv int kcsan_copyin(const void *, void *, size_t); 337 1.5 maxv int kcsan_copyout(const void *, void *, size_t); 338 1.1 maxv int kcopy(const void *, void *, size_t); 339 1.1 maxv int copyinstr(const void *, void *, size_t, size_t *); 340 1.1 maxv int copyoutstr(const void *, void *, size_t, size_t *); 341 1.1 maxv int copyin(const void *, void *, size_t); 342 1.5 maxv int copyout(const void *, void *, size_t); 343 1.1 maxv 344 1.1 maxv int 345 1.1 maxv kcsan_kcopy(const void *src, void *dst, size_t len) 346 1.1 maxv { 347 1.1 maxv kcsan_access((uintptr_t)src, len, false, false, __RET_ADDR); 348 1.1 maxv kcsan_access((uintptr_t)dst, len, true, false, __RET_ADDR); 349 1.1 maxv return kcopy(src, dst, len); 350 1.1 maxv } 351 1.1 maxv 352 1.1 maxv int 353 1.1 maxv kcsan_copyin(const void *uaddr, void *kaddr, size_t len) 354 1.1 maxv { 355 1.1 maxv kcsan_access((uintptr_t)kaddr, len, true, false, __RET_ADDR); 356 1.1 maxv return copyin(uaddr, kaddr, len); 357 1.1 maxv } 358 1.1 maxv 359 1.1 maxv int 360 1.5 maxv kcsan_copyout(const void *kaddr, void *uaddr, size_t len) 361 1.5 maxv { 362 1.5 maxv kcsan_access((uintptr_t)kaddr, len, false, false, __RET_ADDR); 363 1.5 maxv return copyout(kaddr, uaddr, len); 364 1.5 maxv } 365 1.5 maxv 366 1.5 maxv int 367 1.1 maxv kcsan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) 368 1.1 maxv { 369 1.1 maxv kcsan_access((uintptr_t)kaddr, len, true, false, __RET_ADDR); 370 1.1 maxv return copyinstr(uaddr, kaddr, len, done); 371 1.1 maxv } 372 1.1 maxv 373 1.1 maxv int 374 1.1 maxv kcsan_copyoutstr(const void *kaddr, void *uaddr, size_t len, size_t *done) 375 1.1 maxv { 376 1.1 maxv kcsan_access((uintptr_t)kaddr, len, false, false, __RET_ADDR); 377 1.1 maxv return copyoutstr(kaddr, uaddr, len, done); 378 1.1 maxv } 379 1.1 maxv 380 1.1 maxv /* -------------------------------------------------------------------------- */ 381 1.1 maxv 382 1.1 maxv #undef atomic_add_32 383 1.1 maxv #undef atomic_add_int 384 1.1 maxv #undef atomic_add_long 385 1.1 maxv #undef atomic_add_ptr 386 1.1 maxv #undef atomic_add_64 387 1.1 maxv #undef atomic_add_32_nv 388 1.1 maxv #undef atomic_add_int_nv 389 1.1 maxv #undef atomic_add_long_nv 390 1.1 maxv #undef atomic_add_ptr_nv 391 1.1 maxv #undef atomic_add_64_nv 392 1.1 maxv #undef atomic_and_32 393 1.1 maxv #undef atomic_and_uint 394 1.1 maxv #undef atomic_and_ulong 395 1.1 maxv #undef atomic_and_64 396 1.1 maxv #undef atomic_and_32_nv 397 1.1 maxv #undef atomic_and_uint_nv 398 1.1 maxv #undef atomic_and_ulong_nv 399 1.1 maxv #undef atomic_and_64_nv 400 1.1 maxv #undef atomic_or_32 401 1.1 maxv #undef atomic_or_uint 402 1.1 maxv #undef atomic_or_ulong 403 1.1 maxv #undef atomic_or_64 404 1.1 maxv #undef atomic_or_32_nv 405 1.1 maxv #undef atomic_or_uint_nv 406 1.1 maxv #undef atomic_or_ulong_nv 407 1.1 maxv #undef atomic_or_64_nv 408 1.1 maxv #undef atomic_cas_32 409 1.1 maxv #undef atomic_cas_uint 410 1.1 maxv #undef atomic_cas_ulong 411 1.1 maxv #undef atomic_cas_ptr 412 1.1 maxv #undef atomic_cas_64 413 1.1 maxv #undef atomic_cas_32_ni 414 1.1 maxv #undef atomic_cas_uint_ni 415 1.1 maxv #undef atomic_cas_ulong_ni 416 1.1 maxv #undef atomic_cas_ptr_ni 417 1.1 maxv #undef atomic_cas_64_ni 418 1.1 maxv #undef atomic_swap_32 419 1.1 maxv #undef atomic_swap_uint 420 1.1 maxv #undef atomic_swap_ulong 421 1.1 maxv #undef atomic_swap_ptr 422 1.1 maxv #undef atomic_swap_64 423 1.1 maxv #undef atomic_dec_32 424 1.1 maxv #undef atomic_dec_uint 425 1.1 maxv #undef atomic_dec_ulong 426 1.1 maxv #undef atomic_dec_ptr 427 1.1 maxv #undef atomic_dec_64 428 1.1 maxv #undef atomic_dec_32_nv 429 1.1 maxv #undef atomic_dec_uint_nv 430 1.1 maxv #undef atomic_dec_ulong_nv 431 1.1 maxv #undef atomic_dec_ptr_nv 432 1.1 maxv #undef atomic_dec_64_nv 433 1.1 maxv #undef atomic_inc_32 434 1.1 maxv #undef atomic_inc_uint 435 1.1 maxv #undef atomic_inc_ulong 436 1.1 maxv #undef atomic_inc_ptr 437 1.1 maxv #undef atomic_inc_64 438 1.1 maxv #undef atomic_inc_32_nv 439 1.1 maxv #undef atomic_inc_uint_nv 440 1.1 maxv #undef atomic_inc_ulong_nv 441 1.1 maxv #undef atomic_inc_ptr_nv 442 1.1 maxv #undef atomic_inc_64_nv 443 1.1 maxv 444 1.1 maxv #define CSAN_ATOMIC_FUNC_ADD(name, tret, targ1, targ2) \ 445 1.1 maxv void atomic_add_##name(volatile targ1 *, targ2); \ 446 1.1 maxv void kcsan_atomic_add_##name(volatile targ1 *, targ2); \ 447 1.1 maxv void kcsan_atomic_add_##name(volatile targ1 *ptr, targ2 val) \ 448 1.1 maxv { \ 449 1.1 maxv kcsan_access((uintptr_t)ptr, sizeof(tret), true, true, \ 450 1.1 maxv __RET_ADDR); \ 451 1.1 maxv atomic_add_##name(ptr, val); \ 452 1.1 maxv } \ 453 1.1 maxv tret atomic_add_##name##_nv(volatile targ1 *, targ2); \ 454 1.1 maxv tret kcsan_atomic_add_##name##_nv(volatile targ1 *, targ2); \ 455 1.1 maxv tret kcsan_atomic_add_##name##_nv(volatile targ1 *ptr, targ2 val) \ 456 1.1 maxv { \ 457 1.1 maxv kcsan_access((uintptr_t)ptr, sizeof(tret), true, true, \ 458 1.1 maxv __RET_ADDR); \ 459 1.1 maxv return atomic_add_##name##_nv(ptr, val); \ 460 1.1 maxv } 461 1.1 maxv 462 1.1 maxv #define CSAN_ATOMIC_FUNC_AND(name, tret, targ1, targ2) \ 463 1.1 maxv void atomic_and_##name(volatile targ1 *, targ2); \ 464 1.1 maxv void kcsan_atomic_and_##name(volatile targ1 *, targ2); \ 465 1.1 maxv void kcsan_atomic_and_##name(volatile targ1 *ptr, targ2 val) \ 466 1.1 maxv { \ 467 1.1 maxv kcsan_access((uintptr_t)ptr, sizeof(tret), true, true, \ 468 1.1 maxv __RET_ADDR); \ 469 1.1 maxv atomic_and_##name(ptr, val); \ 470 1.1 maxv } \ 471 1.1 maxv tret atomic_and_##name##_nv(volatile targ1 *, targ2); \ 472 1.1 maxv tret kcsan_atomic_and_##name##_nv(volatile targ1 *, targ2); \ 473 1.1 maxv tret kcsan_atomic_and_##name##_nv(volatile targ1 *ptr, targ2 val) \ 474 1.1 maxv { \ 475 1.1 maxv kcsan_access((uintptr_t)ptr, sizeof(tret), true, true, \ 476 1.1 maxv __RET_ADDR); \ 477 1.1 maxv return atomic_and_##name##_nv(ptr, val); \ 478 1.1 maxv } 479 1.1 maxv 480 1.1 maxv #define CSAN_ATOMIC_FUNC_OR(name, tret, targ1, targ2) \ 481 1.1 maxv void atomic_or_##name(volatile targ1 *, targ2); \ 482 1.1 maxv void kcsan_atomic_or_##name(volatile targ1 *, targ2); \ 483 1.1 maxv void kcsan_atomic_or_##name(volatile targ1 *ptr, targ2 val) \ 484 1.1 maxv { \ 485 1.1 maxv kcsan_access((uintptr_t)ptr, sizeof(tret), true, true, \ 486 1.1 maxv __RET_ADDR); \ 487 1.1 maxv atomic_or_##name(ptr, val); \ 488 1.1 maxv } \ 489 1.1 maxv tret atomic_or_##name##_nv(volatile targ1 *, targ2); \ 490 1.1 maxv tret kcsan_atomic_or_##name##_nv(volatile targ1 *, targ2); \ 491 1.1 maxv tret kcsan_atomic_or_##name##_nv(volatile targ1 *ptr, targ2 val) \ 492 1.1 maxv { \ 493 1.1 maxv kcsan_access((uintptr_t)ptr, sizeof(tret), true, true, \ 494 1.1 maxv __RET_ADDR); \ 495 1.1 maxv return atomic_or_##name##_nv(ptr, val); \ 496 1.1 maxv } 497 1.1 maxv 498 1.1 maxv #define CSAN_ATOMIC_FUNC_CAS(name, tret, targ1, targ2) \ 499 1.1 maxv tret atomic_cas_##name(volatile targ1 *, targ2, targ2); \ 500 1.1 maxv tret kcsan_atomic_cas_##name(volatile targ1 *, targ2, targ2); \ 501 1.1 maxv tret kcsan_atomic_cas_##name(volatile targ1 *ptr, targ2 exp, targ2 new) \ 502 1.1 maxv { \ 503 1.1 maxv kcsan_access((uintptr_t)ptr, sizeof(tret), true, true, \ 504 1.1 maxv __RET_ADDR); \ 505 1.1 maxv return atomic_cas_##name(ptr, exp, new); \ 506 1.1 maxv } \ 507 1.1 maxv tret atomic_cas_##name##_ni(volatile targ1 *, targ2, targ2); \ 508 1.1 maxv tret kcsan_atomic_cas_##name##_ni(volatile targ1 *, targ2, targ2); \ 509 1.1 maxv tret kcsan_atomic_cas_##name##_ni(volatile targ1 *ptr, targ2 exp, targ2 new) \ 510 1.1 maxv { \ 511 1.1 maxv kcsan_access((uintptr_t)ptr, sizeof(tret), true, true, \ 512 1.1 maxv __RET_ADDR); \ 513 1.1 maxv return atomic_cas_##name##_ni(ptr, exp, new); \ 514 1.1 maxv } 515 1.1 maxv 516 1.1 maxv #define CSAN_ATOMIC_FUNC_SWAP(name, tret, targ1, targ2) \ 517 1.1 maxv tret atomic_swap_##name(volatile targ1 *, targ2); \ 518 1.1 maxv tret kcsan_atomic_swap_##name(volatile targ1 *, targ2); \ 519 1.1 maxv tret kcsan_atomic_swap_##name(volatile targ1 *ptr, targ2 val) \ 520 1.1 maxv { \ 521 1.1 maxv kcsan_access((uintptr_t)ptr, sizeof(tret), true, true, \ 522 1.1 maxv __RET_ADDR); \ 523 1.1 maxv return atomic_swap_##name(ptr, val); \ 524 1.1 maxv } 525 1.1 maxv 526 1.1 maxv #define CSAN_ATOMIC_FUNC_DEC(name, tret, targ1) \ 527 1.1 maxv void atomic_dec_##name(volatile targ1 *); \ 528 1.1 maxv void kcsan_atomic_dec_##name(volatile targ1 *); \ 529 1.1 maxv void kcsan_atomic_dec_##name(volatile targ1 *ptr) \ 530 1.1 maxv { \ 531 1.1 maxv kcsan_access((uintptr_t)ptr, sizeof(tret), true, true, \ 532 1.1 maxv __RET_ADDR); \ 533 1.1 maxv atomic_dec_##name(ptr); \ 534 1.1 maxv } \ 535 1.1 maxv tret atomic_dec_##name##_nv(volatile targ1 *); \ 536 1.1 maxv tret kcsan_atomic_dec_##name##_nv(volatile targ1 *); \ 537 1.1 maxv tret kcsan_atomic_dec_##name##_nv(volatile targ1 *ptr) \ 538 1.1 maxv { \ 539 1.1 maxv kcsan_access((uintptr_t)ptr, sizeof(tret), true, true, \ 540 1.1 maxv __RET_ADDR); \ 541 1.1 maxv return atomic_dec_##name##_nv(ptr); \ 542 1.1 maxv } 543 1.1 maxv 544 1.1 maxv #define CSAN_ATOMIC_FUNC_INC(name, tret, targ1) \ 545 1.1 maxv void atomic_inc_##name(volatile targ1 *); \ 546 1.1 maxv void kcsan_atomic_inc_##name(volatile targ1 *); \ 547 1.1 maxv void kcsan_atomic_inc_##name(volatile targ1 *ptr) \ 548 1.1 maxv { \ 549 1.1 maxv kcsan_access((uintptr_t)ptr, sizeof(tret), true, true, \ 550 1.1 maxv __RET_ADDR); \ 551 1.1 maxv atomic_inc_##name(ptr); \ 552 1.1 maxv } \ 553 1.1 maxv tret atomic_inc_##name##_nv(volatile targ1 *); \ 554 1.1 maxv tret kcsan_atomic_inc_##name##_nv(volatile targ1 *); \ 555 1.1 maxv tret kcsan_atomic_inc_##name##_nv(volatile targ1 *ptr) \ 556 1.1 maxv { \ 557 1.1 maxv kcsan_access((uintptr_t)ptr, sizeof(tret), true, true, \ 558 1.1 maxv __RET_ADDR); \ 559 1.1 maxv return atomic_inc_##name##_nv(ptr); \ 560 1.1 maxv } 561 1.1 maxv 562 1.1 maxv CSAN_ATOMIC_FUNC_ADD(32, uint32_t, uint32_t, int32_t); 563 1.1 maxv CSAN_ATOMIC_FUNC_ADD(64, uint64_t, uint64_t, int64_t); 564 1.1 maxv CSAN_ATOMIC_FUNC_ADD(int, unsigned int, unsigned int, int); 565 1.1 maxv CSAN_ATOMIC_FUNC_ADD(long, unsigned long, unsigned long, long); 566 1.1 maxv CSAN_ATOMIC_FUNC_ADD(ptr, void *, void, ssize_t); 567 1.1 maxv 568 1.1 maxv CSAN_ATOMIC_FUNC_AND(32, uint32_t, uint32_t, uint32_t); 569 1.1 maxv CSAN_ATOMIC_FUNC_AND(64, uint64_t, uint64_t, uint64_t); 570 1.1 maxv CSAN_ATOMIC_FUNC_AND(uint, unsigned int, unsigned int, unsigned int); 571 1.1 maxv CSAN_ATOMIC_FUNC_AND(ulong, unsigned long, unsigned long, unsigned long); 572 1.1 maxv 573 1.1 maxv CSAN_ATOMIC_FUNC_OR(32, uint32_t, uint32_t, uint32_t); 574 1.1 maxv CSAN_ATOMIC_FUNC_OR(64, uint64_t, uint64_t, uint64_t); 575 1.1 maxv CSAN_ATOMIC_FUNC_OR(uint, unsigned int, unsigned int, unsigned int); 576 1.1 maxv CSAN_ATOMIC_FUNC_OR(ulong, unsigned long, unsigned long, unsigned long); 577 1.1 maxv 578 1.1 maxv CSAN_ATOMIC_FUNC_CAS(32, uint32_t, uint32_t, uint32_t); 579 1.1 maxv CSAN_ATOMIC_FUNC_CAS(64, uint64_t, uint64_t, uint64_t); 580 1.1 maxv CSAN_ATOMIC_FUNC_CAS(uint, unsigned int, unsigned int, unsigned int); 581 1.1 maxv CSAN_ATOMIC_FUNC_CAS(ulong, unsigned long, unsigned long, unsigned long); 582 1.1 maxv CSAN_ATOMIC_FUNC_CAS(ptr, void *, void, void *); 583 1.1 maxv 584 1.1 maxv CSAN_ATOMIC_FUNC_SWAP(32, uint32_t, uint32_t, uint32_t); 585 1.1 maxv CSAN_ATOMIC_FUNC_SWAP(64, uint64_t, uint64_t, uint64_t); 586 1.1 maxv CSAN_ATOMIC_FUNC_SWAP(uint, unsigned int, unsigned int, unsigned int); 587 1.1 maxv CSAN_ATOMIC_FUNC_SWAP(ulong, unsigned long, unsigned long, unsigned long); 588 1.1 maxv CSAN_ATOMIC_FUNC_SWAP(ptr, void *, void, void *); 589 1.1 maxv 590 1.1 maxv CSAN_ATOMIC_FUNC_DEC(32, uint32_t, uint32_t) 591 1.1 maxv CSAN_ATOMIC_FUNC_DEC(64, uint64_t, uint64_t) 592 1.1 maxv CSAN_ATOMIC_FUNC_DEC(uint, unsigned int, unsigned int); 593 1.1 maxv CSAN_ATOMIC_FUNC_DEC(ulong, unsigned long, unsigned long); 594 1.1 maxv CSAN_ATOMIC_FUNC_DEC(ptr, void *, void); 595 1.1 maxv 596 1.1 maxv CSAN_ATOMIC_FUNC_INC(32, uint32_t, uint32_t) 597 1.1 maxv CSAN_ATOMIC_FUNC_INC(64, uint64_t, uint64_t) 598 1.1 maxv CSAN_ATOMIC_FUNC_INC(uint, unsigned int, unsigned int); 599 1.1 maxv CSAN_ATOMIC_FUNC_INC(ulong, unsigned long, unsigned long); 600 1.1 maxv CSAN_ATOMIC_FUNC_INC(ptr, void *, void); 601 1.1 maxv 602 1.6 maxv void 603 1.6 maxv kcsan_atomic_load(const volatile void *p, void *v, int size) 604 1.6 maxv { 605 1.8 maxv kcsan_access((uintptr_t)p, size, false, true, __RET_ADDR); 606 1.6 maxv switch (size) { 607 1.6 maxv case 1: *(uint8_t *)v = *(const volatile uint8_t *)p; break; 608 1.6 maxv case 2: *(uint16_t *)v = *(const volatile uint16_t *)p; break; 609 1.6 maxv case 4: *(uint32_t *)v = *(const volatile uint32_t *)p; break; 610 1.6 maxv case 8: *(uint64_t *)v = *(const volatile uint64_t *)p; break; 611 1.6 maxv } 612 1.6 maxv } 613 1.6 maxv 614 1.6 maxv void 615 1.6 maxv kcsan_atomic_store(volatile void *p, const void *v, int size) 616 1.6 maxv { 617 1.8 maxv kcsan_access((uintptr_t)p, size, true, true, __RET_ADDR); 618 1.14 riastrad #ifdef __HAVE_HASHLOCKED_ATOMICS 619 1.14 riastrad __do_atomic_store(p, v, size); 620 1.14 riastrad #else 621 1.6 maxv switch (size) { 622 1.6 maxv case 1: *(volatile uint8_t *)p = *(const uint8_t *)v; break; 623 1.6 maxv case 2: *(volatile uint16_t *)p = *(const uint16_t *)v; break; 624 1.6 maxv case 4: *(volatile uint32_t *)p = *(const uint32_t *)v; break; 625 1.6 maxv case 8: *(volatile uint64_t *)p = *(const uint64_t *)v; break; 626 1.6 maxv } 627 1.14 riastrad #endif 628 1.6 maxv } 629 1.6 maxv 630 1.1 maxv /* -------------------------------------------------------------------------- */ 631 1.1 maxv 632 1.1 maxv #include <sys/bus.h> 633 1.1 maxv 634 1.1 maxv #undef bus_space_read_multi_1 635 1.1 maxv #undef bus_space_read_multi_2 636 1.1 maxv #undef bus_space_read_multi_4 637 1.1 maxv #undef bus_space_read_multi_8 638 1.1 maxv #undef bus_space_read_multi_stream_1 639 1.1 maxv #undef bus_space_read_multi_stream_2 640 1.1 maxv #undef bus_space_read_multi_stream_4 641 1.1 maxv #undef bus_space_read_multi_stream_8 642 1.1 maxv #undef bus_space_read_region_1 643 1.1 maxv #undef bus_space_read_region_2 644 1.1 maxv #undef bus_space_read_region_4 645 1.1 maxv #undef bus_space_read_region_8 646 1.1 maxv #undef bus_space_read_region_stream_1 647 1.1 maxv #undef bus_space_read_region_stream_2 648 1.1 maxv #undef bus_space_read_region_stream_4 649 1.1 maxv #undef bus_space_read_region_stream_8 650 1.1 maxv #undef bus_space_write_multi_1 651 1.1 maxv #undef bus_space_write_multi_2 652 1.1 maxv #undef bus_space_write_multi_4 653 1.1 maxv #undef bus_space_write_multi_8 654 1.1 maxv #undef bus_space_write_multi_stream_1 655 1.1 maxv #undef bus_space_write_multi_stream_2 656 1.1 maxv #undef bus_space_write_multi_stream_4 657 1.1 maxv #undef bus_space_write_multi_stream_8 658 1.1 maxv #undef bus_space_write_region_1 659 1.1 maxv #undef bus_space_write_region_2 660 1.1 maxv #undef bus_space_write_region_4 661 1.1 maxv #undef bus_space_write_region_8 662 1.1 maxv #undef bus_space_write_region_stream_1 663 1.1 maxv #undef bus_space_write_region_stream_2 664 1.1 maxv #undef bus_space_write_region_stream_4 665 1.1 maxv #undef bus_space_write_region_stream_8 666 1.1 maxv 667 1.1 maxv #define CSAN_BUS_READ_FUNC(bytes, bits) \ 668 1.1 maxv void bus_space_read_multi_##bytes(bus_space_tag_t, bus_space_handle_t, \ 669 1.1 maxv bus_size_t, uint##bits##_t *, bus_size_t); \ 670 1.1 maxv void kcsan_bus_space_read_multi_##bytes(bus_space_tag_t, \ 671 1.1 maxv bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ 672 1.1 maxv void kcsan_bus_space_read_multi_##bytes(bus_space_tag_t tag, \ 673 1.1 maxv bus_space_handle_t hnd, bus_size_t size, uint##bits##_t *buf, \ 674 1.1 maxv bus_size_t count) \ 675 1.1 maxv { \ 676 1.1 maxv kcsan_access((uintptr_t)buf, sizeof(uint##bits##_t) * count, \ 677 1.1 maxv false, false, __RET_ADDR); \ 678 1.1 maxv bus_space_read_multi_##bytes(tag, hnd, size, buf, count); \ 679 1.1 maxv } \ 680 1.1 maxv void bus_space_read_multi_stream_##bytes(bus_space_tag_t, \ 681 1.1 maxv bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ 682 1.1 maxv void kcsan_bus_space_read_multi_stream_##bytes(bus_space_tag_t, \ 683 1.1 maxv bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ 684 1.1 maxv void kcsan_bus_space_read_multi_stream_##bytes(bus_space_tag_t tag, \ 685 1.1 maxv bus_space_handle_t hnd, bus_size_t size, uint##bits##_t *buf, \ 686 1.1 maxv bus_size_t count) \ 687 1.1 maxv { \ 688 1.1 maxv kcsan_access((uintptr_t)buf, sizeof(uint##bits##_t) * count, \ 689 1.1 maxv false, false, __RET_ADDR); \ 690 1.1 maxv bus_space_read_multi_stream_##bytes(tag, hnd, size, buf, count);\ 691 1.1 maxv } \ 692 1.1 maxv void bus_space_read_region_##bytes(bus_space_tag_t, bus_space_handle_t, \ 693 1.1 maxv bus_size_t, uint##bits##_t *, bus_size_t); \ 694 1.1 maxv void kcsan_bus_space_read_region_##bytes(bus_space_tag_t, \ 695 1.1 maxv bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ 696 1.1 maxv void kcsan_bus_space_read_region_##bytes(bus_space_tag_t tag, \ 697 1.1 maxv bus_space_handle_t hnd, bus_size_t size, uint##bits##_t *buf, \ 698 1.1 maxv bus_size_t count) \ 699 1.1 maxv { \ 700 1.1 maxv kcsan_access((uintptr_t)buf, sizeof(uint##bits##_t) * count, \ 701 1.1 maxv false, false, __RET_ADDR); \ 702 1.1 maxv bus_space_read_region_##bytes(tag, hnd, size, buf, count); \ 703 1.1 maxv } \ 704 1.1 maxv void bus_space_read_region_stream_##bytes(bus_space_tag_t, \ 705 1.1 maxv bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ 706 1.1 maxv void kcsan_bus_space_read_region_stream_##bytes(bus_space_tag_t, \ 707 1.1 maxv bus_space_handle_t, bus_size_t, uint##bits##_t *, bus_size_t); \ 708 1.1 maxv void kcsan_bus_space_read_region_stream_##bytes(bus_space_tag_t tag, \ 709 1.1 maxv bus_space_handle_t hnd, bus_size_t size, uint##bits##_t *buf, \ 710 1.1 maxv bus_size_t count) \ 711 1.1 maxv { \ 712 1.1 maxv kcsan_access((uintptr_t)buf, sizeof(uint##bits##_t) * count, \ 713 1.1 maxv false, false, __RET_ADDR); \ 714 1.1 maxv bus_space_read_region_stream_##bytes(tag, hnd, size, buf, count);\ 715 1.1 maxv } 716 1.1 maxv 717 1.1 maxv #define CSAN_BUS_WRITE_FUNC(bytes, bits) \ 718 1.1 maxv void bus_space_write_multi_##bytes(bus_space_tag_t, bus_space_handle_t, \ 719 1.1 maxv bus_size_t, const uint##bits##_t *, bus_size_t); \ 720 1.1 maxv void kcsan_bus_space_write_multi_##bytes(bus_space_tag_t, \ 721 1.1 maxv bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ 722 1.1 maxv void kcsan_bus_space_write_multi_##bytes(bus_space_tag_t tag, \ 723 1.1 maxv bus_space_handle_t hnd, bus_size_t size, const uint##bits##_t *buf, \ 724 1.1 maxv bus_size_t count) \ 725 1.1 maxv { \ 726 1.1 maxv kcsan_access((uintptr_t)buf, sizeof(uint##bits##_t) * count, \ 727 1.1 maxv true, false, __RET_ADDR); \ 728 1.1 maxv bus_space_write_multi_##bytes(tag, hnd, size, buf, count); \ 729 1.1 maxv } \ 730 1.1 maxv void bus_space_write_multi_stream_##bytes(bus_space_tag_t, \ 731 1.1 maxv bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ 732 1.1 maxv void kcsan_bus_space_write_multi_stream_##bytes(bus_space_tag_t, \ 733 1.1 maxv bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ 734 1.1 maxv void kcsan_bus_space_write_multi_stream_##bytes(bus_space_tag_t tag, \ 735 1.1 maxv bus_space_handle_t hnd, bus_size_t size, const uint##bits##_t *buf, \ 736 1.1 maxv bus_size_t count) \ 737 1.1 maxv { \ 738 1.1 maxv kcsan_access((uintptr_t)buf, sizeof(uint##bits##_t) * count, \ 739 1.1 maxv true, false, __RET_ADDR); \ 740 1.1 maxv bus_space_write_multi_stream_##bytes(tag, hnd, size, buf, count);\ 741 1.1 maxv } \ 742 1.1 maxv void bus_space_write_region_##bytes(bus_space_tag_t, bus_space_handle_t,\ 743 1.1 maxv bus_size_t, const uint##bits##_t *, bus_size_t); \ 744 1.1 maxv void kcsan_bus_space_write_region_##bytes(bus_space_tag_t, \ 745 1.1 maxv bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ 746 1.1 maxv void kcsan_bus_space_write_region_##bytes(bus_space_tag_t tag, \ 747 1.1 maxv bus_space_handle_t hnd, bus_size_t size, const uint##bits##_t *buf, \ 748 1.1 maxv bus_size_t count) \ 749 1.1 maxv { \ 750 1.1 maxv kcsan_access((uintptr_t)buf, sizeof(uint##bits##_t) * count, \ 751 1.1 maxv true, false, __RET_ADDR); \ 752 1.1 maxv bus_space_write_region_##bytes(tag, hnd, size, buf, count); \ 753 1.1 maxv } \ 754 1.1 maxv void bus_space_write_region_stream_##bytes(bus_space_tag_t, \ 755 1.1 maxv bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ 756 1.1 maxv void kcsan_bus_space_write_region_stream_##bytes(bus_space_tag_t, \ 757 1.1 maxv bus_space_handle_t, bus_size_t, const uint##bits##_t *, bus_size_t);\ 758 1.1 maxv void kcsan_bus_space_write_region_stream_##bytes(bus_space_tag_t tag, \ 759 1.1 maxv bus_space_handle_t hnd, bus_size_t size, const uint##bits##_t *buf, \ 760 1.1 maxv bus_size_t count) \ 761 1.1 maxv { \ 762 1.1 maxv kcsan_access((uintptr_t)buf, sizeof(uint##bits##_t) * count, \ 763 1.1 maxv true, false, __RET_ADDR); \ 764 1.1 maxv bus_space_write_region_stream_##bytes(tag, hnd, size, buf, count);\ 765 1.1 maxv } 766 1.1 maxv 767 1.1 maxv CSAN_BUS_READ_FUNC(1, 8) 768 1.1 maxv CSAN_BUS_READ_FUNC(2, 16) 769 1.1 maxv CSAN_BUS_READ_FUNC(4, 32) 770 1.1 maxv CSAN_BUS_READ_FUNC(8, 64) 771 1.1 maxv 772 1.1 maxv CSAN_BUS_WRITE_FUNC(1, 8) 773 1.1 maxv CSAN_BUS_WRITE_FUNC(2, 16) 774 1.1 maxv CSAN_BUS_WRITE_FUNC(4, 32) 775 1.1 maxv CSAN_BUS_WRITE_FUNC(8, 64) 776