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