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
333ead6023SMark Johnston #define SAN_RUNTIME
34849aef49SAndrew Turner
35849aef49SAndrew Turner #include "opt_ddb.h"
36849aef49SAndrew Turner
370cb53570SAndrew Turner #include <sys/param.h>
380cb53570SAndrew Turner #include <sys/kernel.h>
39849aef49SAndrew Turner #include <sys/bus.h>
400cb53570SAndrew Turner #include <sys/conf.h>
410cb53570SAndrew Turner #include <sys/cpu.h>
42849aef49SAndrew Turner #include <sys/csan.h>
43849aef49SAndrew Turner #include <sys/proc.h>
44849aef49SAndrew Turner #include <sys/smp.h>
45849aef49SAndrew Turner #include <sys/systm.h>
46849aef49SAndrew Turner
47849aef49SAndrew Turner #include <ddb/ddb.h>
48849aef49SAndrew Turner #include <ddb/db_sym.h>
490cb53570SAndrew Turner
500cb53570SAndrew Turner #ifdef KCSAN_PANIC
510cb53570SAndrew Turner #define REPORT panic
520cb53570SAndrew Turner #else
530cb53570SAndrew Turner #define REPORT printf
540cb53570SAndrew Turner #endif
550cb53570SAndrew Turner
560cb53570SAndrew Turner typedef struct {
570cb53570SAndrew Turner uintptr_t addr;
580cb53570SAndrew Turner uint32_t size;
590cb53570SAndrew Turner bool write:1;
600cb53570SAndrew Turner bool atomic:1;
610cb53570SAndrew Turner uintptr_t pc;
620cb53570SAndrew Turner } csan_cell_t;
630cb53570SAndrew Turner
640cb53570SAndrew Turner typedef struct {
650cb53570SAndrew Turner bool inited;
660cb53570SAndrew Turner uint32_t cnt;
670cb53570SAndrew Turner csan_cell_t cell;
680cb53570SAndrew Turner } csan_cpu_t;
690cb53570SAndrew Turner
70849aef49SAndrew Turner static csan_cpu_t kcsan_cpus[MAXCPU];
710cb53570SAndrew Turner static bool kcsan_enabled __read_mostly;
720cb53570SAndrew Turner
730cb53570SAndrew Turner #define __RET_ADDR (uintptr_t)__builtin_return_address(0)
740cb53570SAndrew Turner
750cb53570SAndrew Turner #define KCSAN_NACCESSES 1024
760cb53570SAndrew Turner #define KCSAN_DELAY 10 /* 10 microseconds */
770cb53570SAndrew Turner
780cb53570SAndrew Turner /* -------------------------------------------------------------------------- */
790cb53570SAndrew Turner
800cb53570SAndrew Turner /* The MD code. */
810cb53570SAndrew Turner #include <machine/csan.h>
820cb53570SAndrew Turner
830cb53570SAndrew Turner /* -------------------------------------------------------------------------- */
840cb53570SAndrew Turner
85849aef49SAndrew Turner static void
kcsan_enable(void * dummy __unused)86849aef49SAndrew Turner kcsan_enable(void *dummy __unused)
870cb53570SAndrew Turner {
88849aef49SAndrew Turner
89849aef49SAndrew Turner printf("Enabling KCSCAN, expect reduced performance.\n");
900cb53570SAndrew Turner kcsan_enabled = true;
910cb53570SAndrew Turner }
92849aef49SAndrew Turner SYSINIT(kcsan_enable, SI_SUB_SMP, SI_ORDER_SECOND, kcsan_enable, NULL);
930cb53570SAndrew Turner
940cb53570SAndrew Turner void
kcsan_cpu_init(u_int cpu)95849aef49SAndrew Turner kcsan_cpu_init(u_int cpu)
960cb53570SAndrew Turner {
97849aef49SAndrew Turner kcsan_cpus[cpu].inited = true;
980cb53570SAndrew Turner }
990cb53570SAndrew Turner
1000cb53570SAndrew Turner /* -------------------------------------------------------------------------- */
1010cb53570SAndrew Turner
1020cb53570SAndrew Turner static inline void
kcsan_report(csan_cell_t * new,u_int newcpu,csan_cell_t * old,u_int oldcpu)103849aef49SAndrew Turner kcsan_report(csan_cell_t *new, u_int newcpu, csan_cell_t *old, u_int oldcpu)
1040cb53570SAndrew Turner {
1050cb53570SAndrew Turner const char *newsym, *oldsym;
106849aef49SAndrew Turner #ifdef DDB
107849aef49SAndrew Turner c_db_sym_t sym;
108849aef49SAndrew Turner db_expr_t offset;
1090cb53570SAndrew Turner
110849aef49SAndrew Turner sym = db_search_symbol((vm_offset_t)new->pc, DB_STGY_PROC, &offset);
111849aef49SAndrew Turner db_symbol_values(sym, &newsym, NULL);
112849aef49SAndrew Turner
113849aef49SAndrew Turner sym = db_search_symbol((vm_offset_t)old->pc, DB_STGY_PROC, &offset);
114849aef49SAndrew Turner db_symbol_values(sym, &oldsym, NULL);
115849aef49SAndrew Turner #else
116849aef49SAndrew Turner newsym = "";
117849aef49SAndrew Turner oldsym = "";
118849aef49SAndrew Turner #endif
1190cb53570SAndrew Turner REPORT("CSan: Racy Access "
120849aef49SAndrew Turner "[Cpu%u %s%s Addr=%p Size=%u PC=%p<%s>] "
121849aef49SAndrew Turner "[Cpu%u %s%s Addr=%p Size=%u PC=%p<%s>]\n",
1220cb53570SAndrew Turner newcpu,
1230cb53570SAndrew Turner (new->atomic ? "Atomic " : ""), (new->write ? "Write" : "Read"),
1240cb53570SAndrew Turner (void *)new->addr, new->size, (void *)new->pc, newsym,
1250cb53570SAndrew Turner oldcpu,
1260cb53570SAndrew Turner (old->atomic ? "Atomic " : ""), (old->write ? "Write" : "Read"),
1270cb53570SAndrew Turner (void *)old->addr, old->size, (void *)old->pc, oldsym);
1280cb53570SAndrew Turner kcsan_md_unwind();
1290cb53570SAndrew Turner }
1300cb53570SAndrew Turner
1310cb53570SAndrew Turner static inline bool
kcsan_access_is_atomic(csan_cell_t * new,csan_cell_t * old)1320cb53570SAndrew Turner kcsan_access_is_atomic(csan_cell_t *new, csan_cell_t *old)
1330cb53570SAndrew Turner {
1340cb53570SAndrew Turner if (new->write && !new->atomic)
1350cb53570SAndrew Turner return false;
1360cb53570SAndrew Turner if (old->write && !old->atomic)
1370cb53570SAndrew Turner return false;
1380cb53570SAndrew Turner return true;
1390cb53570SAndrew Turner }
1400cb53570SAndrew Turner
1410cb53570SAndrew Turner static inline void
kcsan_access(uintptr_t addr,size_t size,bool write,bool atomic,uintptr_t pc)1420cb53570SAndrew Turner kcsan_access(uintptr_t addr, size_t size, bool write, bool atomic, uintptr_t pc)
1430cb53570SAndrew Turner {
1440cb53570SAndrew Turner csan_cell_t old, new;
1450cb53570SAndrew Turner csan_cpu_t *cpu;
1460cb53570SAndrew Turner uint64_t intr;
1470cb53570SAndrew Turner size_t i;
1480cb53570SAndrew Turner
1490cb53570SAndrew Turner if (__predict_false(!kcsan_enabled))
1500cb53570SAndrew Turner return;
15168cad681SAndrew Turner if (__predict_false(kcsan_md_unsupported((vm_offset_t)addr)))
15268cad681SAndrew Turner return;
153879e0604SMateusz Guzik if (KERNEL_PANICKED())
154a27ac464SAndrew Turner return;
1550cb53570SAndrew Turner
1560cb53570SAndrew Turner new.addr = addr;
1570cb53570SAndrew Turner new.size = size;
1580cb53570SAndrew Turner new.write = write;
1590cb53570SAndrew Turner new.atomic = atomic;
1600cb53570SAndrew Turner new.pc = pc;
1610cb53570SAndrew Turner
162849aef49SAndrew Turner CPU_FOREACH(i) {
1630cb53570SAndrew Turner __builtin_memcpy(&old, &kcsan_cpus[i].cell, sizeof(old));
1640cb53570SAndrew Turner
1650cb53570SAndrew Turner if (old.addr + old.size <= new.addr)
1660cb53570SAndrew Turner continue;
1670cb53570SAndrew Turner if (new.addr + new.size <= old.addr)
1680cb53570SAndrew Turner continue;
1690cb53570SAndrew Turner if (__predict_true(!old.write && !new.write))
1700cb53570SAndrew Turner continue;
1710cb53570SAndrew Turner if (__predict_true(kcsan_access_is_atomic(&new, &old)))
1720cb53570SAndrew Turner continue;
1730cb53570SAndrew Turner
174849aef49SAndrew Turner kcsan_report(&new, PCPU_GET(cpuid), &old, i);
1750cb53570SAndrew Turner break;
1760cb53570SAndrew Turner }
1770cb53570SAndrew Turner
1780cb53570SAndrew Turner if (__predict_false(!kcsan_md_is_avail()))
1790cb53570SAndrew Turner return;
1800cb53570SAndrew Turner
1810cb53570SAndrew Turner kcsan_md_disable_intrs(&intr);
1820cb53570SAndrew Turner
183849aef49SAndrew Turner cpu = &kcsan_cpus[PCPU_GET(cpuid)];
1840cb53570SAndrew Turner if (__predict_false(!cpu->inited))
1850cb53570SAndrew Turner goto out;
1860cb53570SAndrew Turner cpu->cnt = (cpu->cnt + 1) % KCSAN_NACCESSES;
1870cb53570SAndrew Turner if (__predict_true(cpu->cnt != 0))
1880cb53570SAndrew Turner goto out;
1890cb53570SAndrew Turner
1900cb53570SAndrew Turner __builtin_memcpy(&cpu->cell, &new, sizeof(new));
1910cb53570SAndrew Turner kcsan_md_delay(KCSAN_DELAY);
1920cb53570SAndrew Turner __builtin_memset(&cpu->cell, 0, sizeof(new));
1930cb53570SAndrew Turner
1940cb53570SAndrew Turner out:
1950cb53570SAndrew Turner kcsan_md_enable_intrs(&intr);
1960cb53570SAndrew Turner }
1970cb53570SAndrew Turner
1980cb53570SAndrew Turner #define CSAN_READ(size) \
1990cb53570SAndrew Turner void __tsan_read##size(uintptr_t); \
2000cb53570SAndrew Turner void __tsan_read##size(uintptr_t addr) \
2010cb53570SAndrew Turner { \
2020cb53570SAndrew Turner kcsan_access(addr, size, false, false, __RET_ADDR); \
203849aef49SAndrew Turner } \
204849aef49SAndrew Turner void __tsan_unaligned_read##size(uintptr_t); \
205849aef49SAndrew Turner void __tsan_unaligned_read##size(uintptr_t addr) \
206849aef49SAndrew Turner { \
207849aef49SAndrew Turner kcsan_access(addr, size, false, false, __RET_ADDR); \
2080cb53570SAndrew Turner }
2090cb53570SAndrew Turner
2100cb53570SAndrew Turner CSAN_READ(1)
2110cb53570SAndrew Turner CSAN_READ(2)
2120cb53570SAndrew Turner CSAN_READ(4)
2130cb53570SAndrew Turner CSAN_READ(8)
2140cb53570SAndrew Turner CSAN_READ(16)
2150cb53570SAndrew Turner
2160cb53570SAndrew Turner #define CSAN_WRITE(size) \
2170cb53570SAndrew Turner void __tsan_write##size(uintptr_t); \
2180cb53570SAndrew Turner void __tsan_write##size(uintptr_t addr) \
2190cb53570SAndrew Turner { \
2200cb53570SAndrew Turner kcsan_access(addr, size, true, false, __RET_ADDR); \
221849aef49SAndrew Turner } \
222849aef49SAndrew Turner void __tsan_unaligned_write##size(uintptr_t); \
223849aef49SAndrew Turner void __tsan_unaligned_write##size(uintptr_t addr) \
224849aef49SAndrew Turner { \
225849aef49SAndrew Turner kcsan_access(addr, size, true, false, __RET_ADDR); \
2260cb53570SAndrew Turner }
2270cb53570SAndrew Turner
2280cb53570SAndrew Turner CSAN_WRITE(1)
2290cb53570SAndrew Turner CSAN_WRITE(2)
2300cb53570SAndrew Turner CSAN_WRITE(4)
2310cb53570SAndrew Turner CSAN_WRITE(8)
2320cb53570SAndrew Turner CSAN_WRITE(16)
2330cb53570SAndrew Turner
2340cb53570SAndrew Turner void __tsan_read_range(uintptr_t, size_t);
2350cb53570SAndrew Turner void __tsan_write_range(uintptr_t, size_t);
2360cb53570SAndrew Turner
2370cb53570SAndrew Turner void
__tsan_read_range(uintptr_t addr,size_t size)2380cb53570SAndrew Turner __tsan_read_range(uintptr_t addr, size_t size)
2390cb53570SAndrew Turner {
2400cb53570SAndrew Turner kcsan_access(addr, size, false, false, __RET_ADDR);
2410cb53570SAndrew Turner }
2420cb53570SAndrew Turner
2430cb53570SAndrew Turner void
__tsan_write_range(uintptr_t addr,size_t size)2440cb53570SAndrew Turner __tsan_write_range(uintptr_t addr, size_t size)
2450cb53570SAndrew Turner {
2460cb53570SAndrew Turner kcsan_access(addr, size, true, false, __RET_ADDR);
2470cb53570SAndrew Turner }
2480cb53570SAndrew Turner
2490cb53570SAndrew Turner void __tsan_init(void);
2500cb53570SAndrew Turner void __tsan_func_entry(void *);
2510cb53570SAndrew Turner void __tsan_func_exit(void);
2520cb53570SAndrew Turner
2530cb53570SAndrew Turner void
__tsan_init(void)2540cb53570SAndrew Turner __tsan_init(void)
2550cb53570SAndrew Turner {
2560cb53570SAndrew Turner }
2570cb53570SAndrew Turner
2580cb53570SAndrew Turner void
__tsan_func_entry(void * call_pc)2590cb53570SAndrew Turner __tsan_func_entry(void *call_pc)
2600cb53570SAndrew Turner {
2610cb53570SAndrew Turner }
2620cb53570SAndrew Turner
2630cb53570SAndrew Turner void
__tsan_func_exit(void)2640cb53570SAndrew Turner __tsan_func_exit(void)
2650cb53570SAndrew Turner {
2660cb53570SAndrew Turner }
2670cb53570SAndrew Turner
2680cb53570SAndrew Turner /* -------------------------------------------------------------------------- */
2690cb53570SAndrew Turner
2700cb53570SAndrew Turner void *
kcsan_memcpy(void * dst,const void * src,size_t len)2710cb53570SAndrew Turner kcsan_memcpy(void *dst, const void *src, size_t len)
2720cb53570SAndrew Turner {
2730cb53570SAndrew Turner kcsan_access((uintptr_t)src, len, false, false, __RET_ADDR);
2740cb53570SAndrew Turner kcsan_access((uintptr_t)dst, len, true, false, __RET_ADDR);
2750cb53570SAndrew Turner return __builtin_memcpy(dst, src, len);
2760cb53570SAndrew Turner }
2770cb53570SAndrew Turner
2780cb53570SAndrew Turner int
kcsan_memcmp(const void * b1,const void * b2,size_t len)2790cb53570SAndrew Turner kcsan_memcmp(const void *b1, const void *b2, size_t len)
2800cb53570SAndrew Turner {
2810cb53570SAndrew Turner kcsan_access((uintptr_t)b1, len, false, false, __RET_ADDR);
2820cb53570SAndrew Turner kcsan_access((uintptr_t)b2, len, false, false, __RET_ADDR);
2830cb53570SAndrew Turner return __builtin_memcmp(b1, b2, len);
2840cb53570SAndrew Turner }
2850cb53570SAndrew Turner
2860cb53570SAndrew Turner void *
kcsan_memset(void * b,int c,size_t len)2870cb53570SAndrew Turner kcsan_memset(void *b, int c, size_t len)
2880cb53570SAndrew Turner {
2890cb53570SAndrew Turner kcsan_access((uintptr_t)b, len, true, false, __RET_ADDR);
2900cb53570SAndrew Turner return __builtin_memset(b, c, len);
2910cb53570SAndrew Turner }
2920cb53570SAndrew Turner
2930cb53570SAndrew Turner void *
kcsan_memmove(void * dst,const void * src,size_t len)2940cb53570SAndrew Turner kcsan_memmove(void *dst, const void *src, size_t len)
2950cb53570SAndrew Turner {
2960cb53570SAndrew Turner kcsan_access((uintptr_t)src, len, false, false, __RET_ADDR);
2970cb53570SAndrew Turner kcsan_access((uintptr_t)dst, len, true, false, __RET_ADDR);
2980cb53570SAndrew Turner return __builtin_memmove(dst, src, len);
2990cb53570SAndrew Turner }
3000cb53570SAndrew Turner
30142162fb2SDimitry Andric __strong_reference(kcsan_memcpy, __tsan_memcpy);
30242162fb2SDimitry Andric __strong_reference(kcsan_memset, __tsan_memset);
30342162fb2SDimitry Andric __strong_reference(kcsan_memmove, __tsan_memmove);
30442162fb2SDimitry Andric
3050cb53570SAndrew Turner char *
kcsan_strcpy(char * dst,const char * src)3060cb53570SAndrew Turner kcsan_strcpy(char *dst, const char *src)
3070cb53570SAndrew Turner {
3080cb53570SAndrew Turner char *save = dst;
3090cb53570SAndrew Turner
3100cb53570SAndrew Turner while (1) {
3110cb53570SAndrew Turner kcsan_access((uintptr_t)src, 1, false, false, __RET_ADDR);
3120cb53570SAndrew Turner kcsan_access((uintptr_t)dst, 1, true, false, __RET_ADDR);
3130cb53570SAndrew Turner *dst = *src;
3140cb53570SAndrew Turner if (*src == '\0')
3150cb53570SAndrew Turner break;
3160cb53570SAndrew Turner src++, dst++;
3170cb53570SAndrew Turner }
3180cb53570SAndrew Turner
3190cb53570SAndrew Turner return save;
3200cb53570SAndrew Turner }
3210cb53570SAndrew Turner
3220cb53570SAndrew Turner int
kcsan_strcmp(const char * s1,const char * s2)3230cb53570SAndrew Turner kcsan_strcmp(const char *s1, const char *s2)
3240cb53570SAndrew Turner {
3250cb53570SAndrew Turner while (1) {
3260cb53570SAndrew Turner kcsan_access((uintptr_t)s1, 1, false, false, __RET_ADDR);
3270cb53570SAndrew Turner kcsan_access((uintptr_t)s2, 1, false, false, __RET_ADDR);
3280cb53570SAndrew Turner if (*s1 != *s2)
3290cb53570SAndrew Turner break;
3300cb53570SAndrew Turner if (*s1 == '\0')
3310cb53570SAndrew Turner return 0;
3320cb53570SAndrew Turner s1++, s2++;
3330cb53570SAndrew Turner }
3340cb53570SAndrew Turner
3350cb53570SAndrew Turner return (*(const unsigned char *)s1 - *(const unsigned char *)s2);
3360cb53570SAndrew Turner }
3370cb53570SAndrew Turner
3380cb53570SAndrew Turner size_t
kcsan_strlen(const char * str)3390cb53570SAndrew Turner kcsan_strlen(const char *str)
3400cb53570SAndrew Turner {
3410cb53570SAndrew Turner const char *s;
3420cb53570SAndrew Turner
3430cb53570SAndrew Turner s = str;
3440cb53570SAndrew Turner while (1) {
3450cb53570SAndrew Turner kcsan_access((uintptr_t)s, 1, false, false, __RET_ADDR);
3460cb53570SAndrew Turner if (*s == '\0')
3470cb53570SAndrew Turner break;
3480cb53570SAndrew Turner s++;
3490cb53570SAndrew Turner }
3500cb53570SAndrew Turner
3510cb53570SAndrew Turner return (s - str);
3520cb53570SAndrew Turner }
3530cb53570SAndrew Turner
3540cb53570SAndrew Turner int
kcsan_copyin(const void * uaddr,void * kaddr,size_t len)3550cb53570SAndrew Turner kcsan_copyin(const void *uaddr, void *kaddr, size_t len)
3560cb53570SAndrew Turner {
3570cb53570SAndrew Turner kcsan_access((uintptr_t)kaddr, len, true, false, __RET_ADDR);
3580cb53570SAndrew Turner return copyin(uaddr, kaddr, len);
3590cb53570SAndrew Turner }
3600cb53570SAndrew Turner
3610cb53570SAndrew Turner int
kcsan_copyinstr(const void * uaddr,void * kaddr,size_t len,size_t * done)3620cb53570SAndrew Turner kcsan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
3630cb53570SAndrew Turner {
3640cb53570SAndrew Turner kcsan_access((uintptr_t)kaddr, len, true, false, __RET_ADDR);
3650cb53570SAndrew Turner return copyinstr(uaddr, kaddr, len, done);
3660cb53570SAndrew Turner }
3670cb53570SAndrew Turner
3680cb53570SAndrew Turner int
kcsan_copyout(const void * kaddr,void * uaddr,size_t len)369849aef49SAndrew Turner kcsan_copyout(const void *kaddr, void *uaddr, size_t len)
3700cb53570SAndrew Turner {
3710cb53570SAndrew Turner kcsan_access((uintptr_t)kaddr, len, false, false, __RET_ADDR);
372849aef49SAndrew Turner return copyout(kaddr, uaddr, len);
3730cb53570SAndrew Turner }
3740cb53570SAndrew Turner
3750cb53570SAndrew Turner /* -------------------------------------------------------------------------- */
3760cb53570SAndrew Turner
377849aef49SAndrew Turner #include <machine/atomic.h>
378435c7cfbSMark Johnston #include <sys/atomic_san.h>
3790cb53570SAndrew Turner
380849aef49SAndrew Turner #define _CSAN_ATOMIC_FUNC_ADD(name, type) \
381849aef49SAndrew Turner void kcsan_atomic_add_##name(volatile type *ptr, type val) \
3820cb53570SAndrew Turner { \
383849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \
3840cb53570SAndrew Turner __RET_ADDR); \
3850cb53570SAndrew Turner atomic_add_##name(ptr, val); \
3860cb53570SAndrew Turner }
3870cb53570SAndrew Turner
388849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_ADD(name, type) \
389849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_ADD(name, type) \
390849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_ADD(acq_##name, type) \
391849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_ADD(rel_##name, type)
392849aef49SAndrew Turner
393849aef49SAndrew Turner #define _CSAN_ATOMIC_FUNC_CLEAR(name, type) \
394849aef49SAndrew Turner void kcsan_atomic_clear_##name(volatile type *ptr, type val) \
3950cb53570SAndrew Turner { \
396849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \
3970cb53570SAndrew Turner __RET_ADDR); \
398849aef49SAndrew Turner atomic_clear_##name(ptr, val); \
3990cb53570SAndrew Turner }
4000cb53570SAndrew Turner
401849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_CLEAR(name, type) \
402849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_CLEAR(name, type) \
403849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_CLEAR(acq_##name, type) \
404849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_CLEAR(rel_##name, type)
405849aef49SAndrew Turner
406849aef49SAndrew Turner #define _CSAN_ATOMIC_FUNC_CMPSET(name, type) \
407849aef49SAndrew Turner int kcsan_atomic_cmpset_##name(volatile type *ptr, type val1, \
408849aef49SAndrew Turner type val2) \
4090cb53570SAndrew Turner { \
410849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \
4110cb53570SAndrew Turner __RET_ADDR); \
412849aef49SAndrew Turner return (atomic_cmpset_##name(ptr, val1, val2)); \
4130cb53570SAndrew Turner }
4140cb53570SAndrew Turner
415849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_CMPSET(name, type) \
416849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_CMPSET(name, type) \
417849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_CMPSET(acq_##name, type) \
418849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_CMPSET(rel_##name, type)
419849aef49SAndrew Turner
420849aef49SAndrew Turner #define _CSAN_ATOMIC_FUNC_FCMPSET(name, type) \
421849aef49SAndrew Turner int kcsan_atomic_fcmpset_##name(volatile type *ptr, type *val1, \
422849aef49SAndrew Turner type val2) \
4230cb53570SAndrew Turner { \
424849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \
4250cb53570SAndrew Turner __RET_ADDR); \
426849aef49SAndrew Turner return (atomic_fcmpset_##name(ptr, val1, val2)); \
4270cb53570SAndrew Turner }
4280cb53570SAndrew Turner
429849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_FCMPSET(name, type) \
430849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_FCMPSET(name, type) \
431849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_FCMPSET(acq_##name, type) \
432849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_FCMPSET(rel_##name, type)
433849aef49SAndrew Turner
434849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_FETCHADD(name, type) \
435849aef49SAndrew Turner type kcsan_atomic_fetchadd_##name(volatile type *ptr, type val) \
4360cb53570SAndrew Turner { \
437849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \
4380cb53570SAndrew Turner __RET_ADDR); \
439849aef49SAndrew Turner return (atomic_fetchadd_##name(ptr, val)); \
4400cb53570SAndrew Turner }
4410cb53570SAndrew Turner
442849aef49SAndrew Turner #define _CSAN_ATOMIC_FUNC_LOAD(name, type) \
443*fa5f4c10SMark Johnston type kcsan_atomic_load_##name(const volatile type *ptr) \
4440cb53570SAndrew Turner { \
445849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), false, true, \
4460cb53570SAndrew Turner __RET_ADDR); \
447849aef49SAndrew Turner return (atomic_load_##name(ptr)); \
4480cb53570SAndrew Turner }
4490cb53570SAndrew Turner
450849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_LOAD(name, type) \
451849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_LOAD(name, type) \
452849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_LOAD(acq_##name, type) \
453849aef49SAndrew Turner
454849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_READANDCLEAR(name, type) \
455849aef49SAndrew Turner type kcsan_atomic_readandclear_##name(volatile type *ptr) \
4560cb53570SAndrew Turner { \
457849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \
4580cb53570SAndrew Turner __RET_ADDR); \
459849aef49SAndrew Turner return (atomic_readandclear_##name(ptr)); \
4600cb53570SAndrew Turner }
4610cb53570SAndrew Turner
462849aef49SAndrew Turner #define _CSAN_ATOMIC_FUNC_SET(name, type) \
463849aef49SAndrew Turner void kcsan_atomic_set_##name(volatile type *ptr, type val) \
464849aef49SAndrew Turner { \
465849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \
466849aef49SAndrew Turner __RET_ADDR); \
467849aef49SAndrew Turner atomic_set_##name(ptr, val); \
468849aef49SAndrew Turner }
4690cb53570SAndrew Turner
470849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_SET(name, type) \
471849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_SET(name, type) \
472849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_SET(acq_##name, type) \
473849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_SET(rel_##name, type)
4740cb53570SAndrew Turner
475849aef49SAndrew Turner #define _CSAN_ATOMIC_FUNC_SUBTRACT(name, type) \
476849aef49SAndrew Turner void kcsan_atomic_subtract_##name(volatile type *ptr, type val) \
477849aef49SAndrew Turner { \
478849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \
479849aef49SAndrew Turner __RET_ADDR); \
480849aef49SAndrew Turner atomic_subtract_##name(ptr, val); \
481849aef49SAndrew Turner }
4820cb53570SAndrew Turner
483849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_SUBTRACT(name, type) \
484849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_SUBTRACT(name, type) \
485849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_SUBTRACT(acq_##name, type) \
486849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_SUBTRACT(rel_##name, type)
4870cb53570SAndrew Turner
488849aef49SAndrew Turner #define _CSAN_ATOMIC_FUNC_STORE(name, type) \
489849aef49SAndrew Turner void kcsan_atomic_store_##name(volatile type *ptr, type val) \
490849aef49SAndrew Turner { \
491849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \
492849aef49SAndrew Turner __RET_ADDR); \
493849aef49SAndrew Turner atomic_store_##name(ptr, val); \
494849aef49SAndrew Turner }
4950cb53570SAndrew Turner
496849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_STORE(name, type) \
497849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_STORE(name, type) \
498849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_STORE(rel_##name, type)
499849aef49SAndrew Turner
500849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_SWAP(name, type) \
501849aef49SAndrew Turner type kcsan_atomic_swap_##name(volatile type *ptr, type val) \
502849aef49SAndrew Turner { \
503849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \
504849aef49SAndrew Turner __RET_ADDR); \
505849aef49SAndrew Turner return(atomic_swap_##name(ptr, val)); \
506849aef49SAndrew Turner }
507849aef49SAndrew Turner
508849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_TESTANDCLEAR(name, type) \
509849aef49SAndrew Turner int kcsan_atomic_testandclear_##name(volatile type *ptr, u_int val) \
510849aef49SAndrew Turner { \
511849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \
512849aef49SAndrew Turner __RET_ADDR); \
513849aef49SAndrew Turner return(atomic_testandclear_##name(ptr, val)); \
514849aef49SAndrew Turner }
515849aef49SAndrew Turner
516849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_TESTANDSET(name, type) \
517849aef49SAndrew Turner int kcsan_atomic_testandset_##name(volatile type *ptr, u_int val) \
518849aef49SAndrew Turner { \
519849aef49SAndrew Turner kcsan_access((uintptr_t)ptr, sizeof(type), true, true, \
520849aef49SAndrew Turner __RET_ADDR); \
521849aef49SAndrew Turner return (atomic_testandset_##name(ptr, val)); \
522849aef49SAndrew Turner }
523849aef49SAndrew Turner
_CSAN_ATOMIC_FUNC_LOAD(bool,bool)5241f6b6cf1SMark Johnston _CSAN_ATOMIC_FUNC_LOAD(bool, bool)
5251f6b6cf1SMark Johnston _CSAN_ATOMIC_FUNC_STORE(bool, bool)
5261f6b6cf1SMark Johnston
527849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(8, uint8_t)
528849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(8, uint8_t)
529849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(8, uint8_t)
530849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(8, uint8_t)
531ca0ec73cSConrad Meyer CSAN_ATOMIC_FUNC_LOAD(8, uint8_t)
532849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(8, uint8_t)
533849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(8, uint8_t)
534849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_STORE(8, uint8_t)
535849aef49SAndrew Turner #if 0
536849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(8, uint8_t)
537849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(8, uint8_t)
538849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(8, uint8_t)
539849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(8, uint8_t)
540849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(8, uint8_t)
541849aef49SAndrew Turner #endif
542849aef49SAndrew Turner
543849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(16, uint16_t)
544849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(16, uint16_t)
545849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(16, uint16_t)
546849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(16, uint16_t)
547849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(16, uint16_t)
548849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(16, uint16_t)
549849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(16, uint16_t)
550849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_STORE(16, uint16_t)
551849aef49SAndrew Turner #if 0
552849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(16, uint16_t)
553849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(16, uint16_t)
554849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(16, uint16_t)
555849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(16, uint16_t)
556849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(16, uint16_t)
557849aef49SAndrew Turner #endif
558849aef49SAndrew Turner
559849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(32, uint32_t)
560849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(32, uint32_t)
561849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(32, uint32_t)
562849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(32, uint32_t)
563849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(32, uint32_t)
564849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(32, uint32_t)
565849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(32, uint32_t)
566849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(32, uint32_t)
567849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(32, uint32_t)
568849aef49SAndrew Turner CSAN_ATOMIC_FUNC_STORE(32, uint32_t)
569849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(32, uint32_t)
570849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(32, uint32_t)
571849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(32, uint32_t)
572849aef49SAndrew Turner
573849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(64, uint64_t)
574849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(64, uint64_t)
575849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(64, uint64_t)
576849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(64, uint64_t)
577849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(64, uint64_t)
578849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(64, uint64_t)
579849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(64, uint64_t)
580849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(64, uint64_t)
581849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(64, uint64_t)
582849aef49SAndrew Turner CSAN_ATOMIC_FUNC_STORE(64, uint64_t)
583849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(64, uint64_t)
584849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(64, uint64_t)
585849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(64, uint64_t)
586849aef49SAndrew Turner
587dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_ADD(char, uint8_t)
588dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_CLEAR(char, uint8_t)
589dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_CMPSET(char, uint8_t)
590dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_FCMPSET(char, uint8_t)
591dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_LOAD(char, uint8_t)
592dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_SET(char, uint8_t)
593dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_SUBTRACT(char, uint8_t)
594dc3c9915SMateusz Guzik _CSAN_ATOMIC_FUNC_STORE(char, uint8_t)
595dc3c9915SMateusz Guzik #if 0
596dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_FETCHADD(char, uint8_t)
597dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_READANDCLEAR(char, uint8_t)
598dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_SWAP(char, uint8_t)
599dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_TESTANDCLEAR(char, uint8_t)
600dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_TESTANDSET(char, uint8_t)
601dc3c9915SMateusz Guzik #endif
602dc3c9915SMateusz Guzik
603dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_ADD(short, uint16_t)
604dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_CLEAR(short, uint16_t)
605dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_CMPSET(short, uint16_t)
606dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_FCMPSET(short, uint16_t)
607dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_LOAD(short, uint16_t)
608dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_SET(short, uint16_t)
609dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_SUBTRACT(short, uint16_t)
610dc3c9915SMateusz Guzik _CSAN_ATOMIC_FUNC_STORE(short, uint16_t)
611dc3c9915SMateusz Guzik #if 0
612dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_FETCHADD(short, uint16_t)
613dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_READANDCLEAR(short, uint16_t)
614dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_SWAP(short, uint16_t)
615dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_TESTANDCLEAR(short, uint16_t)
616dc3c9915SMateusz Guzik CSAN_ATOMIC_FUNC_TESTANDSET(short, uint16_t)
617dc3c9915SMateusz Guzik #endif
618dc3c9915SMateusz Guzik
619849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(int, u_int)
620849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(int, u_int)
621849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(int, u_int)
622849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(int, u_int)
623849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(int, u_int)
624849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(int, u_int)
625849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(int, u_int)
626849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(int, u_int)
627849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(int, u_int)
628849aef49SAndrew Turner CSAN_ATOMIC_FUNC_STORE(int, u_int)
629849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(int, u_int)
630849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(int, u_int)
631849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(int, u_int)
632849aef49SAndrew Turner
633849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(long, u_long)
634849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(long, u_long)
635849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(long, u_long)
636849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(long, u_long)
637849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(long, u_long)
638849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(long, u_long)
639849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(long, u_long)
640849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(long, u_long)
641849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(long, u_long)
642849aef49SAndrew Turner CSAN_ATOMIC_FUNC_STORE(long, u_long)
643849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(long, u_long)
644849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(long, u_long)
645849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(long, u_long)
646ca0ec73cSConrad Meyer CSAN_ATOMIC_FUNC_TESTANDSET(acq_long, u_long)
647849aef49SAndrew Turner
648849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(ptr, uintptr_t)
649849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(ptr, uintptr_t)
650849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(ptr, uintptr_t)
651849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(ptr, uintptr_t)
652849aef49SAndrew Turner #if !defined(__amd64__)
653849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(ptr, uintptr_t)
654849aef49SAndrew Turner #endif
655849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(ptr, uintptr_t)
656849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(ptr, uintptr_t)
657849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(ptr, uintptr_t)
658849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(ptr, uintptr_t)
659849aef49SAndrew Turner CSAN_ATOMIC_FUNC_STORE(ptr, uintptr_t)
660849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(ptr, uintptr_t)
661849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(ptr, uintptr_t)
662849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(ptr, uintptr_t)
663849aef49SAndrew Turner
664849aef49SAndrew Turner #define CSAN_ATOMIC_FUNC_THREAD_FENCE(name) \
665849aef49SAndrew Turner void kcsan_atomic_thread_fence_##name(void) \
666849aef49SAndrew Turner { \
667849aef49SAndrew Turner atomic_thread_fence_##name(); \
668849aef49SAndrew Turner }
669849aef49SAndrew Turner
670849aef49SAndrew Turner CSAN_ATOMIC_FUNC_THREAD_FENCE(acq)
671849aef49SAndrew Turner CSAN_ATOMIC_FUNC_THREAD_FENCE(acq_rel)
672849aef49SAndrew Turner CSAN_ATOMIC_FUNC_THREAD_FENCE(rel)
673849aef49SAndrew Turner CSAN_ATOMIC_FUNC_THREAD_FENCE(seq_cst)
6740cb53570SAndrew Turner
6753ead6023SMark Johnston void
6763ead6023SMark Johnston kcsan_atomic_interrupt_fence(void)
6773ead6023SMark Johnston {
6783ead6023SMark Johnston atomic_interrupt_fence();
6793ead6023SMark Johnston }
6803ead6023SMark Johnston
6810cb53570SAndrew Turner /* -------------------------------------------------------------------------- */
6820cb53570SAndrew Turner
6830cb53570SAndrew Turner #include <sys/bus.h>
684849aef49SAndrew Turner #include <machine/bus.h>
685435c7cfbSMark Johnston #include <sys/bus_san.h>
6860cb53570SAndrew Turner
687849aef49SAndrew Turner int
kcsan_bus_space_map(bus_space_tag_t tag,bus_addr_t hnd,bus_size_t size,int flags,bus_space_handle_t * handlep)688849aef49SAndrew Turner kcsan_bus_space_map(bus_space_tag_t tag, bus_addr_t hnd, bus_size_t size,
689849aef49SAndrew Turner int flags, bus_space_handle_t *handlep)
690849aef49SAndrew Turner {
6910cb53570SAndrew Turner
692849aef49SAndrew Turner return (bus_space_map(tag, hnd, size, flags, handlep));
6930cb53570SAndrew Turner }
6940cb53570SAndrew Turner
695849aef49SAndrew Turner void
kcsan_bus_space_unmap(bus_space_tag_t tag,bus_space_handle_t hnd,bus_size_t size)696849aef49SAndrew Turner kcsan_bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t hnd,
697849aef49SAndrew Turner bus_size_t size)
698849aef49SAndrew Turner {
699849aef49SAndrew Turner
700849aef49SAndrew Turner bus_space_unmap(tag, hnd, size);
7010cb53570SAndrew Turner }
7020cb53570SAndrew Turner
703849aef49SAndrew Turner int
kcsan_bus_space_subregion(bus_space_tag_t tag,bus_space_handle_t hnd,bus_size_t offset,bus_size_t size,bus_space_handle_t * handlep)704849aef49SAndrew Turner kcsan_bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t hnd,
705849aef49SAndrew Turner bus_size_t offset, bus_size_t size, bus_space_handle_t *handlep)
706849aef49SAndrew Turner {
7070cb53570SAndrew Turner
708849aef49SAndrew Turner return (bus_space_subregion(tag, hnd, offset, size, handlep));
709849aef49SAndrew Turner }
710849aef49SAndrew Turner
711849aef49SAndrew Turner #if !defined(__amd64__)
712849aef49SAndrew Turner int
kcsan_bus_space_alloc(bus_space_tag_t tag,bus_addr_t reg_start,bus_addr_t reg_end,bus_size_t size,bus_size_t alignment,bus_size_t boundary,int flags,bus_addr_t * addrp,bus_space_handle_t * handlep)713849aef49SAndrew Turner kcsan_bus_space_alloc(bus_space_tag_t tag, bus_addr_t reg_start,
714849aef49SAndrew Turner bus_addr_t reg_end, bus_size_t size, bus_size_t alignment,
715849aef49SAndrew Turner bus_size_t boundary, int flags, bus_addr_t *addrp,
716849aef49SAndrew Turner bus_space_handle_t *handlep)
717849aef49SAndrew Turner {
718849aef49SAndrew Turner
719849aef49SAndrew Turner return (bus_space_alloc(tag, reg_start, reg_end, size, alignment,
720849aef49SAndrew Turner boundary, flags, addrp, handlep));
721849aef49SAndrew Turner }
722849aef49SAndrew Turner #endif
723849aef49SAndrew Turner
724849aef49SAndrew Turner void
kcsan_bus_space_free(bus_space_tag_t tag,bus_space_handle_t hnd,bus_size_t size)725849aef49SAndrew Turner kcsan_bus_space_free(bus_space_tag_t tag, bus_space_handle_t hnd,
726849aef49SAndrew Turner bus_size_t size)
727849aef49SAndrew Turner {
728849aef49SAndrew Turner
729849aef49SAndrew Turner bus_space_free(tag, hnd, size);
730849aef49SAndrew Turner }
731849aef49SAndrew Turner
732849aef49SAndrew Turner void
kcsan_bus_space_barrier(bus_space_tag_t tag,bus_space_handle_t hnd,bus_size_t offset,bus_size_t size,int flags)733849aef49SAndrew Turner kcsan_bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t hnd,
734849aef49SAndrew Turner bus_size_t offset, bus_size_t size, int flags)
735849aef49SAndrew Turner {
736849aef49SAndrew Turner
737849aef49SAndrew Turner bus_space_barrier(tag, hnd, offset, size, flags);
738849aef49SAndrew Turner }
739849aef49SAndrew Turner
740849aef49SAndrew Turner #define CSAN_BUS_READ_FUNC(func, width, type) \
741849aef49SAndrew Turner type kcsan_bus_space_read##func##_##width(bus_space_tag_t tag, \
742849aef49SAndrew Turner bus_space_handle_t hnd, bus_size_t offset) \
743849aef49SAndrew Turner { \
744849aef49SAndrew Turner return (bus_space_read##func##_##width(tag, hnd, \
745849aef49SAndrew Turner offset)); \
746849aef49SAndrew Turner } \
747849aef49SAndrew Turner
748849aef49SAndrew Turner #define CSAN_BUS_READ_PTR_FUNC(func, width, type) \
749849aef49SAndrew Turner void kcsan_bus_space_read_##func##_##width(bus_space_tag_t tag, \
750849aef49SAndrew Turner bus_space_handle_t hnd, bus_size_t size, type *buf, \
751849aef49SAndrew Turner bus_size_t count) \
752849aef49SAndrew Turner { \
753849aef49SAndrew Turner kcsan_access((uintptr_t)buf, sizeof(type) * count, \
754849aef49SAndrew Turner false, false, __RET_ADDR); \
755849aef49SAndrew Turner bus_space_read_##func##_##width(tag, hnd, size, buf, \
756849aef49SAndrew Turner count); \
757849aef49SAndrew Turner }
758849aef49SAndrew Turner
759849aef49SAndrew Turner CSAN_BUS_READ_FUNC(, 1, uint8_t)
760849aef49SAndrew Turner CSAN_BUS_READ_FUNC(_stream, 1, uint8_t)
761849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi, 1, uint8_t)
762849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi_stream, 1, uint8_t)
763849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region, 1, uint8_t)
764849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region_stream, 1, uint8_t)
765849aef49SAndrew Turner
766849aef49SAndrew Turner CSAN_BUS_READ_FUNC(, 2, uint16_t)
767849aef49SAndrew Turner CSAN_BUS_READ_FUNC(_stream, 2, uint16_t)
768849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi, 2, uint16_t)
769849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi_stream, 2, uint16_t)
770849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region, 2, uint16_t)
771849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region_stream, 2, uint16_t)
772849aef49SAndrew Turner
773849aef49SAndrew Turner CSAN_BUS_READ_FUNC(, 4, uint32_t)
774849aef49SAndrew Turner CSAN_BUS_READ_FUNC(_stream, 4, uint32_t)
775849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi, 4, uint32_t)
776849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi_stream, 4, uint32_t)
777849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region, 4, uint32_t)
778849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region_stream, 4, uint32_t)
779849aef49SAndrew Turner
780849aef49SAndrew Turner CSAN_BUS_READ_FUNC(, 8, uint64_t)
781849aef49SAndrew Turner #if defined(__aarch64__)
782849aef49SAndrew Turner CSAN_BUS_READ_FUNC(_stream, 8, uint64_t)
783849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi, 8, uint64_t)
784849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi_stream, 8, uint64_t)
785849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region, 8, uint64_t)
786849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region_stream, 8, uint64_t)
787849aef49SAndrew Turner #endif
788849aef49SAndrew Turner
789849aef49SAndrew Turner #define CSAN_BUS_WRITE_FUNC(func, width, type) \
790849aef49SAndrew Turner void kcsan_bus_space_write##func##_##width(bus_space_tag_t tag, \
791849aef49SAndrew Turner bus_space_handle_t hnd, bus_size_t offset, type value) \
792849aef49SAndrew Turner { \
793849aef49SAndrew Turner bus_space_write##func##_##width(tag, hnd, offset, value); \
794849aef49SAndrew Turner } \
795849aef49SAndrew Turner
796849aef49SAndrew Turner #define CSAN_BUS_WRITE_PTR_FUNC(func, width, type) \
797849aef49SAndrew Turner void kcsan_bus_space_write_##func##_##width(bus_space_tag_t tag, \
798849aef49SAndrew Turner bus_space_handle_t hnd, bus_size_t size, const type *buf, \
799849aef49SAndrew Turner bus_size_t count) \
800849aef49SAndrew Turner { \
801849aef49SAndrew Turner kcsan_access((uintptr_t)buf, sizeof(type) * count, \
802849aef49SAndrew Turner true, false, __RET_ADDR); \
803849aef49SAndrew Turner bus_space_write_##func##_##width(tag, hnd, size, buf, \
804849aef49SAndrew Turner count); \
805849aef49SAndrew Turner }
806849aef49SAndrew Turner
807849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(, 1, uint8_t)
808849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(_stream, 1, uint8_t)
809849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi, 1, uint8_t)
810849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 1, uint8_t)
811849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region, 1, uint8_t)
812849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region_stream, 1, uint8_t)
813849aef49SAndrew Turner
814849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(, 2, uint16_t)
815849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(_stream, 2, uint16_t)
816849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi, 2, uint16_t)
817849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 2, uint16_t)
818849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region, 2, uint16_t)
819849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region_stream, 2, uint16_t)
820849aef49SAndrew Turner
821849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(, 4, uint32_t)
822849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(_stream, 4, uint32_t)
823849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi, 4, uint32_t)
824849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 4, uint32_t)
825849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region, 4, uint32_t)
826849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region_stream, 4, uint32_t)
827849aef49SAndrew Turner
828849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(, 8, uint64_t)
829849aef49SAndrew Turner #if defined(__aarch64__)
830849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(_stream, 8, uint64_t)
831849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi, 8, uint64_t)
832849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 8, uint64_t)
833849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region, 8, uint64_t)
834849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region_stream, 8, uint64_t)
835849aef49SAndrew Turner #endif
836849aef49SAndrew Turner
837849aef49SAndrew Turner #define CSAN_BUS_SET_FUNC(func, width, type) \
838849aef49SAndrew Turner void kcsan_bus_space_set_##func##_##width(bus_space_tag_t tag, \
839849aef49SAndrew Turner bus_space_handle_t hnd, bus_size_t offset, type value, \
840849aef49SAndrew Turner bus_size_t count) \
841849aef49SAndrew Turner { \
842849aef49SAndrew Turner bus_space_set_##func##_##width(tag, hnd, offset, value, \
843849aef49SAndrew Turner count); \
844849aef49SAndrew Turner }
845849aef49SAndrew Turner
846849aef49SAndrew Turner CSAN_BUS_SET_FUNC(multi, 1, uint8_t)
847849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region, 1, uint8_t)
848bba0065fSAndrew Turner #if !defined(__aarch64__)
849bba0065fSAndrew Turner CSAN_BUS_SET_FUNC(multi_stream, 1, uint8_t)
850849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region_stream, 1, uint8_t)
851bba0065fSAndrew Turner #endif
852849aef49SAndrew Turner
853849aef49SAndrew Turner CSAN_BUS_SET_FUNC(multi, 2, uint16_t)
854849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region, 2, uint16_t)
855bba0065fSAndrew Turner #if !defined(__aarch64__)
856bba0065fSAndrew Turner CSAN_BUS_SET_FUNC(multi_stream, 2, uint16_t)
857849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region_stream, 2, uint16_t)
858bba0065fSAndrew Turner #endif
859849aef49SAndrew Turner
860849aef49SAndrew Turner CSAN_BUS_SET_FUNC(multi, 4, uint32_t)
861849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region, 4, uint32_t)
862bba0065fSAndrew Turner #if !defined(__aarch64__)
863bba0065fSAndrew Turner CSAN_BUS_SET_FUNC(multi_stream, 4, uint32_t)
864849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region_stream, 4, uint32_t)
865bba0065fSAndrew Turner #endif
866849aef49SAndrew Turner
867849aef49SAndrew Turner #if !defined(__amd64__)
868849aef49SAndrew Turner CSAN_BUS_SET_FUNC(multi, 8, uint64_t)
869849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region, 8, uint64_t)
870bba0065fSAndrew Turner #if !defined(__aarch64__)
871bba0065fSAndrew Turner CSAN_BUS_SET_FUNC(multi_stream, 8, uint64_t)
872849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region_stream, 8, uint64_t)
873849aef49SAndrew Turner #endif
874bba0065fSAndrew Turner #endif
87595a85c12SMichal Meloun
87695a85c12SMichal Meloun #define CSAN_BUS_PEEK_FUNC(width, type) \
87795a85c12SMichal Meloun int kcsan_bus_space_peek_##width(bus_space_tag_t tag, \
87895a85c12SMichal Meloun bus_space_handle_t hnd, bus_size_t offset, type *value) \
87995a85c12SMichal Meloun { \
88095a85c12SMichal Meloun kcsan_access((uintptr_t)value, sizeof(type), true, false, \
88195a85c12SMichal Meloun __RET_ADDR); \
88295a85c12SMichal Meloun return (bus_space_peek_##width(tag, hnd, offset, value)); \
88395a85c12SMichal Meloun }
88495a85c12SMichal Meloun
88595a85c12SMichal Meloun CSAN_BUS_PEEK_FUNC(1, uint8_t)
88695a85c12SMichal Meloun CSAN_BUS_PEEK_FUNC(2, uint16_t)
88795a85c12SMichal Meloun CSAN_BUS_PEEK_FUNC(4, uint32_t)
88895a85c12SMichal Meloun #if !defined(__i386__)
88995a85c12SMichal Meloun CSAN_BUS_PEEK_FUNC(8, uint64_t)
89095a85c12SMichal Meloun #endif
89195a85c12SMichal Meloun
89295a85c12SMichal Meloun #define CSAN_BUS_POKE_FUNC(width, type) \
89395a85c12SMichal Meloun int kcsan_bus_space_poke_##width(bus_space_tag_t tag, \
89495a85c12SMichal Meloun bus_space_handle_t hnd, bus_size_t offset, type value) \
89595a85c12SMichal Meloun { \
89695a85c12SMichal Meloun return (bus_space_poke_##width(tag, hnd, offset, value)); \
89795a85c12SMichal Meloun }
89895a85c12SMichal Meloun
89995a85c12SMichal Meloun CSAN_BUS_POKE_FUNC(1, uint8_t)
90095a85c12SMichal Meloun CSAN_BUS_POKE_FUNC(2, uint16_t)
90195a85c12SMichal Meloun CSAN_BUS_POKE_FUNC(4, uint32_t)
90295a85c12SMichal Meloun #if !defined(__i386__)
90395a85c12SMichal Meloun CSAN_BUS_POKE_FUNC(8, uint64_t)
90495a85c12SMichal Meloun #endif
905