xref: /freebsd/sys/kern/subr_csan.c (revision 849aef496d2ae19961310f4e92f3a0b928732d26)
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.
6*849aef49SAndrew 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 
33*849aef49SAndrew Turner #define	KCSAN_RUNTIME
34*849aef49SAndrew Turner 
35*849aef49SAndrew Turner #include "opt_ddb.h"
36*849aef49SAndrew Turner 
370cb53570SAndrew Turner #include <sys/cdefs.h>
38*849aef49SAndrew Turner __FBSDID("$FreeBSD$");
390cb53570SAndrew Turner 
400cb53570SAndrew Turner #include <sys/param.h>
410cb53570SAndrew Turner #include <sys/kernel.h>
42*849aef49SAndrew Turner #include <sys/bus.h>
430cb53570SAndrew Turner #include <sys/conf.h>
440cb53570SAndrew Turner #include <sys/cpu.h>
45*849aef49SAndrew Turner #include <sys/csan.h>
46*849aef49SAndrew Turner #include <sys/proc.h>
47*849aef49SAndrew Turner #include <sys/smp.h>
48*849aef49SAndrew Turner #include <sys/systm.h>
49*849aef49SAndrew Turner 
50*849aef49SAndrew Turner #include <ddb/ddb.h>
51*849aef49SAndrew 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 
73*849aef49SAndrew 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 
88*849aef49SAndrew Turner static void
89*849aef49SAndrew Turner kcsan_enable(void *dummy __unused)
900cb53570SAndrew Turner {
91*849aef49SAndrew Turner 
92*849aef49SAndrew Turner 	printf("Enabling KCSCAN, expect reduced performance.\n");
930cb53570SAndrew Turner 	kcsan_enabled = true;
940cb53570SAndrew Turner }
95*849aef49SAndrew Turner SYSINIT(kcsan_enable, SI_SUB_SMP, SI_ORDER_SECOND, kcsan_enable, NULL);
960cb53570SAndrew Turner 
970cb53570SAndrew Turner void
98*849aef49SAndrew Turner kcsan_cpu_init(u_int cpu)
990cb53570SAndrew Turner {
100*849aef49SAndrew Turner 	kcsan_cpus[cpu].inited = true;
1010cb53570SAndrew Turner }
1020cb53570SAndrew Turner 
1030cb53570SAndrew Turner /* -------------------------------------------------------------------------- */
1040cb53570SAndrew Turner 
1050cb53570SAndrew Turner static inline void
106*849aef49SAndrew 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;
109*849aef49SAndrew Turner #ifdef DDB
110*849aef49SAndrew Turner 	c_db_sym_t sym;
111*849aef49SAndrew Turner 	db_expr_t offset;
1120cb53570SAndrew Turner 
113*849aef49SAndrew Turner 	sym = db_search_symbol((vm_offset_t)new->pc, DB_STGY_PROC, &offset);
114*849aef49SAndrew Turner 	db_symbol_values(sym, &newsym, NULL);
115*849aef49SAndrew Turner 
116*849aef49SAndrew Turner 	sym = db_search_symbol((vm_offset_t)old->pc, DB_STGY_PROC, &offset);
117*849aef49SAndrew Turner 	db_symbol_values(sym, &oldsym, NULL);
118*849aef49SAndrew Turner #else
119*849aef49SAndrew Turner 	newsym = "";
120*849aef49SAndrew Turner 	oldsym = "";
121*849aef49SAndrew Turner #endif
1220cb53570SAndrew Turner 	REPORT("CSan: Racy Access "
123*849aef49SAndrew Turner 	    "[Cpu%u %s%s Addr=%p Size=%u PC=%p<%s>] "
124*849aef49SAndrew 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;
1540cb53570SAndrew Turner 
1550cb53570SAndrew Turner 	new.addr = addr;
1560cb53570SAndrew Turner 	new.size = size;
1570cb53570SAndrew Turner 	new.write = write;
1580cb53570SAndrew Turner 	new.atomic = atomic;
1590cb53570SAndrew Turner 	new.pc = pc;
1600cb53570SAndrew Turner 
161*849aef49SAndrew Turner 	CPU_FOREACH(i) {
1620cb53570SAndrew Turner 		__builtin_memcpy(&old, &kcsan_cpus[i].cell, sizeof(old));
1630cb53570SAndrew Turner 
1640cb53570SAndrew Turner 		if (old.addr + old.size <= new.addr)
1650cb53570SAndrew Turner 			continue;
1660cb53570SAndrew Turner 		if (new.addr + new.size <= old.addr)
1670cb53570SAndrew Turner 			continue;
1680cb53570SAndrew Turner 		if (__predict_true(!old.write && !new.write))
1690cb53570SAndrew Turner 			continue;
1700cb53570SAndrew Turner 		if (__predict_true(kcsan_access_is_atomic(&new, &old)))
1710cb53570SAndrew Turner 			continue;
1720cb53570SAndrew Turner 
173*849aef49SAndrew Turner 		kcsan_report(&new, PCPU_GET(cpuid), &old, i);
1740cb53570SAndrew Turner 		break;
1750cb53570SAndrew Turner 	}
1760cb53570SAndrew Turner 
1770cb53570SAndrew Turner 	if (__predict_false(!kcsan_md_is_avail()))
1780cb53570SAndrew Turner 		return;
1790cb53570SAndrew Turner 
1800cb53570SAndrew Turner 	kcsan_md_disable_intrs(&intr);
1810cb53570SAndrew Turner 
182*849aef49SAndrew Turner 	cpu = &kcsan_cpus[PCPU_GET(cpuid)];
1830cb53570SAndrew Turner 	if (__predict_false(!cpu->inited))
1840cb53570SAndrew Turner 		goto out;
1850cb53570SAndrew Turner 	cpu->cnt = (cpu->cnt + 1) % KCSAN_NACCESSES;
1860cb53570SAndrew Turner 	if (__predict_true(cpu->cnt != 0))
1870cb53570SAndrew Turner 		goto out;
1880cb53570SAndrew Turner 
1890cb53570SAndrew Turner 	__builtin_memcpy(&cpu->cell, &new, sizeof(new));
1900cb53570SAndrew Turner 	kcsan_md_delay(KCSAN_DELAY);
1910cb53570SAndrew Turner 	__builtin_memset(&cpu->cell, 0, sizeof(new));
1920cb53570SAndrew Turner 
1930cb53570SAndrew Turner out:
1940cb53570SAndrew Turner 	kcsan_md_enable_intrs(&intr);
1950cb53570SAndrew Turner }
1960cb53570SAndrew Turner 
1970cb53570SAndrew Turner #define CSAN_READ(size)							\
1980cb53570SAndrew Turner 	void __tsan_read##size(uintptr_t);				\
1990cb53570SAndrew Turner 	void __tsan_read##size(uintptr_t addr)				\
2000cb53570SAndrew Turner 	{								\
2010cb53570SAndrew Turner 		kcsan_access(addr, size, false, false, __RET_ADDR);	\
202*849aef49SAndrew Turner 	}								\
203*849aef49SAndrew Turner 	void __tsan_unaligned_read##size(uintptr_t);			\
204*849aef49SAndrew Turner 	void __tsan_unaligned_read##size(uintptr_t addr)		\
205*849aef49SAndrew Turner 	{								\
206*849aef49SAndrew Turner 		kcsan_access(addr, size, false, false, __RET_ADDR);	\
2070cb53570SAndrew Turner 	}
2080cb53570SAndrew Turner 
2090cb53570SAndrew Turner CSAN_READ(1)
2100cb53570SAndrew Turner CSAN_READ(2)
2110cb53570SAndrew Turner CSAN_READ(4)
2120cb53570SAndrew Turner CSAN_READ(8)
2130cb53570SAndrew Turner CSAN_READ(16)
2140cb53570SAndrew Turner 
2150cb53570SAndrew Turner #define CSAN_WRITE(size)						\
2160cb53570SAndrew Turner 	void __tsan_write##size(uintptr_t);				\
2170cb53570SAndrew Turner 	void __tsan_write##size(uintptr_t addr)				\
2180cb53570SAndrew Turner 	{								\
2190cb53570SAndrew Turner 		kcsan_access(addr, size, true, false, __RET_ADDR);	\
220*849aef49SAndrew Turner 	}								\
221*849aef49SAndrew Turner 	void __tsan_unaligned_write##size(uintptr_t);			\
222*849aef49SAndrew Turner 	void __tsan_unaligned_write##size(uintptr_t addr)		\
223*849aef49SAndrew Turner 	{								\
224*849aef49SAndrew Turner 		kcsan_access(addr, size, true, false, __RET_ADDR);	\
2250cb53570SAndrew Turner 	}
2260cb53570SAndrew Turner 
2270cb53570SAndrew Turner CSAN_WRITE(1)
2280cb53570SAndrew Turner CSAN_WRITE(2)
2290cb53570SAndrew Turner CSAN_WRITE(4)
2300cb53570SAndrew Turner CSAN_WRITE(8)
2310cb53570SAndrew Turner CSAN_WRITE(16)
2320cb53570SAndrew Turner 
2330cb53570SAndrew Turner void __tsan_read_range(uintptr_t, size_t);
2340cb53570SAndrew Turner void __tsan_write_range(uintptr_t, size_t);
2350cb53570SAndrew Turner 
2360cb53570SAndrew Turner void
2370cb53570SAndrew Turner __tsan_read_range(uintptr_t addr, size_t size)
2380cb53570SAndrew Turner {
2390cb53570SAndrew Turner 	kcsan_access(addr, size, false, false, __RET_ADDR);
2400cb53570SAndrew Turner }
2410cb53570SAndrew Turner 
2420cb53570SAndrew Turner void
2430cb53570SAndrew Turner __tsan_write_range(uintptr_t addr, size_t size)
2440cb53570SAndrew Turner {
2450cb53570SAndrew Turner 	kcsan_access(addr, size, true, false, __RET_ADDR);
2460cb53570SAndrew Turner }
2470cb53570SAndrew Turner 
2480cb53570SAndrew Turner void __tsan_init(void);
2490cb53570SAndrew Turner void __tsan_func_entry(void *);
2500cb53570SAndrew Turner void __tsan_func_exit(void);
2510cb53570SAndrew Turner 
2520cb53570SAndrew Turner void
2530cb53570SAndrew Turner __tsan_init(void)
2540cb53570SAndrew Turner {
2550cb53570SAndrew Turner }
2560cb53570SAndrew Turner 
2570cb53570SAndrew Turner void
2580cb53570SAndrew Turner __tsan_func_entry(void *call_pc)
2590cb53570SAndrew Turner {
2600cb53570SAndrew Turner }
2610cb53570SAndrew Turner 
2620cb53570SAndrew Turner void
2630cb53570SAndrew Turner __tsan_func_exit(void)
2640cb53570SAndrew Turner {
2650cb53570SAndrew Turner }
2660cb53570SAndrew Turner 
2670cb53570SAndrew Turner /* -------------------------------------------------------------------------- */
2680cb53570SAndrew Turner 
2690cb53570SAndrew Turner void *
2700cb53570SAndrew Turner kcsan_memcpy(void *dst, const void *src, size_t len)
2710cb53570SAndrew Turner {
2720cb53570SAndrew Turner 	kcsan_access((uintptr_t)src, len, false, false, __RET_ADDR);
2730cb53570SAndrew Turner 	kcsan_access((uintptr_t)dst, len, true, false, __RET_ADDR);
2740cb53570SAndrew Turner 	return __builtin_memcpy(dst, src, len);
2750cb53570SAndrew Turner }
2760cb53570SAndrew Turner 
2770cb53570SAndrew Turner int
2780cb53570SAndrew Turner kcsan_memcmp(const void *b1, const void *b2, size_t len)
2790cb53570SAndrew Turner {
2800cb53570SAndrew Turner 	kcsan_access((uintptr_t)b1, len, false, false, __RET_ADDR);
2810cb53570SAndrew Turner 	kcsan_access((uintptr_t)b2, len, false, false, __RET_ADDR);
2820cb53570SAndrew Turner 	return __builtin_memcmp(b1, b2, len);
2830cb53570SAndrew Turner }
2840cb53570SAndrew Turner 
2850cb53570SAndrew Turner void *
2860cb53570SAndrew Turner kcsan_memset(void *b, int c, size_t len)
2870cb53570SAndrew Turner {
2880cb53570SAndrew Turner 	kcsan_access((uintptr_t)b, len, true, false, __RET_ADDR);
2890cb53570SAndrew Turner 	return __builtin_memset(b, c, len);
2900cb53570SAndrew Turner }
2910cb53570SAndrew Turner 
2920cb53570SAndrew Turner void *
2930cb53570SAndrew Turner kcsan_memmove(void *dst, const void *src, size_t len)
2940cb53570SAndrew Turner {
2950cb53570SAndrew Turner 	kcsan_access((uintptr_t)src, len, false, false, __RET_ADDR);
2960cb53570SAndrew Turner 	kcsan_access((uintptr_t)dst, len, true, false, __RET_ADDR);
2970cb53570SAndrew Turner 	return __builtin_memmove(dst, src, len);
2980cb53570SAndrew Turner }
2990cb53570SAndrew Turner 
3000cb53570SAndrew Turner char *
3010cb53570SAndrew Turner kcsan_strcpy(char *dst, const char *src)
3020cb53570SAndrew Turner {
3030cb53570SAndrew Turner 	char *save = dst;
3040cb53570SAndrew Turner 
3050cb53570SAndrew Turner 	while (1) {
3060cb53570SAndrew Turner 		kcsan_access((uintptr_t)src, 1, false, false, __RET_ADDR);
3070cb53570SAndrew Turner 		kcsan_access((uintptr_t)dst, 1, true, false, __RET_ADDR);
3080cb53570SAndrew Turner 		*dst = *src;
3090cb53570SAndrew Turner 		if (*src == '\0')
3100cb53570SAndrew Turner 			break;
3110cb53570SAndrew Turner 		src++, dst++;
3120cb53570SAndrew Turner 	}
3130cb53570SAndrew Turner 
3140cb53570SAndrew Turner 	return save;
3150cb53570SAndrew Turner }
3160cb53570SAndrew Turner 
3170cb53570SAndrew Turner int
3180cb53570SAndrew Turner kcsan_strcmp(const char *s1, const char *s2)
3190cb53570SAndrew Turner {
3200cb53570SAndrew Turner 	while (1) {
3210cb53570SAndrew Turner 		kcsan_access((uintptr_t)s1, 1, false, false, __RET_ADDR);
3220cb53570SAndrew Turner 		kcsan_access((uintptr_t)s2, 1, false, false, __RET_ADDR);
3230cb53570SAndrew Turner 		if (*s1 != *s2)
3240cb53570SAndrew Turner 			break;
3250cb53570SAndrew Turner 		if (*s1 == '\0')
3260cb53570SAndrew Turner 			return 0;
3270cb53570SAndrew Turner 		s1++, s2++;
3280cb53570SAndrew Turner 	}
3290cb53570SAndrew Turner 
3300cb53570SAndrew Turner 	return (*(const unsigned char *)s1 - *(const unsigned char *)s2);
3310cb53570SAndrew Turner }
3320cb53570SAndrew Turner 
3330cb53570SAndrew Turner size_t
3340cb53570SAndrew Turner kcsan_strlen(const char *str)
3350cb53570SAndrew Turner {
3360cb53570SAndrew Turner 	const char *s;
3370cb53570SAndrew Turner 
3380cb53570SAndrew Turner 	s = str;
3390cb53570SAndrew Turner 	while (1) {
3400cb53570SAndrew Turner 		kcsan_access((uintptr_t)s, 1, false, false, __RET_ADDR);
3410cb53570SAndrew Turner 		if (*s == '\0')
3420cb53570SAndrew Turner 			break;
3430cb53570SAndrew Turner 		s++;
3440cb53570SAndrew Turner 	}
3450cb53570SAndrew Turner 
3460cb53570SAndrew Turner 	return (s - str);
3470cb53570SAndrew Turner }
3480cb53570SAndrew Turner 
3490cb53570SAndrew Turner #undef copystr
3500cb53570SAndrew Turner #undef copyin
351*849aef49SAndrew Turner #undef copyin_nofault
352*849aef49SAndrew Turner #undef copyinstr
3530cb53570SAndrew Turner #undef copyout
354*849aef49SAndrew Turner #undef copyout_nofault
3550cb53570SAndrew Turner 
3560cb53570SAndrew Turner int
3570cb53570SAndrew Turner kcsan_copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done)
3580cb53570SAndrew Turner {
3590cb53570SAndrew Turner 	kcsan_access((uintptr_t)kdaddr, len, true, false, __RET_ADDR);
3600cb53570SAndrew Turner 	return copystr(kfaddr, kdaddr, len, done);
3610cb53570SAndrew Turner }
3620cb53570SAndrew Turner 
3630cb53570SAndrew Turner int
3640cb53570SAndrew Turner kcsan_copyin(const void *uaddr, void *kaddr, size_t len)
3650cb53570SAndrew Turner {
3660cb53570SAndrew Turner 	kcsan_access((uintptr_t)kaddr, len, true, false, __RET_ADDR);
3670cb53570SAndrew Turner 	return copyin(uaddr, kaddr, len);
3680cb53570SAndrew Turner }
3690cb53570SAndrew Turner 
3700cb53570SAndrew Turner int
3710cb53570SAndrew Turner kcsan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
3720cb53570SAndrew Turner {
3730cb53570SAndrew Turner 	kcsan_access((uintptr_t)kaddr, len, true, false, __RET_ADDR);
3740cb53570SAndrew Turner 	return copyinstr(uaddr, kaddr, len, done);
3750cb53570SAndrew Turner }
3760cb53570SAndrew Turner 
3770cb53570SAndrew Turner int
378*849aef49SAndrew Turner kcsan_copyout(const void *kaddr, void *uaddr, size_t len)
3790cb53570SAndrew Turner {
3800cb53570SAndrew Turner 	kcsan_access((uintptr_t)kaddr, len, false, false, __RET_ADDR);
381*849aef49SAndrew Turner 	return copyout(kaddr, uaddr, len);
3820cb53570SAndrew Turner }
3830cb53570SAndrew Turner 
3840cb53570SAndrew Turner /* -------------------------------------------------------------------------- */
3850cb53570SAndrew Turner 
386*849aef49SAndrew Turner #include <machine/atomic.h>
387*849aef49SAndrew Turner #include <sys/_cscan_atomic.h>
3880cb53570SAndrew Turner 
389*849aef49SAndrew Turner #define	_CSAN_ATOMIC_FUNC_ADD(name, type)				\
390*849aef49SAndrew Turner 	void kcsan_atomic_add_##name(volatile type *ptr, type val)	\
3910cb53570SAndrew Turner 	{								\
392*849aef49SAndrew Turner 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
3930cb53570SAndrew Turner 		    __RET_ADDR);					\
3940cb53570SAndrew Turner 		atomic_add_##name(ptr, val); 				\
3950cb53570SAndrew Turner 	}
3960cb53570SAndrew Turner 
397*849aef49SAndrew Turner #define	CSAN_ATOMIC_FUNC_ADD(name, type)				\
398*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_ADD(name, type)				\
399*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_ADD(acq_##name, type)				\
400*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_ADD(rel_##name, type)
401*849aef49SAndrew Turner 
402*849aef49SAndrew Turner #define	_CSAN_ATOMIC_FUNC_CLEAR(name, type)				\
403*849aef49SAndrew Turner 	void kcsan_atomic_clear_##name(volatile type *ptr, type val)	\
4040cb53570SAndrew Turner 	{								\
405*849aef49SAndrew Turner 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
4060cb53570SAndrew Turner 		    __RET_ADDR);					\
407*849aef49SAndrew Turner 		atomic_clear_##name(ptr, val); 				\
4080cb53570SAndrew Turner 	}
4090cb53570SAndrew Turner 
410*849aef49SAndrew Turner #define	CSAN_ATOMIC_FUNC_CLEAR(name, type)				\
411*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_CLEAR(name, type)				\
412*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_CLEAR(acq_##name, type)			\
413*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_CLEAR(rel_##name, type)
414*849aef49SAndrew Turner 
415*849aef49SAndrew Turner #define	_CSAN_ATOMIC_FUNC_CMPSET(name, type)				\
416*849aef49SAndrew Turner 	int kcsan_atomic_cmpset_##name(volatile type *ptr, type val1,	\
417*849aef49SAndrew Turner 	    type val2)							\
4180cb53570SAndrew Turner 	{								\
419*849aef49SAndrew Turner 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
4200cb53570SAndrew Turner 		    __RET_ADDR);					\
421*849aef49SAndrew Turner 		return (atomic_cmpset_##name(ptr, val1, val2));		\
4220cb53570SAndrew Turner 	}
4230cb53570SAndrew Turner 
424*849aef49SAndrew Turner #define	CSAN_ATOMIC_FUNC_CMPSET(name, type)				\
425*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_CMPSET(name, type)				\
426*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_CMPSET(acq_##name, type)			\
427*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_CMPSET(rel_##name, type)
428*849aef49SAndrew Turner 
429*849aef49SAndrew Turner #define	_CSAN_ATOMIC_FUNC_FCMPSET(name, type)				\
430*849aef49SAndrew Turner 	int kcsan_atomic_fcmpset_##name(volatile type *ptr, type *val1,	\
431*849aef49SAndrew Turner 	    type val2)							\
4320cb53570SAndrew Turner 	{								\
433*849aef49SAndrew Turner 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
4340cb53570SAndrew Turner 		    __RET_ADDR);					\
435*849aef49SAndrew Turner 		return (atomic_fcmpset_##name(ptr, val1, val2));	\
4360cb53570SAndrew Turner 	}
4370cb53570SAndrew Turner 
438*849aef49SAndrew Turner #define	CSAN_ATOMIC_FUNC_FCMPSET(name, type)				\
439*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_FCMPSET(name, type)				\
440*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_FCMPSET(acq_##name, type)			\
441*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_FCMPSET(rel_##name, type)
442*849aef49SAndrew Turner 
443*849aef49SAndrew Turner #define	CSAN_ATOMIC_FUNC_FETCHADD(name, type)				\
444*849aef49SAndrew Turner 	type kcsan_atomic_fetchadd_##name(volatile type *ptr, type val)	\
4450cb53570SAndrew Turner 	{								\
446*849aef49SAndrew Turner 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
4470cb53570SAndrew Turner 		    __RET_ADDR);					\
448*849aef49SAndrew Turner 		return (atomic_fetchadd_##name(ptr, val));		\
4490cb53570SAndrew Turner 	}
4500cb53570SAndrew Turner 
451*849aef49SAndrew Turner #define	_CSAN_ATOMIC_FUNC_LOAD(name, type)				\
452*849aef49SAndrew Turner 	type kcsan_atomic_load_##name(volatile type *ptr)		\
4530cb53570SAndrew Turner 	{								\
454*849aef49SAndrew Turner 		kcsan_access((uintptr_t)ptr, sizeof(type), false, true,	\
4550cb53570SAndrew Turner 		    __RET_ADDR);					\
456*849aef49SAndrew Turner 		return (atomic_load_##name(ptr));			\
4570cb53570SAndrew Turner 	}
4580cb53570SAndrew Turner 
459*849aef49SAndrew Turner #define	CSAN_ATOMIC_FUNC_LOAD(name, type)				\
460*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_LOAD(name, type)				\
461*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_LOAD(acq_##name, type)			\
462*849aef49SAndrew Turner 
463*849aef49SAndrew Turner #define	CSAN_ATOMIC_FUNC_READANDCLEAR(name, type)			\
464*849aef49SAndrew Turner 	type kcsan_atomic_readandclear_##name(volatile type *ptr)	\
4650cb53570SAndrew Turner 	{								\
466*849aef49SAndrew Turner 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
4670cb53570SAndrew Turner 		    __RET_ADDR);					\
468*849aef49SAndrew Turner 		return (atomic_readandclear_##name(ptr));		\
4690cb53570SAndrew Turner 	}
4700cb53570SAndrew Turner 
471*849aef49SAndrew Turner #define	_CSAN_ATOMIC_FUNC_SET(name, type)				\
472*849aef49SAndrew Turner 	void kcsan_atomic_set_##name(volatile type *ptr, type val)	\
473*849aef49SAndrew Turner 	{								\
474*849aef49SAndrew Turner 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
475*849aef49SAndrew Turner 		    __RET_ADDR);					\
476*849aef49SAndrew Turner 		atomic_set_##name(ptr, val); 				\
477*849aef49SAndrew Turner 	}
4780cb53570SAndrew Turner 
479*849aef49SAndrew Turner #define	CSAN_ATOMIC_FUNC_SET(name, type)				\
480*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_SET(name, type)				\
481*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_SET(acq_##name, type)				\
482*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_SET(rel_##name, type)
4830cb53570SAndrew Turner 
484*849aef49SAndrew Turner #define	_CSAN_ATOMIC_FUNC_SUBTRACT(name, type)				\
485*849aef49SAndrew Turner 	void kcsan_atomic_subtract_##name(volatile type *ptr, type val)	\
486*849aef49SAndrew Turner 	{								\
487*849aef49SAndrew Turner 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
488*849aef49SAndrew Turner 		    __RET_ADDR);					\
489*849aef49SAndrew Turner 		atomic_subtract_##name(ptr, val); 			\
490*849aef49SAndrew Turner 	}
4910cb53570SAndrew Turner 
4920cb53570SAndrew Turner 
493*849aef49SAndrew Turner #define	CSAN_ATOMIC_FUNC_SUBTRACT(name, type)				\
494*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_SUBTRACT(name, type)				\
495*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_SUBTRACT(acq_##name, type)			\
496*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_SUBTRACT(rel_##name, type)
4970cb53570SAndrew Turner 
498*849aef49SAndrew Turner #define	_CSAN_ATOMIC_FUNC_STORE(name, type)				\
499*849aef49SAndrew Turner 	void kcsan_atomic_store_##name(volatile type *ptr, type val)	\
500*849aef49SAndrew Turner 	{								\
501*849aef49SAndrew Turner 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
502*849aef49SAndrew Turner 		    __RET_ADDR);					\
503*849aef49SAndrew Turner 		atomic_store_##name(ptr, val); 				\
504*849aef49SAndrew Turner 	}
5050cb53570SAndrew Turner 
506*849aef49SAndrew Turner #define	CSAN_ATOMIC_FUNC_STORE(name, type)				\
507*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_STORE(name, type)				\
508*849aef49SAndrew Turner 	_CSAN_ATOMIC_FUNC_STORE(rel_##name, type)
509*849aef49SAndrew Turner 
510*849aef49SAndrew Turner #define	CSAN_ATOMIC_FUNC_SWAP(name, type)				\
511*849aef49SAndrew Turner 	type kcsan_atomic_swap_##name(volatile type *ptr, type val)	\
512*849aef49SAndrew Turner 	{								\
513*849aef49SAndrew Turner 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
514*849aef49SAndrew Turner 		    __RET_ADDR);					\
515*849aef49SAndrew Turner 		return(atomic_swap_##name(ptr, val)); 			\
516*849aef49SAndrew Turner 	}
517*849aef49SAndrew Turner 
518*849aef49SAndrew Turner #define	CSAN_ATOMIC_FUNC_TESTANDCLEAR(name, type)			\
519*849aef49SAndrew Turner 	int kcsan_atomic_testandclear_##name(volatile type *ptr, u_int val) \
520*849aef49SAndrew Turner 	{								\
521*849aef49SAndrew Turner 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
522*849aef49SAndrew Turner 		    __RET_ADDR);					\
523*849aef49SAndrew Turner 		return(atomic_testandclear_##name(ptr, val)); 		\
524*849aef49SAndrew Turner 	}
525*849aef49SAndrew Turner 
526*849aef49SAndrew Turner #define	CSAN_ATOMIC_FUNC_TESTANDSET(name, type)				\
527*849aef49SAndrew Turner 	int kcsan_atomic_testandset_##name(volatile type *ptr, u_int val) \
528*849aef49SAndrew Turner 	{								\
529*849aef49SAndrew Turner 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
530*849aef49SAndrew Turner 		    __RET_ADDR);					\
531*849aef49SAndrew Turner 		return (atomic_testandset_##name(ptr, val)); 		\
532*849aef49SAndrew Turner 	}
533*849aef49SAndrew Turner 
534*849aef49SAndrew Turner 
535*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(8, uint8_t)
536*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(8, uint8_t)
537*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(8, uint8_t)
538*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(8, uint8_t)
539*849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_LOAD(8, uint8_t)
540*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(8, uint8_t)
541*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(8, uint8_t)
542*849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_STORE(8, uint8_t)
543*849aef49SAndrew Turner #if 0
544*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(8, uint8_t)
545*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(8, uint8_t)
546*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(8, uint8_t)
547*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(8, uint8_t)
548*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(8, uint8_t)
549*849aef49SAndrew Turner #endif
550*849aef49SAndrew Turner 
551*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(16, uint16_t)
552*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(16, uint16_t)
553*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(16, uint16_t)
554*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(16, uint16_t)
555*849aef49SAndrew Turner #if defined(__aarch64__)
556*849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_LOAD(16, uint16_t)
557*849aef49SAndrew Turner #else
558*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(16, uint16_t)
559*849aef49SAndrew Turner #endif
560*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(16, uint16_t)
561*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(16, uint16_t)
562*849aef49SAndrew Turner _CSAN_ATOMIC_FUNC_STORE(16, uint16_t)
563*849aef49SAndrew Turner #if 0
564*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(16, uint16_t)
565*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(16, uint16_t)
566*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(16, uint16_t)
567*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(16, uint16_t)
568*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(16, uint16_t)
569*849aef49SAndrew Turner #endif
570*849aef49SAndrew Turner 
571*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(32, uint32_t)
572*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(32, uint32_t)
573*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(32, uint32_t)
574*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(32, uint32_t)
575*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(32, uint32_t)
576*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(32, uint32_t)
577*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(32, uint32_t)
578*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(32, uint32_t)
579*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(32, uint32_t)
580*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_STORE(32, uint32_t)
581*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(32, uint32_t)
582*849aef49SAndrew Turner #if !defined(__aarch64__)
583*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(32, uint32_t)
584*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(32, uint32_t)
585*849aef49SAndrew Turner #endif
586*849aef49SAndrew Turner 
587*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(64, uint64_t)
588*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(64, uint64_t)
589*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(64, uint64_t)
590*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(64, uint64_t)
591*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(64, uint64_t)
592*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(64, uint64_t)
593*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(64, uint64_t)
594*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(64, uint64_t)
595*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(64, uint64_t)
596*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_STORE(64, uint64_t)
597*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(64, uint64_t)
598*849aef49SAndrew Turner #if !defined(__aarch64__)
599*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(64, uint64_t)
600*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(64, uint64_t)
601*849aef49SAndrew Turner #endif
602*849aef49SAndrew Turner 
603*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(int, u_int)
604*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(int, u_int)
605*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(int, u_int)
606*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(int, u_int)
607*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(int, u_int)
608*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(int, u_int)
609*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(int, u_int)
610*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(int, u_int)
611*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(int, u_int)
612*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_STORE(int, u_int)
613*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(int, u_int)
614*849aef49SAndrew Turner #if !defined(__aarch64__)
615*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(int, u_int)
616*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(int, u_int)
617*849aef49SAndrew Turner #endif
618*849aef49SAndrew Turner 
619*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(long, u_long)
620*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(long, u_long)
621*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(long, u_long)
622*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(long, u_long)
623*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(long, u_long)
624*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(long, u_long)
625*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(long, u_long)
626*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(long, u_long)
627*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(long, u_long)
628*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_STORE(long, u_long)
629*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(long, u_long)
630*849aef49SAndrew Turner #if !defined(__aarch64__)
631*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(long, u_long)
632*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(long, u_long)
633*849aef49SAndrew Turner #endif
634*849aef49SAndrew Turner 
635*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_ADD(ptr, uintptr_t)
636*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CLEAR(ptr, uintptr_t)
637*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_CMPSET(ptr, uintptr_t)
638*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FCMPSET(ptr, uintptr_t)
639*849aef49SAndrew Turner #if !defined(__amd64__)
640*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_FETCHADD(ptr, uintptr_t)
641*849aef49SAndrew Turner #endif
642*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_LOAD(ptr, uintptr_t)
643*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_READANDCLEAR(ptr, uintptr_t)
644*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SET(ptr, uintptr_t)
645*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SUBTRACT(ptr, uintptr_t)
646*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_STORE(ptr, uintptr_t)
647*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_SWAP(ptr, uintptr_t)
648*849aef49SAndrew Turner #if 0
649*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDCLEAR(ptr, uintptr_t)
650*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_TESTANDSET(ptr, uintptr_t)
651*849aef49SAndrew Turner #endif
652*849aef49SAndrew Turner 
653*849aef49SAndrew Turner #define	CSAN_ATOMIC_FUNC_THREAD_FENCE(name)				\
654*849aef49SAndrew Turner 	void kcsan_atomic_thread_fence_##name(void)			\
655*849aef49SAndrew Turner 	{								\
656*849aef49SAndrew Turner 		atomic_thread_fence_##name();				\
657*849aef49SAndrew Turner 	}
658*849aef49SAndrew Turner 
659*849aef49SAndrew Turner 
660*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_THREAD_FENCE(acq)
661*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_THREAD_FENCE(acq_rel)
662*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_THREAD_FENCE(rel)
663*849aef49SAndrew Turner CSAN_ATOMIC_FUNC_THREAD_FENCE(seq_cst)
6640cb53570SAndrew Turner 
6650cb53570SAndrew Turner /* -------------------------------------------------------------------------- */
6660cb53570SAndrew Turner 
6670cb53570SAndrew Turner #include <sys/bus.h>
668*849aef49SAndrew Turner #include <machine/bus.h>
669*849aef49SAndrew Turner #include <sys/_cscan_bus.h>
6700cb53570SAndrew Turner 
671*849aef49SAndrew Turner int
672*849aef49SAndrew Turner kcsan_bus_space_map(bus_space_tag_t tag, bus_addr_t hnd, bus_size_t size,
673*849aef49SAndrew Turner     int flags, bus_space_handle_t *handlep)
674*849aef49SAndrew Turner {
6750cb53570SAndrew Turner 
676*849aef49SAndrew Turner 	return (bus_space_map(tag, hnd, size, flags, handlep));
6770cb53570SAndrew Turner }
6780cb53570SAndrew Turner 
679*849aef49SAndrew Turner void
680*849aef49SAndrew Turner kcsan_bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t hnd,
681*849aef49SAndrew Turner     bus_size_t size)
682*849aef49SAndrew Turner {
683*849aef49SAndrew Turner 
684*849aef49SAndrew Turner 	bus_space_unmap(tag, hnd, size);
6850cb53570SAndrew Turner }
6860cb53570SAndrew Turner 
687*849aef49SAndrew Turner int
688*849aef49SAndrew Turner kcsan_bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t hnd,
689*849aef49SAndrew Turner     bus_size_t offset, bus_size_t size, bus_space_handle_t *handlep)
690*849aef49SAndrew Turner {
6910cb53570SAndrew Turner 
692*849aef49SAndrew Turner 	return (bus_space_subregion(tag, hnd, offset, size, handlep));
693*849aef49SAndrew Turner }
694*849aef49SAndrew Turner 
695*849aef49SAndrew Turner #if !defined(__amd64__)
696*849aef49SAndrew Turner int
697*849aef49SAndrew Turner kcsan_bus_space_alloc(bus_space_tag_t tag, bus_addr_t reg_start,
698*849aef49SAndrew Turner     bus_addr_t reg_end, bus_size_t size, bus_size_t alignment,
699*849aef49SAndrew Turner     bus_size_t boundary, int flags, bus_addr_t *addrp,
700*849aef49SAndrew Turner     bus_space_handle_t *handlep)
701*849aef49SAndrew Turner {
702*849aef49SAndrew Turner 
703*849aef49SAndrew Turner 	return (bus_space_alloc(tag, reg_start, reg_end, size, alignment,
704*849aef49SAndrew Turner 	    boundary, flags, addrp, handlep));
705*849aef49SAndrew Turner }
706*849aef49SAndrew Turner #endif
707*849aef49SAndrew Turner 
708*849aef49SAndrew Turner void
709*849aef49SAndrew Turner kcsan_bus_space_free(bus_space_tag_t tag, bus_space_handle_t hnd,
710*849aef49SAndrew Turner     bus_size_t size)
711*849aef49SAndrew Turner {
712*849aef49SAndrew Turner 
713*849aef49SAndrew Turner 	bus_space_free(tag, hnd, size);
714*849aef49SAndrew Turner }
715*849aef49SAndrew Turner 
716*849aef49SAndrew Turner void
717*849aef49SAndrew Turner kcsan_bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t hnd,
718*849aef49SAndrew Turner     bus_size_t offset, bus_size_t size, int flags)
719*849aef49SAndrew Turner {
720*849aef49SAndrew Turner 
721*849aef49SAndrew Turner 	bus_space_barrier(tag, hnd, offset, size, flags);
722*849aef49SAndrew Turner }
723*849aef49SAndrew Turner 
724*849aef49SAndrew Turner #define CSAN_BUS_READ_FUNC(func, width, type)				\
725*849aef49SAndrew Turner 	type kcsan_bus_space_read##func##_##width(bus_space_tag_t tag,	\
726*849aef49SAndrew Turner 	    bus_space_handle_t hnd, bus_size_t offset)			\
727*849aef49SAndrew Turner 	{								\
728*849aef49SAndrew Turner 		return (bus_space_read##func##_##width(tag, hnd,	\
729*849aef49SAndrew Turner 		    offset));						\
730*849aef49SAndrew Turner 	}								\
731*849aef49SAndrew Turner 
732*849aef49SAndrew Turner #define CSAN_BUS_READ_PTR_FUNC(func, width, type)			\
733*849aef49SAndrew Turner 	void kcsan_bus_space_read_##func##_##width(bus_space_tag_t tag,	\
734*849aef49SAndrew Turner 	    bus_space_handle_t hnd, bus_size_t size, type *buf,		\
735*849aef49SAndrew Turner 	    bus_size_t count)						\
736*849aef49SAndrew Turner 	{								\
737*849aef49SAndrew Turner 		kcsan_access((uintptr_t)buf, sizeof(type) * count,	\
738*849aef49SAndrew Turner 		    false, false, __RET_ADDR);				\
739*849aef49SAndrew Turner 		bus_space_read_##func##_##width(tag, hnd, size, buf, 	\
740*849aef49SAndrew Turner 		    count);						\
741*849aef49SAndrew Turner 	}
742*849aef49SAndrew Turner 
743*849aef49SAndrew Turner CSAN_BUS_READ_FUNC(, 1, uint8_t)
744*849aef49SAndrew Turner CSAN_BUS_READ_FUNC(_stream, 1, uint8_t)
745*849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi, 1, uint8_t)
746*849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi_stream, 1, uint8_t)
747*849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region, 1, uint8_t)
748*849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region_stream, 1, uint8_t)
749*849aef49SAndrew Turner 
750*849aef49SAndrew Turner CSAN_BUS_READ_FUNC(, 2, uint16_t)
751*849aef49SAndrew Turner CSAN_BUS_READ_FUNC(_stream, 2, uint16_t)
752*849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi, 2, uint16_t)
753*849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi_stream, 2, uint16_t)
754*849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region, 2, uint16_t)
755*849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region_stream, 2, uint16_t)
756*849aef49SAndrew Turner 
757*849aef49SAndrew Turner CSAN_BUS_READ_FUNC(, 4, uint32_t)
758*849aef49SAndrew Turner CSAN_BUS_READ_FUNC(_stream, 4, uint32_t)
759*849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi, 4, uint32_t)
760*849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi_stream, 4, uint32_t)
761*849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region, 4, uint32_t)
762*849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region_stream, 4, uint32_t)
763*849aef49SAndrew Turner 
764*849aef49SAndrew Turner CSAN_BUS_READ_FUNC(, 8, uint64_t)
765*849aef49SAndrew Turner #if defined(__aarch64__)
766*849aef49SAndrew Turner CSAN_BUS_READ_FUNC(_stream, 8, uint64_t)
767*849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi, 8, uint64_t)
768*849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(multi_stream, 8, uint64_t)
769*849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region, 8, uint64_t)
770*849aef49SAndrew Turner CSAN_BUS_READ_PTR_FUNC(region_stream, 8, uint64_t)
771*849aef49SAndrew Turner #endif
772*849aef49SAndrew Turner 
773*849aef49SAndrew Turner #define CSAN_BUS_WRITE_FUNC(func, width, type)				\
774*849aef49SAndrew Turner 	void kcsan_bus_space_write##func##_##width(bus_space_tag_t tag,		\
775*849aef49SAndrew Turner 	    bus_space_handle_t hnd, bus_size_t offset, type value)	\
776*849aef49SAndrew Turner 	{								\
777*849aef49SAndrew Turner 		bus_space_write##func##_##width(tag, hnd, offset, value); \
778*849aef49SAndrew Turner 	}								\
779*849aef49SAndrew Turner 
780*849aef49SAndrew Turner #define CSAN_BUS_WRITE_PTR_FUNC(func, width, type)			\
781*849aef49SAndrew Turner 	void kcsan_bus_space_write_##func##_##width(bus_space_tag_t tag, \
782*849aef49SAndrew Turner 	    bus_space_handle_t hnd, bus_size_t size, const type *buf,	\
783*849aef49SAndrew Turner 	    bus_size_t count)						\
784*849aef49SAndrew Turner 	{								\
785*849aef49SAndrew Turner 		kcsan_access((uintptr_t)buf, sizeof(type) * count,	\
786*849aef49SAndrew Turner 		    true, false, __RET_ADDR);				\
787*849aef49SAndrew Turner 		bus_space_write_##func##_##width(tag, hnd, size, buf, 	\
788*849aef49SAndrew Turner 		    count);						\
789*849aef49SAndrew Turner 	}
790*849aef49SAndrew Turner 
791*849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(, 1, uint8_t)
792*849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(_stream, 1, uint8_t)
793*849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi, 1, uint8_t)
794*849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 1, uint8_t)
795*849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region, 1, uint8_t)
796*849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region_stream, 1, uint8_t)
797*849aef49SAndrew Turner 
798*849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(, 2, uint16_t)
799*849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(_stream, 2, uint16_t)
800*849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi, 2, uint16_t)
801*849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 2, uint16_t)
802*849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region, 2, uint16_t)
803*849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region_stream, 2, uint16_t)
804*849aef49SAndrew Turner 
805*849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(, 4, uint32_t)
806*849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(_stream, 4, uint32_t)
807*849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi, 4, uint32_t)
808*849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 4, uint32_t)
809*849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region, 4, uint32_t)
810*849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region_stream, 4, uint32_t)
811*849aef49SAndrew Turner 
812*849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(, 8, uint64_t)
813*849aef49SAndrew Turner #if defined(__aarch64__)
814*849aef49SAndrew Turner CSAN_BUS_WRITE_FUNC(_stream, 8, uint64_t)
815*849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi, 8, uint64_t)
816*849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 8, uint64_t)
817*849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region, 8, uint64_t)
818*849aef49SAndrew Turner CSAN_BUS_WRITE_PTR_FUNC(region_stream, 8, uint64_t)
819*849aef49SAndrew Turner #endif
820*849aef49SAndrew Turner 
821*849aef49SAndrew Turner #define CSAN_BUS_SET_FUNC(func, width, type)				\
822*849aef49SAndrew Turner 	void kcsan_bus_space_set_##func##_##width(bus_space_tag_t tag,	\
823*849aef49SAndrew Turner 	    bus_space_handle_t hnd, bus_size_t offset, type value,	\
824*849aef49SAndrew Turner 	    bus_size_t count)						\
825*849aef49SAndrew Turner 	{								\
826*849aef49SAndrew Turner 		bus_space_set_##func##_##width(tag, hnd, offset, value,	\
827*849aef49SAndrew Turner 		    count);						\
828*849aef49SAndrew Turner 	}
829*849aef49SAndrew Turner 
830*849aef49SAndrew Turner CSAN_BUS_SET_FUNC(multi, 1, uint8_t)
831*849aef49SAndrew Turner CSAN_BUS_SET_FUNC(multi_stream, 1, uint8_t)
832*849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region, 1, uint8_t)
833*849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region_stream, 1, uint8_t)
834*849aef49SAndrew Turner 
835*849aef49SAndrew Turner CSAN_BUS_SET_FUNC(multi, 2, uint16_t)
836*849aef49SAndrew Turner CSAN_BUS_SET_FUNC(multi_stream, 2, uint16_t)
837*849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region, 2, uint16_t)
838*849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region_stream, 2, uint16_t)
839*849aef49SAndrew Turner 
840*849aef49SAndrew Turner CSAN_BUS_SET_FUNC(multi, 4, uint32_t)
841*849aef49SAndrew Turner CSAN_BUS_SET_FUNC(multi_stream, 4, uint32_t)
842*849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region, 4, uint32_t)
843*849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region_stream, 4, uint32_t)
844*849aef49SAndrew Turner 
845*849aef49SAndrew Turner #if !defined(__amd64__)
846*849aef49SAndrew Turner CSAN_BUS_SET_FUNC(multi, 8, uint64_t)
847*849aef49SAndrew Turner CSAN_BUS_SET_FUNC(multi_stream, 8, uint64_t)
848*849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region, 8, uint64_t)
849*849aef49SAndrew Turner CSAN_BUS_SET_FUNC(region_stream, 8, uint64_t)
850*849aef49SAndrew Turner #endif
851*849aef49SAndrew Turner 
852