10cb53570SAndrew Turner /* $NetBSD: subr_csan.c,v 1.5 2019/11/15 08:11:37 maxv Exp $ */ 20cb53570SAndrew Turner 30cb53570SAndrew Turner /* 40cb53570SAndrew Turner * Copyright (c) 2019 The NetBSD Foundation, Inc. 50cb53570SAndrew Turner * All rights reserved. 6849aef49SAndrew Turner * Copyright (c) 2019 Andrew Turner 70cb53570SAndrew Turner * 80cb53570SAndrew Turner * This code is derived from software contributed to The NetBSD Foundation 90cb53570SAndrew Turner * by Maxime Villard. 100cb53570SAndrew Turner * 110cb53570SAndrew Turner * Redistribution and use in source and binary forms, with or without 120cb53570SAndrew Turner * modification, are permitted provided that the following conditions 130cb53570SAndrew Turner * are met: 140cb53570SAndrew Turner * 1. Redistributions of source code must retain the above copyright 150cb53570SAndrew Turner * notice, this list of conditions and the following disclaimer. 160cb53570SAndrew Turner * 2. Redistributions in binary form must reproduce the above copyright 170cb53570SAndrew Turner * notice, this list of conditions and the following disclaimer in the 180cb53570SAndrew Turner * documentation and/or other materials provided with the distribution. 190cb53570SAndrew Turner * 200cb53570SAndrew Turner * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 210cb53570SAndrew Turner * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 220cb53570SAndrew Turner * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 230cb53570SAndrew Turner * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 240cb53570SAndrew Turner * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 250cb53570SAndrew Turner * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 260cb53570SAndrew Turner * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 270cb53570SAndrew Turner * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 280cb53570SAndrew Turner * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 290cb53570SAndrew Turner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 300cb53570SAndrew Turner * POSSIBILITY OF SUCH DAMAGE. 310cb53570SAndrew Turner */ 320cb53570SAndrew Turner 33849aef49SAndrew Turner #define KCSAN_RUNTIME 34849aef49SAndrew Turner 35849aef49SAndrew Turner #include "opt_ddb.h" 36849aef49SAndrew Turner 370cb53570SAndrew Turner #include <sys/cdefs.h> 38849aef49SAndrew Turner __FBSDID("$FreeBSD$"); 390cb53570SAndrew Turner 400cb53570SAndrew Turner #include <sys/param.h> 410cb53570SAndrew Turner #include <sys/kernel.h> 42849aef49SAndrew Turner #include <sys/bus.h> 430cb53570SAndrew Turner #include <sys/conf.h> 440cb53570SAndrew Turner #include <sys/cpu.h> 45849aef49SAndrew Turner #include <sys/csan.h> 46849aef49SAndrew Turner #include <sys/proc.h> 47849aef49SAndrew Turner #include <sys/smp.h> 48849aef49SAndrew Turner #include <sys/systm.h> 49849aef49SAndrew Turner 50849aef49SAndrew Turner #include <ddb/ddb.h> 51849aef49SAndrew Turner #include <ddb/db_sym.h> 520cb53570SAndrew Turner 530cb53570SAndrew Turner #ifdef KCSAN_PANIC 540cb53570SAndrew Turner #define REPORT panic 550cb53570SAndrew Turner #else 560cb53570SAndrew Turner #define REPORT printf 570cb53570SAndrew Turner #endif 580cb53570SAndrew Turner 590cb53570SAndrew Turner typedef struct { 600cb53570SAndrew Turner uintptr_t addr; 610cb53570SAndrew Turner uint32_t size; 620cb53570SAndrew Turner bool write:1; 630cb53570SAndrew Turner bool atomic:1; 640cb53570SAndrew Turner uintptr_t pc; 650cb53570SAndrew Turner } csan_cell_t; 660cb53570SAndrew Turner 670cb53570SAndrew Turner typedef struct { 680cb53570SAndrew Turner bool inited; 690cb53570SAndrew Turner uint32_t cnt; 700cb53570SAndrew Turner csan_cell_t cell; 710cb53570SAndrew Turner } csan_cpu_t; 720cb53570SAndrew Turner 73849aef49SAndrew Turner static csan_cpu_t kcsan_cpus[MAXCPU]; 740cb53570SAndrew Turner static bool kcsan_enabled __read_mostly; 750cb53570SAndrew Turner 760cb53570SAndrew Turner #define __RET_ADDR (uintptr_t)__builtin_return_address(0) 770cb53570SAndrew Turner 780cb53570SAndrew Turner #define KCSAN_NACCESSES 1024 790cb53570SAndrew Turner #define KCSAN_DELAY 10 /* 10 microseconds */ 800cb53570SAndrew Turner 810cb53570SAndrew Turner /* -------------------------------------------------------------------------- */ 820cb53570SAndrew Turner 830cb53570SAndrew Turner /* The MD code. */ 840cb53570SAndrew Turner #include <machine/csan.h> 850cb53570SAndrew Turner 860cb53570SAndrew Turner /* -------------------------------------------------------------------------- */ 870cb53570SAndrew Turner 88849aef49SAndrew Turner static void 89849aef49SAndrew Turner kcsan_enable(void *dummy __unused) 900cb53570SAndrew Turner { 91849aef49SAndrew Turner 92849aef49SAndrew Turner printf("Enabling KCSCAN, expect reduced performance.\n"); 930cb53570SAndrew Turner kcsan_enabled = true; 940cb53570SAndrew Turner } 95849aef49SAndrew Turner SYSINIT(kcsan_enable, SI_SUB_SMP, SI_ORDER_SECOND, kcsan_enable, NULL); 960cb53570SAndrew Turner 970cb53570SAndrew Turner void 98849aef49SAndrew Turner kcsan_cpu_init(u_int cpu) 990cb53570SAndrew Turner { 100849aef49SAndrew Turner kcsan_cpus[cpu].inited = true; 1010cb53570SAndrew Turner } 1020cb53570SAndrew Turner 1030cb53570SAndrew Turner /* -------------------------------------------------------------------------- */ 1040cb53570SAndrew Turner 1050cb53570SAndrew Turner static inline void 106849aef49SAndrew Turner kcsan_report(csan_cell_t *new, u_int newcpu, csan_cell_t *old, u_int oldcpu) 1070cb53570SAndrew Turner { 1080cb53570SAndrew Turner const char *newsym, *oldsym; 109849aef49SAndrew Turner #ifdef DDB 110849aef49SAndrew Turner c_db_sym_t sym; 111849aef49SAndrew Turner db_expr_t offset; 1120cb53570SAndrew Turner 113849aef49SAndrew Turner sym = db_search_symbol((vm_offset_t)new->pc, DB_STGY_PROC, &offset); 114849aef49SAndrew Turner db_symbol_values(sym, &newsym, NULL); 115849aef49SAndrew Turner 116849aef49SAndrew Turner sym = db_search_symbol((vm_offset_t)old->pc, DB_STGY_PROC, &offset); 117849aef49SAndrew Turner db_symbol_values(sym, &oldsym, NULL); 118849aef49SAndrew Turner #else 119849aef49SAndrew Turner newsym = ""; 120849aef49SAndrew Turner oldsym = ""; 121849aef49SAndrew Turner #endif 1220cb53570SAndrew Turner REPORT("CSan: Racy Access " 123849aef49SAndrew Turner "[Cpu%u %s%s Addr=%p Size=%u PC=%p<%s>] " 124849aef49SAndrew Turner "[Cpu%u %s%s Addr=%p Size=%u PC=%p<%s>]\n", 1250cb53570SAndrew Turner newcpu, 1260cb53570SAndrew Turner (new->atomic ? "Atomic " : ""), (new->write ? "Write" : "Read"), 1270cb53570SAndrew Turner (void *)new->addr, new->size, (void *)new->pc, newsym, 1280cb53570SAndrew Turner oldcpu, 1290cb53570SAndrew Turner (old->atomic ? "Atomic " : ""), (old->write ? "Write" : "Read"), 1300cb53570SAndrew Turner (void *)old->addr, old->size, (void *)old->pc, oldsym); 1310cb53570SAndrew Turner kcsan_md_unwind(); 1320cb53570SAndrew Turner } 1330cb53570SAndrew Turner 1340cb53570SAndrew Turner static inline bool 1350cb53570SAndrew Turner kcsan_access_is_atomic(csan_cell_t *new, csan_cell_t *old) 1360cb53570SAndrew Turner { 1370cb53570SAndrew Turner if (new->write && !new->atomic) 1380cb53570SAndrew Turner return false; 1390cb53570SAndrew Turner if (old->write && !old->atomic) 1400cb53570SAndrew Turner return false; 1410cb53570SAndrew Turner return true; 1420cb53570SAndrew Turner } 1430cb53570SAndrew Turner 1440cb53570SAndrew Turner static inline void 1450cb53570SAndrew Turner kcsan_access(uintptr_t addr, size_t size, bool write, bool atomic, uintptr_t pc) 1460cb53570SAndrew Turner { 1470cb53570SAndrew Turner csan_cell_t old, new; 1480cb53570SAndrew Turner csan_cpu_t *cpu; 1490cb53570SAndrew Turner uint64_t intr; 1500cb53570SAndrew Turner size_t i; 1510cb53570SAndrew Turner 1520cb53570SAndrew Turner if (__predict_false(!kcsan_enabled)) 1530cb53570SAndrew Turner return; 15468cad681SAndrew Turner if (__predict_false(kcsan_md_unsupported((vm_offset_t)addr))) 15568cad681SAndrew Turner return; 156879e0604SMateusz Guzik if (KERNEL_PANICKED()) 157a27ac464SAndrew Turner return; 1580cb53570SAndrew Turner 1590cb53570SAndrew Turner new.addr = addr; 1600cb53570SAndrew Turner new.size = size; 1610cb53570SAndrew Turner new.write = write; 1620cb53570SAndrew Turner new.atomic = atomic; 1630cb53570SAndrew Turner new.pc = pc; 1640cb53570SAndrew Turner 165849aef49SAndrew Turner CPU_FOREACH(i) { 1660cb53570SAndrew Turner __builtin_memcpy(&old, &kcsan_cpus[i].cell, sizeof(old)); 1670cb53570SAndrew Turner 1680cb53570SAndrew Turner if (old.addr + old.size <= new.addr) 1690cb53570SAndrew Turner continue; 1700cb53570SAndrew Turner if (new.addr + new.size <= old.addr) 1710cb53570SAndrew Turner continue; 1720cb53570SAndrew Turner if (__predict_true(!old.write && !new.write)) 1730cb53570SAndrew Turner continue; 1740cb53570SAndrew Turner if (__predict_true(kcsan_access_is_atomic(&new, &old))) 1750cb53570SAndrew Turner continue; 1760cb53570SAndrew Turner 177849aef49SAndrew Turner kcsan_report(&new, PCPU_GET(cpuid), &old, i); 1780cb53570SAndrew Turner break; 1790cb53570SAndrew Turner } 1800cb53570SAndrew Turner 1810cb53570SAndrew Turner if (__predict_false(!kcsan_md_is_avail())) 1820cb53570SAndrew Turner return; 1830cb53570SAndrew Turner 1840cb53570SAndrew Turner kcsan_md_disable_intrs(&intr); 1850cb53570SAndrew Turner 186849aef49SAndrew Turner cpu = &kcsan_cpus[PCPU_GET(cpuid)]; 1870cb53570SAndrew Turner if (__predict_false(!cpu->inited)) 1880cb53570SAndrew Turner goto out; 1890cb53570SAndrew Turner cpu->cnt = (cpu->cnt + 1) % KCSAN_NACCESSES; 1900cb53570SAndrew Turner if (__predict_true(cpu->cnt != 0)) 1910cb53570SAndrew Turner goto out; 1920cb53570SAndrew Turner 1930cb53570SAndrew Turner __builtin_memcpy(&cpu->cell, &new, sizeof(new)); 1940cb53570SAndrew Turner kcsan_md_delay(KCSAN_DELAY); 1950cb53570SAndrew Turner __builtin_memset(&cpu->cell, 0, sizeof(new)); 1960cb53570SAndrew Turner 1970cb53570SAndrew Turner out: 1980cb53570SAndrew Turner kcsan_md_enable_intrs(&intr); 1990cb53570SAndrew Turner } 2000cb53570SAndrew Turner 2010cb53570SAndrew Turner #define CSAN_READ(size) \ 2020cb53570SAndrew Turner void __tsan_read##size(uintptr_t); \ 2030cb53570SAndrew Turner void __tsan_read##size(uintptr_t addr) \ 2040cb53570SAndrew Turner { \ 2050cb53570SAndrew Turner kcsan_access(addr, size, false, false, __RET_ADDR); \ 206849aef49SAndrew Turner } \ 207849aef49SAndrew Turner void __tsan_unaligned_read##size(uintptr_t); \ 208849aef49SAndrew Turner void __tsan_unaligned_read##size(uintptr_t addr) \ 209849aef49SAndrew Turner { \ 210849aef49SAndrew Turner kcsan_access(addr, size, false, false, __RET_ADDR); \ 2110cb53570SAndrew Turner } 2120cb53570SAndrew Turner 2130cb53570SAndrew Turner CSAN_READ(1) 2140cb53570SAndrew Turner CSAN_READ(2) 2150cb53570SAndrew Turner CSAN_READ(4) 2160cb53570SAndrew Turner CSAN_READ(8) 2170cb53570SAndrew Turner CSAN_READ(16) 2180cb53570SAndrew Turner 2190cb53570SAndrew Turner #define CSAN_WRITE(size) \ 2200cb53570SAndrew Turner void __tsan_write##size(uintptr_t); \ 2210cb53570SAndrew Turner void __tsan_write##size(uintptr_t addr) \ 2220cb53570SAndrew Turner { \ 2230cb53570SAndrew Turner kcsan_access(addr, size, true, false, __RET_ADDR); \ 224849aef49SAndrew Turner } \ 225849aef49SAndrew Turner void __tsan_unaligned_write##size(uintptr_t); \ 226849aef49SAndrew Turner void __tsan_unaligned_write##size(uintptr_t addr) \ 227849aef49SAndrew Turner { \ 228849aef49SAndrew Turner kcsan_access(addr, size, true, false, __RET_ADDR); \ 2290cb53570SAndrew Turner } 2300cb53570SAndrew Turner 2310cb53570SAndrew Turner CSAN_WRITE(1) 2320cb53570SAndrew Turner CSAN_WRITE(2) 2330cb53570SAndrew Turner CSAN_WRITE(4) 2340cb53570SAndrew Turner CSAN_WRITE(8) 2350cb53570SAndrew Turner CSAN_WRITE(16) 2360cb53570SAndrew Turner 2370cb53570SAndrew Turner void __tsan_read_range(uintptr_t, size_t); 2380cb53570SAndrew Turner void __tsan_write_range(uintptr_t, size_t); 2390cb53570SAndrew Turner 2400cb53570SAndrew Turner void 2410cb53570SAndrew Turner __tsan_read_range(uintptr_t addr, size_t size) 2420cb53570SAndrew Turner { 2430cb53570SAndrew Turner kcsan_access(addr, size, false, false, __RET_ADDR); 2440cb53570SAndrew Turner } 2450cb53570SAndrew Turner 2460cb53570SAndrew Turner void 2470cb53570SAndrew Turner __tsan_write_range(uintptr_t addr, size_t size) 2480cb53570SAndrew Turner { 2490cb53570SAndrew Turner kcsan_access(addr, size, true, false, __RET_ADDR); 2500cb53570SAndrew Turner } 2510cb53570SAndrew Turner 2520cb53570SAndrew Turner void __tsan_init(void); 2530cb53570SAndrew Turner void __tsan_func_entry(void *); 2540cb53570SAndrew Turner void __tsan_func_exit(void); 2550cb53570SAndrew Turner 2560cb53570SAndrew Turner void 2570cb53570SAndrew Turner __tsan_init(void) 2580cb53570SAndrew Turner { 2590cb53570SAndrew Turner } 2600cb53570SAndrew Turner 2610cb53570SAndrew Turner void 2620cb53570SAndrew Turner __tsan_func_entry(void *call_pc) 2630cb53570SAndrew Turner { 2640cb53570SAndrew Turner } 2650cb53570SAndrew Turner 2660cb53570SAndrew Turner void 2670cb53570SAndrew Turner __tsan_func_exit(void) 2680cb53570SAndrew Turner { 2690cb53570SAndrew Turner } 2700cb53570SAndrew Turner 2710cb53570SAndrew Turner /* -------------------------------------------------------------------------- */ 2720cb53570SAndrew Turner 2730cb53570SAndrew Turner void * 2740cb53570SAndrew Turner kcsan_memcpy(void *dst, const void *src, size_t len) 2750cb53570SAndrew Turner { 2760cb53570SAndrew Turner kcsan_access((uintptr_t)src, len, false, false, __RET_ADDR); 2770cb53570SAndrew Turner kcsan_access((uintptr_t)dst, len, true, false, __RET_ADDR); 2780cb53570SAndrew Turner return __builtin_memcpy(dst, src, len); 2790cb53570SAndrew Turner } 2800cb53570SAndrew Turner 2810cb53570SAndrew Turner int 2820cb53570SAndrew Turner kcsan_memcmp(const void *b1, const void *b2, size_t len) 2830cb53570SAndrew Turner { 2840cb53570SAndrew Turner kcsan_access((uintptr_t)b1, len, false, false, __RET_ADDR); 2850cb53570SAndrew Turner kcsan_access((uintptr_t)b2, len, false, false, __RET_ADDR); 2860cb53570SAndrew Turner return __builtin_memcmp(b1, b2, len); 2870cb53570SAndrew Turner } 2880cb53570SAndrew Turner 2890cb53570SAndrew Turner void * 2900cb53570SAndrew Turner kcsan_memset(void *b, int c, size_t len) 2910cb53570SAndrew Turner { 2920cb53570SAndrew Turner kcsan_access((uintptr_t)b, len, true, false, __RET_ADDR); 2930cb53570SAndrew Turner return __builtin_memset(b, c, len); 2940cb53570SAndrew Turner } 2950cb53570SAndrew Turner 2960cb53570SAndrew Turner void * 2970cb53570SAndrew Turner kcsan_memmove(void *dst, const void *src, size_t len) 2980cb53570SAndrew Turner { 2990cb53570SAndrew Turner kcsan_access((uintptr_t)src, len, false, false, __RET_ADDR); 3000cb53570SAndrew Turner kcsan_access((uintptr_t)dst, len, true, false, __RET_ADDR); 3010cb53570SAndrew Turner return __builtin_memmove(dst, src, len); 3020cb53570SAndrew Turner } 3030cb53570SAndrew Turner 3040cb53570SAndrew Turner char * 3050cb53570SAndrew Turner kcsan_strcpy(char *dst, const char *src) 3060cb53570SAndrew Turner { 3070cb53570SAndrew Turner char *save = dst; 3080cb53570SAndrew Turner 3090cb53570SAndrew Turner while (1) { 3100cb53570SAndrew Turner kcsan_access((uintptr_t)src, 1, false, false, __RET_ADDR); 3110cb53570SAndrew Turner kcsan_access((uintptr_t)dst, 1, true, false, __RET_ADDR); 3120cb53570SAndrew Turner *dst = *src; 3130cb53570SAndrew Turner if (*src == '\0') 3140cb53570SAndrew Turner break; 3150cb53570SAndrew Turner src++, dst++; 3160cb53570SAndrew Turner } 3170cb53570SAndrew Turner 3180cb53570SAndrew Turner return save; 3190cb53570SAndrew Turner } 3200cb53570SAndrew Turner 3210cb53570SAndrew Turner int 3220cb53570SAndrew Turner kcsan_strcmp(const char *s1, const char *s2) 3230cb53570SAndrew Turner { 3240cb53570SAndrew Turner while (1) { 3250cb53570SAndrew Turner kcsan_access((uintptr_t)s1, 1, false, false, __RET_ADDR); 3260cb53570SAndrew Turner kcsan_access((uintptr_t)s2, 1, false, false, __RET_ADDR); 3270cb53570SAndrew Turner if (*s1 != *s2) 3280cb53570SAndrew Turner break; 3290cb53570SAndrew Turner if (*s1 == '\0') 3300cb53570SAndrew Turner return 0; 3310cb53570SAndrew Turner s1++, s2++; 3320cb53570SAndrew Turner } 3330cb53570SAndrew Turner 3340cb53570SAndrew Turner return (*(const unsigned char *)s1 - *(const unsigned char *)s2); 3350cb53570SAndrew Turner } 3360cb53570SAndrew Turner 3370cb53570SAndrew Turner size_t 3380cb53570SAndrew Turner kcsan_strlen(const char *str) 3390cb53570SAndrew Turner { 3400cb53570SAndrew Turner const char *s; 3410cb53570SAndrew Turner 3420cb53570SAndrew Turner s = str; 3430cb53570SAndrew Turner while (1) { 3440cb53570SAndrew Turner kcsan_access((uintptr_t)s, 1, false, false, __RET_ADDR); 3450cb53570SAndrew Turner if (*s == '\0') 3460cb53570SAndrew Turner break; 3470cb53570SAndrew Turner s++; 3480cb53570SAndrew Turner } 3490cb53570SAndrew Turner 3500cb53570SAndrew Turner return (s - str); 3510cb53570SAndrew Turner } 3520cb53570SAndrew Turner 3530cb53570SAndrew Turner #undef copyin 354849aef49SAndrew Turner #undef copyin_nofault 355849aef49SAndrew Turner #undef copyinstr 3560cb53570SAndrew Turner #undef copyout 357849aef49SAndrew Turner #undef copyout_nofault 3580cb53570SAndrew Turner 3590cb53570SAndrew Turner int 3600cb53570SAndrew Turner kcsan_copyin(const void *uaddr, void *kaddr, size_t len) 3610cb53570SAndrew Turner { 3620cb53570SAndrew Turner kcsan_access((uintptr_t)kaddr, len, true, false, __RET_ADDR); 3630cb53570SAndrew Turner return copyin(uaddr, kaddr, len); 3640cb53570SAndrew Turner } 3650cb53570SAndrew Turner 3660cb53570SAndrew Turner int 3670cb53570SAndrew Turner kcsan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) 3680cb53570SAndrew Turner { 3690cb53570SAndrew Turner kcsan_access((uintptr_t)kaddr, len, true, false, __RET_ADDR); 3700cb53570SAndrew Turner return copyinstr(uaddr, kaddr, len, done); 3710cb53570SAndrew Turner } 3720cb53570SAndrew Turner 3730cb53570SAndrew Turner int 374849aef49SAndrew Turner kcsan_copyout(const void *kaddr, void *uaddr, size_t len) 3750cb53570SAndrew Turner { 3760cb53570SAndrew Turner kcsan_access((uintptr_t)kaddr, len, false, false, __RET_ADDR); 377849aef49SAndrew Turner return copyout(kaddr, uaddr, len); 3780cb53570SAndrew Turner } 3790cb53570SAndrew Turner 3800cb53570SAndrew Turner /* -------------------------------------------------------------------------- */ 3810cb53570SAndrew Turner 382849aef49SAndrew Turner #include <machine/atomic.h> 383849aef49SAndrew Turner #include <sys/_cscan_atomic.h> 3840cb53570SAndrew Turner 385849aef49SAndrew Turner #define _CSAN_ATOMIC_FUNC_ADD(name, type) \ 386849aef49SAndrew Turner void kcsan_atomic_add_##name(volatile type *ptr, type val) \ 3870cb53570SAndrew Turner { \ 388849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \ 3890cb53570SAndrew Turner __RET_ADDR); \ 3900cb53570SAndrew Turner atomic_add_##name(ptr, val); \ 3910cb53570SAndrew Turner } 3920cb53570SAndrew Turner 393849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_ADD(name, type) \ 394849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_ADD(name, type) \ 395849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_ADD(acq_##name, type) \ 396849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_ADD(rel_##name, type) 397849aef49SAndrew Turner 398849aef49SAndrew Turner #define _CSAN_ATOMIC_FUNC_CLEAR(name, type) \ 399849aef49SAndrew Turner void kcsan_atomic_clear_##name(volatile type *ptr, type val) \ 4000cb53570SAndrew Turner { \ 401849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \ 4020cb53570SAndrew Turner __RET_ADDR); \ 403849aef49SAndrew Turner atomic_clear_##name(ptr, val); \ 4040cb53570SAndrew Turner } 4050cb53570SAndrew Turner 406849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_CLEAR(name, type) \ 407849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_CLEAR(name, type) \ 408849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_CLEAR(acq_##name, type) \ 409849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_CLEAR(rel_##name, type) 410849aef49SAndrew Turner 411849aef49SAndrew Turner #define _CSAN_ATOMIC_FUNC_CMPSET(name, type) \ 412849aef49SAndrew Turner int kcsan_atomic_cmpset_##name(volatile type *ptr, type val1, \ 413849aef49SAndrew Turner type val2) \ 4140cb53570SAndrew Turner { \ 415849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \ 4160cb53570SAndrew Turner __RET_ADDR); \ 417849aef49SAndrew Turner return (atomic_cmpset_##name(ptr, val1, val2)); \ 4180cb53570SAndrew Turner } 4190cb53570SAndrew Turner 420849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_CMPSET(name, type) \ 421849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_CMPSET(name, type) \ 422849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_CMPSET(acq_##name, type) \ 423849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_CMPSET(rel_##name, type) 424849aef49SAndrew Turner 425849aef49SAndrew Turner #define _CSAN_ATOMIC_FUNC_FCMPSET(name, type) \ 426849aef49SAndrew Turner int kcsan_atomic_fcmpset_##name(volatile type *ptr, type *val1, \ 427849aef49SAndrew Turner type val2) \ 4280cb53570SAndrew Turner { \ 429849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \ 4300cb53570SAndrew Turner __RET_ADDR); \ 431849aef49SAndrew Turner return (atomic_fcmpset_##name(ptr, val1, val2)); \ 4320cb53570SAndrew Turner } 4330cb53570SAndrew Turner 434849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_FCMPSET(name, type) \ 435849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_FCMPSET(name, type) \ 436849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_FCMPSET(acq_##name, type) \ 437849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_FCMPSET(rel_##name, type) 438849aef49SAndrew Turner 439849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_FETCHADD(name, type) \ 440849aef49SAndrew Turner type kcsan_atomic_fetchadd_##name(volatile type *ptr, type val) \ 4410cb53570SAndrew Turner { \ 442849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \ 4430cb53570SAndrew Turner __RET_ADDR); \ 444849aef49SAndrew Turner return (atomic_fetchadd_##name(ptr, val)); \ 4450cb53570SAndrew Turner } 4460cb53570SAndrew Turner 447849aef49SAndrew Turner #define _CSAN_ATOMIC_FUNC_LOAD(name, type) \ 448849aef49SAndrew Turner type kcsan_atomic_load_##name(volatile type *ptr) \ 4490cb53570SAndrew Turner { \ 450849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), false, true, \ 4510cb53570SAndrew Turner __RET_ADDR); \ 452849aef49SAndrew Turner return (atomic_load_##name(ptr)); \ 4530cb53570SAndrew Turner } 4540cb53570SAndrew Turner 455849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_LOAD(name, type) \ 456849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_LOAD(name, type) \ 457849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_LOAD(acq_##name, type) \ 458849aef49SAndrew Turner 459849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_READANDCLEAR(name, type) \ 460849aef49SAndrew Turner type kcsan_atomic_readandclear_##name(volatile type *ptr) \ 4610cb53570SAndrew Turner { \ 462849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \ 4630cb53570SAndrew Turner __RET_ADDR); \ 464849aef49SAndrew Turner return (atomic_readandclear_##name(ptr)); \ 4650cb53570SAndrew Turner } 4660cb53570SAndrew Turner 467849aef49SAndrew Turner #define _CSAN_ATOMIC_FUNC_SET(name, type) \ 468849aef49SAndrew Turner void kcsan_atomic_set_##name(volatile type *ptr, type val) \ 469849aef49SAndrew Turner { \ 470849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \ 471849aef49SAndrew Turner __RET_ADDR); \ 472849aef49SAndrew Turner atomic_set_##name(ptr, val); \ 473849aef49SAndrew Turner } 4740cb53570SAndrew Turner 475849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_SET(name, type) \ 476849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_SET(name, type) \ 477849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_SET(acq_##name, type) \ 478849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_SET(rel_##name, type) 4790cb53570SAndrew Turner 480849aef49SAndrew Turner #define _CSAN_ATOMIC_FUNC_SUBTRACT(name, type) \ 481849aef49SAndrew Turner void kcsan_atomic_subtract_##name(volatile type *ptr, type val) \ 482849aef49SAndrew Turner { \ 483849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \ 484849aef49SAndrew Turner __RET_ADDR); \ 485849aef49SAndrew Turner atomic_subtract_##name(ptr, val); \ 486849aef49SAndrew Turner } 4870cb53570SAndrew Turner 488849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_SUBTRACT(name, type) \ 489849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_SUBTRACT(name, type) \ 490849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_SUBTRACT(acq_##name, type) \ 491849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_SUBTRACT(rel_##name, type) 4920cb53570SAndrew Turner 493849aef49SAndrew Turner #define _CSAN_ATOMIC_FUNC_STORE(name, type) \ 494849aef49SAndrew Turner void kcsan_atomic_store_##name(volatile type *ptr, type val) \ 495849aef49SAndrew Turner { \ 496849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \ 497849aef49SAndrew Turner __RET_ADDR); \ 498849aef49SAndrew Turner atomic_store_##name(ptr, val); \ 499849aef49SAndrew Turner } 5000cb53570SAndrew Turner 501849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_STORE(name, type) \ 502849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_STORE(name, type) \ 503849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_STORE(rel_##name, type) 504849aef49SAndrew Turner 505849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_SWAP(name, type) \ 506849aef49SAndrew Turner type kcsan_atomic_swap_##name(volatile type *ptr, type val) \ 507849aef49SAndrew Turner { \ 508849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \ 509849aef49SAndrew Turner __RET_ADDR); \ 510849aef49SAndrew Turner return(atomic_swap_##name(ptr, val)); \ 511849aef49SAndrew Turner } 512849aef49SAndrew Turner 513849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_TESTANDCLEAR(name, type) \ 514849aef49SAndrew Turner int kcsan_atomic_testandclear_##name(volatile type *ptr, u_int val) \ 515849aef49SAndrew Turner { \ 516849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \ 517849aef49SAndrew Turner __RET_ADDR); \ 518849aef49SAndrew Turner return(atomic_testandclear_##name(ptr, val)); \ 519849aef49SAndrew Turner } 520849aef49SAndrew Turner 521849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_TESTANDSET(name, type) \ 522849aef49SAndrew Turner int kcsan_atomic_testandset_##name(volatile type *ptr, u_int val) \ 523849aef49SAndrew Turner { \ 524849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \ 525849aef49SAndrew Turner __RET_ADDR); \ 526849aef49SAndrew Turner return (atomic_testandset_##name(ptr, val)); \ 527849aef49SAndrew Turner } 528849aef49SAndrew Turner 529849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(8, uint8_t) 530849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(8, uint8_t) 531849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(8, uint8_t) 532849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(8, uint8_t) 533ca0ec73cSConrad Meyer CSAN_ATOMIC_FUNC_LOAD(8, uint8_t) 534849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(8, uint8_t) 535849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(8, uint8_t) 536849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_STORE(8, uint8_t) 537849aef49SAndrew Turner #if 0 538849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(8, uint8_t) 539849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(8, uint8_t) 540849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(8, uint8_t) 541849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(8, uint8_t) 542849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(8, uint8_t) 543849aef49SAndrew Turner #endif 544849aef49SAndrew Turner 545849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(16, uint16_t) 546849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(16, uint16_t) 547849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(16, uint16_t) 548849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(16, uint16_t) 549849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(16, uint16_t) 550849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(16, uint16_t) 551849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(16, uint16_t) 552849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_STORE(16, uint16_t) 553849aef49SAndrew Turner #if 0 554849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(16, uint16_t) 555849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(16, uint16_t) 556849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(16, uint16_t) 557849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(16, uint16_t) 558849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(16, uint16_t) 559849aef49SAndrew Turner #endif 560849aef49SAndrew Turner 561849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(32, uint32_t) 562849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(32, uint32_t) 563849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(32, uint32_t) 564849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(32, uint32_t) 565849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(32, uint32_t) 566849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(32, uint32_t) 567849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(32, uint32_t) 568849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(32, uint32_t) 569849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(32, uint32_t) 570849aef49SAndrew Turner CSAN_ATOMIC_FUNC_STORE(32, uint32_t) 571849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(32, uint32_t) 572849aef49SAndrew Turner #if !defined(__aarch64__) 573849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(32, uint32_t) 574849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(32, uint32_t) 575849aef49SAndrew Turner #endif 576849aef49SAndrew Turner 577849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(64, uint64_t) 578849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(64, uint64_t) 579849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(64, uint64_t) 580849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(64, uint64_t) 581849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(64, uint64_t) 582849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(64, uint64_t) 583849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(64, uint64_t) 584849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(64, uint64_t) 585849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(64, uint64_t) 586849aef49SAndrew Turner CSAN_ATOMIC_FUNC_STORE(64, uint64_t) 587849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(64, uint64_t) 588849aef49SAndrew Turner #if !defined(__aarch64__) 589849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(64, uint64_t) 590849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(64, uint64_t) 591849aef49SAndrew Turner #endif 592849aef49SAndrew Turner 593dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_ADD(char, uint8_t) 594dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_CLEAR(char, uint8_t) 595dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_CMPSET(char, uint8_t) 596dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_FCMPSET(char, uint8_t) 597dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_LOAD(char, uint8_t) 598dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_SET(char, uint8_t) 599dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_SUBTRACT(char, uint8_t) 600dc3c9915SMateusz Guzik _CSAN_ATOMIC_FUNC_STORE(char, uint8_t) 601dc3c9915SMateusz Guzik #if 0 602dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_FETCHADD(char, uint8_t) 603dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_READANDCLEAR(char, uint8_t) 604dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_SWAP(char, uint8_t) 605dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_TESTANDCLEAR(char, uint8_t) 606dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_TESTANDSET(char, uint8_t) 607dc3c9915SMateusz Guzik #endif 608dc3c9915SMateusz Guzik 609dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_ADD(short, uint16_t) 610dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_CLEAR(short, uint16_t) 611dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_CMPSET(short, uint16_t) 612dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_FCMPSET(short, uint16_t) 613dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_LOAD(short, uint16_t) 614dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_SET(short, uint16_t) 615dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_SUBTRACT(short, uint16_t) 616dc3c9915SMateusz Guzik _CSAN_ATOMIC_FUNC_STORE(short, uint16_t) 617dc3c9915SMateusz Guzik #if 0 618dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_FETCHADD(short, uint16_t) 619dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_READANDCLEAR(short, uint16_t) 620dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_SWAP(short, uint16_t) 621dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_TESTANDCLEAR(short, uint16_t) 622dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_TESTANDSET(short, uint16_t) 623dc3c9915SMateusz Guzik #endif 624dc3c9915SMateusz Guzik 625849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(int, u_int) 626849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(int, u_int) 627849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(int, u_int) 628849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(int, u_int) 629849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(int, u_int) 630849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(int, u_int) 631849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(int, u_int) 632849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(int, u_int) 633849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(int, u_int) 634849aef49SAndrew Turner CSAN_ATOMIC_FUNC_STORE(int, u_int) 635849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(int, u_int) 636849aef49SAndrew Turner #if !defined(__aarch64__) 637849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(int, u_int) 638849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(int, u_int) 639849aef49SAndrew Turner #endif 640849aef49SAndrew Turner 641849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(long, u_long) 642849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(long, u_long) 643849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(long, u_long) 644849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(long, u_long) 645849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(long, u_long) 646849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(long, u_long) 647849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(long, u_long) 648849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(long, u_long) 649849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(long, u_long) 650849aef49SAndrew Turner CSAN_ATOMIC_FUNC_STORE(long, u_long) 651849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(long, u_long) 652849aef49SAndrew Turner #if !defined(__aarch64__) 653849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(long, u_long) 654849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(long, u_long) 655ca0ec73cSConrad Meyer CSAN_ATOMIC_FUNC_TESTANDSET(acq_long, u_long) 656849aef49SAndrew Turner #endif 657849aef49SAndrew Turner 658849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(ptr, uintptr_t) 659849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(ptr, uintptr_t) 660849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(ptr, uintptr_t) 661849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(ptr, uintptr_t) 662849aef49SAndrew Turner #if !defined(__amd64__) 663849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(ptr, uintptr_t) 664849aef49SAndrew Turner #endif 665849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(ptr, uintptr_t) 666849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(ptr, uintptr_t) 667849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(ptr, uintptr_t) 668849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(ptr, uintptr_t) 669849aef49SAndrew Turner CSAN_ATOMIC_FUNC_STORE(ptr, uintptr_t) 670849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(ptr, uintptr_t) 671849aef49SAndrew Turner #if 0 672849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(ptr, uintptr_t) 673849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(ptr, uintptr_t) 674849aef49SAndrew Turner #endif 675849aef49SAndrew Turner 676849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_THREAD_FENCE(name) \ 677849aef49SAndrew Turner void kcsan_atomic_thread_fence_##name(void) \ 678849aef49SAndrew Turner { \ 679849aef49SAndrew Turner atomic_thread_fence_##name(); \ 680849aef49SAndrew Turner } 681849aef49SAndrew Turner 682849aef49SAndrew Turner CSAN_ATOMIC_FUNC_THREAD_FENCE(acq) 683849aef49SAndrew Turner CSAN_ATOMIC_FUNC_THREAD_FENCE(acq_rel) 684849aef49SAndrew Turner CSAN_ATOMIC_FUNC_THREAD_FENCE(rel) 685849aef49SAndrew Turner CSAN_ATOMIC_FUNC_THREAD_FENCE(seq_cst) 6860cb53570SAndrew Turner 6870cb53570SAndrew Turner /* -------------------------------------------------------------------------- */ 6880cb53570SAndrew Turner 6890cb53570SAndrew Turner #include <sys/bus.h> 690849aef49SAndrew Turner #include <machine/bus.h> 691849aef49SAndrew Turner #include <sys/_cscan_bus.h> 6920cb53570SAndrew Turner 693849aef49SAndrew Turner int 694849aef49SAndrew Turner kcsan_bus_space_map(bus_space_tag_t tag, bus_addr_t hnd, bus_size_t size, 695849aef49SAndrew Turner int flags, bus_space_handle_t *handlep) 696849aef49SAndrew Turner { 6970cb53570SAndrew Turner 698849aef49SAndrew Turner return (bus_space_map(tag, hnd, size, flags, handlep)); 6990cb53570SAndrew Turner } 7000cb53570SAndrew Turner 701849aef49SAndrew Turner void 702849aef49SAndrew Turner kcsan_bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t hnd, 703849aef49SAndrew Turner bus_size_t size) 704849aef49SAndrew Turner { 705849aef49SAndrew Turner 706849aef49SAndrew Turner bus_space_unmap(tag, hnd, size); 7070cb53570SAndrew Turner } 7080cb53570SAndrew Turner 709849aef49SAndrew Turner int 710849aef49SAndrew Turner kcsan_bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t hnd, 711849aef49SAndrew Turner bus_size_t offset, bus_size_t size, bus_space_handle_t *handlep) 712849aef49SAndrew Turner { 7130cb53570SAndrew Turner 714849aef49SAndrew Turner return (bus_space_subregion(tag, hnd, offset, size, handlep)); 715849aef49SAndrew Turner } 716849aef49SAndrew Turner 717849aef49SAndrew Turner #if !defined(__amd64__) 718849aef49SAndrew Turner int 719849aef49SAndrew Turner kcsan_bus_space_alloc(bus_space_tag_t tag, bus_addr_t reg_start, 720849aef49SAndrew Turner bus_addr_t reg_end, bus_size_t size, bus_size_t alignment, 721849aef49SAndrew Turner bus_size_t boundary, int flags, bus_addr_t *addrp, 722849aef49SAndrew Turner bus_space_handle_t *handlep) 723849aef49SAndrew Turner { 724849aef49SAndrew Turner 725849aef49SAndrew Turner return (bus_space_alloc(tag, reg_start, reg_end, size, alignment, 726849aef49SAndrew Turner boundary, flags, addrp, handlep)); 727849aef49SAndrew Turner } 728849aef49SAndrew Turner #endif 729849aef49SAndrew Turner 730849aef49SAndrew Turner void 731849aef49SAndrew Turner kcsan_bus_space_free(bus_space_tag_t tag, bus_space_handle_t hnd, 732849aef49SAndrew Turner bus_size_t size) 733849aef49SAndrew Turner { 734849aef49SAndrew Turner 735849aef49SAndrew Turner bus_space_free(tag, hnd, size); 736849aef49SAndrew Turner } 737849aef49SAndrew Turner 738849aef49SAndrew Turner void 739849aef49SAndrew Turner kcsan_bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t hnd, 740849aef49SAndrew Turner bus_size_t offset, bus_size_t size, int flags) 741849aef49SAndrew Turner { 742849aef49SAndrew Turner 743849aef49SAndrew Turner bus_space_barrier(tag, hnd, offset, size, flags); 744849aef49SAndrew Turner } 745849aef49SAndrew Turner 746849aef49SAndrew Turner #define CSAN_BUS_READ_FUNC(func, width, type) \ 747849aef49SAndrew Turner type kcsan_bus_space_read##func##_##width(bus_space_tag_t tag, \ 748849aef49SAndrew Turner bus_space_handle_t hnd, bus_size_t offset) \ 749849aef49SAndrew Turner { \ 750849aef49SAndrew Turner return (bus_space_read##func##_##width(tag, hnd, \ 751849aef49SAndrew Turner offset)); \ 752849aef49SAndrew Turner } \ 753849aef49SAndrew Turner 754849aef49SAndrew Turner #define CSAN_BUS_READ_PTR_FUNC(func, width, type) \ 755849aef49SAndrew Turner void kcsan_bus_space_read_##func##_##width(bus_space_tag_t tag, \ 756849aef49SAndrew Turner bus_space_handle_t hnd, bus_size_t size, type *buf, \ 757849aef49SAndrew Turner bus_size_t count) \ 758849aef49SAndrew Turner { \ 759849aef49SAndrew Turner kcsan_access((uintptr_t)buf, sizeof(type) * count, \ 760849aef49SAndrew Turner false, false, __RET_ADDR); \ 761849aef49SAndrew Turner bus_space_read_##func##_##width(tag, hnd, size, buf, \ 762849aef49SAndrew Turner count); \ 763849aef49SAndrew Turner } 764849aef49SAndrew Turner 765849aef49SAndrew Turner CSAN_BUS_READ_FUNC(, 1, uint8_t) 766849aef49SAndrew Turner CSAN_BUS_READ_FUNC(_stream, 1, uint8_t) 767849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi, 1, uint8_t) 768849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi_stream, 1, uint8_t) 769849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region, 1, uint8_t) 770849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region_stream, 1, uint8_t) 771849aef49SAndrew Turner 772849aef49SAndrew Turner CSAN_BUS_READ_FUNC(, 2, uint16_t) 773849aef49SAndrew Turner CSAN_BUS_READ_FUNC(_stream, 2, uint16_t) 774849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi, 2, uint16_t) 775849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi_stream, 2, uint16_t) 776849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region, 2, uint16_t) 777849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region_stream, 2, uint16_t) 778849aef49SAndrew Turner 779849aef49SAndrew Turner CSAN_BUS_READ_FUNC(, 4, uint32_t) 780849aef49SAndrew Turner CSAN_BUS_READ_FUNC(_stream, 4, uint32_t) 781849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi, 4, uint32_t) 782849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi_stream, 4, uint32_t) 783849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region, 4, uint32_t) 784849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region_stream, 4, uint32_t) 785849aef49SAndrew Turner 786849aef49SAndrew Turner CSAN_BUS_READ_FUNC(, 8, uint64_t) 787849aef49SAndrew Turner #if defined(__aarch64__) 788849aef49SAndrew Turner CSAN_BUS_READ_FUNC(_stream, 8, uint64_t) 789849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi, 8, uint64_t) 790849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi_stream, 8, uint64_t) 791849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region, 8, uint64_t) 792849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region_stream, 8, uint64_t) 793849aef49SAndrew Turner #endif 794849aef49SAndrew Turner 795849aef49SAndrew Turner #define CSAN_BUS_WRITE_FUNC(func, width, type) \ 796849aef49SAndrew Turner void kcsan_bus_space_write##func##_##width(bus_space_tag_t tag, \ 797849aef49SAndrew Turner bus_space_handle_t hnd, bus_size_t offset, type value) \ 798849aef49SAndrew Turner { \ 799849aef49SAndrew Turner bus_space_write##func##_##width(tag, hnd, offset, value); \ 800849aef49SAndrew Turner } \ 801849aef49SAndrew Turner 802849aef49SAndrew Turner #define CSAN_BUS_WRITE_PTR_FUNC(func, width, type) \ 803849aef49SAndrew Turner void kcsan_bus_space_write_##func##_##width(bus_space_tag_t tag, \ 804849aef49SAndrew Turner bus_space_handle_t hnd, bus_size_t size, const type *buf, \ 805849aef49SAndrew Turner bus_size_t count) \ 806849aef49SAndrew Turner { \ 807849aef49SAndrew Turner kcsan_access((uintptr_t)buf, sizeof(type) * count, \ 808849aef49SAndrew Turner true, false, __RET_ADDR); \ 809849aef49SAndrew Turner bus_space_write_##func##_##width(tag, hnd, size, buf, \ 810849aef49SAndrew Turner count); \ 811849aef49SAndrew Turner } 812849aef49SAndrew Turner 813849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(, 1, uint8_t) 814849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(_stream, 1, uint8_t) 815849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi, 1, uint8_t) 816849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 1, uint8_t) 817849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region, 1, uint8_t) 818849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region_stream, 1, uint8_t) 819849aef49SAndrew Turner 820849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(, 2, uint16_t) 821849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(_stream, 2, uint16_t) 822849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi, 2, uint16_t) 823849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 2, uint16_t) 824849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region, 2, uint16_t) 825849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region_stream, 2, uint16_t) 826849aef49SAndrew Turner 827849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(, 4, uint32_t) 828849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(_stream, 4, uint32_t) 829849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi, 4, uint32_t) 830849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 4, uint32_t) 831849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region, 4, uint32_t) 832849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region_stream, 4, uint32_t) 833849aef49SAndrew Turner 834849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(, 8, uint64_t) 835849aef49SAndrew Turner #if defined(__aarch64__) 836849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(_stream, 8, uint64_t) 837849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi, 8, uint64_t) 838849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 8, uint64_t) 839849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region, 8, uint64_t) 840849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region_stream, 8, uint64_t) 841849aef49SAndrew Turner #endif 842849aef49SAndrew Turner 843849aef49SAndrew Turner #define CSAN_BUS_SET_FUNC(func, width, type) \ 844849aef49SAndrew Turner void kcsan_bus_space_set_##func##_##width(bus_space_tag_t tag, \ 845849aef49SAndrew Turner bus_space_handle_t hnd, bus_size_t offset, type value, \ 846849aef49SAndrew Turner bus_size_t count) \ 847849aef49SAndrew Turner { \ 848849aef49SAndrew Turner bus_space_set_##func##_##width(tag, hnd, offset, value, \ 849849aef49SAndrew Turner count); \ 850849aef49SAndrew Turner } 851849aef49SAndrew Turner 852849aef49SAndrew Turner CSAN_BUS_SET_FUNC(multi, 1, uint8_t) 853849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region, 1, uint8_t) 854bba0065fSAndrew Turner #if !defined(__aarch64__) 855bba0065fSAndrew Turner CSAN_BUS_SET_FUNC(multi_stream, 1, uint8_t) 856849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region_stream, 1, uint8_t) 857bba0065fSAndrew Turner #endif 858849aef49SAndrew Turner 859849aef49SAndrew Turner CSAN_BUS_SET_FUNC(multi, 2, uint16_t) 860849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region, 2, uint16_t) 861bba0065fSAndrew Turner #if !defined(__aarch64__) 862bba0065fSAndrew Turner CSAN_BUS_SET_FUNC(multi_stream, 2, uint16_t) 863849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region_stream, 2, uint16_t) 864bba0065fSAndrew Turner #endif 865849aef49SAndrew Turner 866849aef49SAndrew Turner CSAN_BUS_SET_FUNC(multi, 4, uint32_t) 867849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region, 4, uint32_t) 868bba0065fSAndrew Turner #if !defined(__aarch64__) 869bba0065fSAndrew Turner CSAN_BUS_SET_FUNC(multi_stream, 4, uint32_t) 870849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region_stream, 4, uint32_t) 871bba0065fSAndrew Turner #endif 872849aef49SAndrew Turner 873849aef49SAndrew Turner #if !defined(__amd64__) 874849aef49SAndrew Turner CSAN_BUS_SET_FUNC(multi, 8, uint64_t) 875849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region, 8, uint64_t) 876bba0065fSAndrew Turner #if !defined(__aarch64__) 877bba0065fSAndrew Turner CSAN_BUS_SET_FUNC(multi_stream, 8, uint64_t) 878849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region_stream, 8, uint64_t) 879849aef49SAndrew Turner #endif 880bba0065fSAndrew Turner #endif 881*95a85c12SMichal Meloun 882*95a85c12SMichal Meloun #define CSAN_BUS_PEEK_FUNC(width, type) \ 883*95a85c12SMichal Meloun int kcsan_bus_space_peek_##width(bus_space_tag_t tag, \ 884*95a85c12SMichal Meloun bus_space_handle_t hnd, bus_size_t offset, type *value) \ 885*95a85c12SMichal Meloun { \ 886*95a85c12SMichal Meloun kcsan_access((uintptr_t)value, sizeof(type), true, false, \ 887*95a85c12SMichal Meloun __RET_ADDR); \ 888*95a85c12SMichal Meloun return (bus_space_peek_##width(tag, hnd, offset, value)); \ 889*95a85c12SMichal Meloun } 890*95a85c12SMichal Meloun 891*95a85c12SMichal Meloun CSAN_BUS_PEEK_FUNC(1, uint8_t) 892*95a85c12SMichal Meloun CSAN_BUS_PEEK_FUNC(2, uint16_t) 893*95a85c12SMichal Meloun CSAN_BUS_PEEK_FUNC(4, uint32_t) 894*95a85c12SMichal Meloun #if !defined(__i386__) 895*95a85c12SMichal Meloun CSAN_BUS_PEEK_FUNC(8, uint64_t) 896*95a85c12SMichal Meloun #endif 897*95a85c12SMichal Meloun 898*95a85c12SMichal Meloun #define CSAN_BUS_POKE_FUNC(width, type) \ 899*95a85c12SMichal Meloun int kcsan_bus_space_poke_##width(bus_space_tag_t tag, \ 900*95a85c12SMichal Meloun bus_space_handle_t hnd, bus_size_t offset, type value) \ 901*95a85c12SMichal Meloun { \ 902*95a85c12SMichal Meloun return (bus_space_poke_##width(tag, hnd, offset, value)); \ 903*95a85c12SMichal Meloun } 904*95a85c12SMichal Meloun 905*95a85c12SMichal Meloun CSAN_BUS_POKE_FUNC(1, uint8_t) 906*95a85c12SMichal Meloun CSAN_BUS_POKE_FUNC(2, uint16_t) 907*95a85c12SMichal Meloun CSAN_BUS_POKE_FUNC(4, uint32_t) 908*95a85c12SMichal Meloun #if !defined(__i386__) 909*95a85c12SMichal Meloun CSAN_BUS_POKE_FUNC(8, uint64_t) 910*95a85c12SMichal Meloun #endif 911