xref: /freebsd/sys/kern/subr_csan.c (revision d4eeb02986980bf33dd56c41ceb9fc5f180c0d47)
1 /*	$NetBSD: subr_csan.c,v 1.5 2019/11/15 08:11:37 maxv Exp $	*/
2 
3 /*
4  * Copyright (c) 2019 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  * Copyright (c) 2019 Andrew Turner
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Maxime Villard.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #define	SAN_RUNTIME
34 
35 #include "opt_ddb.h"
36 
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
39 
40 #include <sys/param.h>
41 #include <sys/kernel.h>
42 #include <sys/bus.h>
43 #include <sys/conf.h>
44 #include <sys/cpu.h>
45 #include <sys/csan.h>
46 #include <sys/proc.h>
47 #include <sys/smp.h>
48 #include <sys/systm.h>
49 
50 #include <ddb/ddb.h>
51 #include <ddb/db_sym.h>
52 
53 #ifdef KCSAN_PANIC
54 #define REPORT panic
55 #else
56 #define REPORT printf
57 #endif
58 
59 typedef struct {
60 	uintptr_t addr;
61 	uint32_t size;
62 	bool write:1;
63 	bool atomic:1;
64 	uintptr_t pc;
65 } csan_cell_t;
66 
67 typedef struct {
68 	bool inited;
69 	uint32_t cnt;
70 	csan_cell_t cell;
71 } csan_cpu_t;
72 
73 static csan_cpu_t kcsan_cpus[MAXCPU];
74 static bool kcsan_enabled __read_mostly;
75 
76 #define __RET_ADDR	(uintptr_t)__builtin_return_address(0)
77 
78 #define KCSAN_NACCESSES	1024
79 #define KCSAN_DELAY	10	/* 10 microseconds */
80 
81 /* -------------------------------------------------------------------------- */
82 
83 /* The MD code. */
84 #include <machine/csan.h>
85 
86 /* -------------------------------------------------------------------------- */
87 
88 static void
89 kcsan_enable(void *dummy __unused)
90 {
91 
92 	printf("Enabling KCSCAN, expect reduced performance.\n");
93 	kcsan_enabled = true;
94 }
95 SYSINIT(kcsan_enable, SI_SUB_SMP, SI_ORDER_SECOND, kcsan_enable, NULL);
96 
97 void
98 kcsan_cpu_init(u_int cpu)
99 {
100 	kcsan_cpus[cpu].inited = true;
101 }
102 
103 /* -------------------------------------------------------------------------- */
104 
105 static inline void
106 kcsan_report(csan_cell_t *new, u_int newcpu, csan_cell_t *old, u_int oldcpu)
107 {
108 	const char *newsym, *oldsym;
109 #ifdef DDB
110 	c_db_sym_t sym;
111 	db_expr_t offset;
112 
113 	sym = db_search_symbol((vm_offset_t)new->pc, DB_STGY_PROC, &offset);
114 	db_symbol_values(sym, &newsym, NULL);
115 
116 	sym = db_search_symbol((vm_offset_t)old->pc, DB_STGY_PROC, &offset);
117 	db_symbol_values(sym, &oldsym, NULL);
118 #else
119 	newsym = "";
120 	oldsym = "";
121 #endif
122 	REPORT("CSan: Racy Access "
123 	    "[Cpu%u %s%s Addr=%p Size=%u PC=%p<%s>] "
124 	    "[Cpu%u %s%s Addr=%p Size=%u PC=%p<%s>]\n",
125 	    newcpu,
126 	    (new->atomic ? "Atomic " : ""), (new->write ? "Write" : "Read"),
127 	    (void *)new->addr, new->size, (void *)new->pc, newsym,
128 	    oldcpu,
129 	    (old->atomic ? "Atomic " : ""), (old->write ? "Write" : "Read"),
130 	    (void *)old->addr, old->size, (void *)old->pc, oldsym);
131 	kcsan_md_unwind();
132 }
133 
134 static inline bool
135 kcsan_access_is_atomic(csan_cell_t *new, csan_cell_t *old)
136 {
137 	if (new->write && !new->atomic)
138 		return false;
139 	if (old->write && !old->atomic)
140 		return false;
141 	return true;
142 }
143 
144 static inline void
145 kcsan_access(uintptr_t addr, size_t size, bool write, bool atomic, uintptr_t pc)
146 {
147 	csan_cell_t old, new;
148 	csan_cpu_t *cpu;
149 	uint64_t intr;
150 	size_t i;
151 
152 	if (__predict_false(!kcsan_enabled))
153 		return;
154 	if (__predict_false(kcsan_md_unsupported((vm_offset_t)addr)))
155 		return;
156 	if (KERNEL_PANICKED())
157 		return;
158 
159 	new.addr = addr;
160 	new.size = size;
161 	new.write = write;
162 	new.atomic = atomic;
163 	new.pc = pc;
164 
165 	CPU_FOREACH(i) {
166 		__builtin_memcpy(&old, &kcsan_cpus[i].cell, sizeof(old));
167 
168 		if (old.addr + old.size <= new.addr)
169 			continue;
170 		if (new.addr + new.size <= old.addr)
171 			continue;
172 		if (__predict_true(!old.write && !new.write))
173 			continue;
174 		if (__predict_true(kcsan_access_is_atomic(&new, &old)))
175 			continue;
176 
177 		kcsan_report(&new, PCPU_GET(cpuid), &old, i);
178 		break;
179 	}
180 
181 	if (__predict_false(!kcsan_md_is_avail()))
182 		return;
183 
184 	kcsan_md_disable_intrs(&intr);
185 
186 	cpu = &kcsan_cpus[PCPU_GET(cpuid)];
187 	if (__predict_false(!cpu->inited))
188 		goto out;
189 	cpu->cnt = (cpu->cnt + 1) % KCSAN_NACCESSES;
190 	if (__predict_true(cpu->cnt != 0))
191 		goto out;
192 
193 	__builtin_memcpy(&cpu->cell, &new, sizeof(new));
194 	kcsan_md_delay(KCSAN_DELAY);
195 	__builtin_memset(&cpu->cell, 0, sizeof(new));
196 
197 out:
198 	kcsan_md_enable_intrs(&intr);
199 }
200 
201 #define CSAN_READ(size)							\
202 	void __tsan_read##size(uintptr_t);				\
203 	void __tsan_read##size(uintptr_t addr)				\
204 	{								\
205 		kcsan_access(addr, size, false, false, __RET_ADDR);	\
206 	}								\
207 	void __tsan_unaligned_read##size(uintptr_t);			\
208 	void __tsan_unaligned_read##size(uintptr_t addr)		\
209 	{								\
210 		kcsan_access(addr, size, false, false, __RET_ADDR);	\
211 	}
212 
213 CSAN_READ(1)
214 CSAN_READ(2)
215 CSAN_READ(4)
216 CSAN_READ(8)
217 CSAN_READ(16)
218 
219 #define CSAN_WRITE(size)						\
220 	void __tsan_write##size(uintptr_t);				\
221 	void __tsan_write##size(uintptr_t addr)				\
222 	{								\
223 		kcsan_access(addr, size, true, false, __RET_ADDR);	\
224 	}								\
225 	void __tsan_unaligned_write##size(uintptr_t);			\
226 	void __tsan_unaligned_write##size(uintptr_t addr)		\
227 	{								\
228 		kcsan_access(addr, size, true, false, __RET_ADDR);	\
229 	}
230 
231 CSAN_WRITE(1)
232 CSAN_WRITE(2)
233 CSAN_WRITE(4)
234 CSAN_WRITE(8)
235 CSAN_WRITE(16)
236 
237 void __tsan_read_range(uintptr_t, size_t);
238 void __tsan_write_range(uintptr_t, size_t);
239 
240 void
241 __tsan_read_range(uintptr_t addr, size_t size)
242 {
243 	kcsan_access(addr, size, false, false, __RET_ADDR);
244 }
245 
246 void
247 __tsan_write_range(uintptr_t addr, size_t size)
248 {
249 	kcsan_access(addr, size, true, false, __RET_ADDR);
250 }
251 
252 void __tsan_init(void);
253 void __tsan_func_entry(void *);
254 void __tsan_func_exit(void);
255 
256 void
257 __tsan_init(void)
258 {
259 }
260 
261 void
262 __tsan_func_entry(void *call_pc)
263 {
264 }
265 
266 void
267 __tsan_func_exit(void)
268 {
269 }
270 
271 /* -------------------------------------------------------------------------- */
272 
273 void *
274 kcsan_memcpy(void *dst, const void *src, size_t len)
275 {
276 	kcsan_access((uintptr_t)src, len, false, false, __RET_ADDR);
277 	kcsan_access((uintptr_t)dst, len, true, false, __RET_ADDR);
278 	return __builtin_memcpy(dst, src, len);
279 }
280 
281 int
282 kcsan_memcmp(const void *b1, const void *b2, size_t len)
283 {
284 	kcsan_access((uintptr_t)b1, len, false, false, __RET_ADDR);
285 	kcsan_access((uintptr_t)b2, len, false, false, __RET_ADDR);
286 	return __builtin_memcmp(b1, b2, len);
287 }
288 
289 void *
290 kcsan_memset(void *b, int c, size_t len)
291 {
292 	kcsan_access((uintptr_t)b, len, true, false, __RET_ADDR);
293 	return __builtin_memset(b, c, len);
294 }
295 
296 void *
297 kcsan_memmove(void *dst, const void *src, size_t len)
298 {
299 	kcsan_access((uintptr_t)src, len, false, false, __RET_ADDR);
300 	kcsan_access((uintptr_t)dst, len, true, false, __RET_ADDR);
301 	return __builtin_memmove(dst, src, len);
302 }
303 
304 char *
305 kcsan_strcpy(char *dst, const char *src)
306 {
307 	char *save = dst;
308 
309 	while (1) {
310 		kcsan_access((uintptr_t)src, 1, false, false, __RET_ADDR);
311 		kcsan_access((uintptr_t)dst, 1, true, false, __RET_ADDR);
312 		*dst = *src;
313 		if (*src == '\0')
314 			break;
315 		src++, dst++;
316 	}
317 
318 	return save;
319 }
320 
321 int
322 kcsan_strcmp(const char *s1, const char *s2)
323 {
324 	while (1) {
325 		kcsan_access((uintptr_t)s1, 1, false, false, __RET_ADDR);
326 		kcsan_access((uintptr_t)s2, 1, false, false, __RET_ADDR);
327 		if (*s1 != *s2)
328 			break;
329 		if (*s1 == '\0')
330 			return 0;
331 		s1++, s2++;
332 	}
333 
334 	return (*(const unsigned char *)s1 - *(const unsigned char *)s2);
335 }
336 
337 size_t
338 kcsan_strlen(const char *str)
339 {
340 	const char *s;
341 
342 	s = str;
343 	while (1) {
344 		kcsan_access((uintptr_t)s, 1, false, false, __RET_ADDR);
345 		if (*s == '\0')
346 			break;
347 		s++;
348 	}
349 
350 	return (s - str);
351 }
352 
353 int
354 kcsan_copyin(const void *uaddr, void *kaddr, size_t len)
355 {
356 	kcsan_access((uintptr_t)kaddr, len, true, false, __RET_ADDR);
357 	return copyin(uaddr, kaddr, len);
358 }
359 
360 int
361 kcsan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
362 {
363 	kcsan_access((uintptr_t)kaddr, len, true, false, __RET_ADDR);
364 	return copyinstr(uaddr, kaddr, len, done);
365 }
366 
367 int
368 kcsan_copyout(const void *kaddr, void *uaddr, size_t len)
369 {
370 	kcsan_access((uintptr_t)kaddr, len, false, false, __RET_ADDR);
371 	return copyout(kaddr, uaddr, len);
372 }
373 
374 /* -------------------------------------------------------------------------- */
375 
376 #include <machine/atomic.h>
377 #include <sys/atomic_san.h>
378 
379 #define	_CSAN_ATOMIC_FUNC_ADD(name, type)				\
380 	void kcsan_atomic_add_##name(volatile type *ptr, type val)	\
381 	{								\
382 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
383 		    __RET_ADDR);					\
384 		atomic_add_##name(ptr, val); 				\
385 	}
386 
387 #define	CSAN_ATOMIC_FUNC_ADD(name, type)				\
388 	_CSAN_ATOMIC_FUNC_ADD(name, type)				\
389 	_CSAN_ATOMIC_FUNC_ADD(acq_##name, type)				\
390 	_CSAN_ATOMIC_FUNC_ADD(rel_##name, type)
391 
392 #define	_CSAN_ATOMIC_FUNC_CLEAR(name, type)				\
393 	void kcsan_atomic_clear_##name(volatile type *ptr, type val)	\
394 	{								\
395 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
396 		    __RET_ADDR);					\
397 		atomic_clear_##name(ptr, val); 				\
398 	}
399 
400 #define	CSAN_ATOMIC_FUNC_CLEAR(name, type)				\
401 	_CSAN_ATOMIC_FUNC_CLEAR(name, type)				\
402 	_CSAN_ATOMIC_FUNC_CLEAR(acq_##name, type)			\
403 	_CSAN_ATOMIC_FUNC_CLEAR(rel_##name, type)
404 
405 #define	_CSAN_ATOMIC_FUNC_CMPSET(name, type)				\
406 	int kcsan_atomic_cmpset_##name(volatile type *ptr, type val1,	\
407 	    type val2)							\
408 	{								\
409 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
410 		    __RET_ADDR);					\
411 		return (atomic_cmpset_##name(ptr, val1, val2));		\
412 	}
413 
414 #define	CSAN_ATOMIC_FUNC_CMPSET(name, type)				\
415 	_CSAN_ATOMIC_FUNC_CMPSET(name, type)				\
416 	_CSAN_ATOMIC_FUNC_CMPSET(acq_##name, type)			\
417 	_CSAN_ATOMIC_FUNC_CMPSET(rel_##name, type)
418 
419 #define	_CSAN_ATOMIC_FUNC_FCMPSET(name, type)				\
420 	int kcsan_atomic_fcmpset_##name(volatile type *ptr, type *val1,	\
421 	    type val2)							\
422 	{								\
423 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
424 		    __RET_ADDR);					\
425 		return (atomic_fcmpset_##name(ptr, val1, val2));	\
426 	}
427 
428 #define	CSAN_ATOMIC_FUNC_FCMPSET(name, type)				\
429 	_CSAN_ATOMIC_FUNC_FCMPSET(name, type)				\
430 	_CSAN_ATOMIC_FUNC_FCMPSET(acq_##name, type)			\
431 	_CSAN_ATOMIC_FUNC_FCMPSET(rel_##name, type)
432 
433 #define	CSAN_ATOMIC_FUNC_FETCHADD(name, type)				\
434 	type kcsan_atomic_fetchadd_##name(volatile type *ptr, type val)	\
435 	{								\
436 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
437 		    __RET_ADDR);					\
438 		return (atomic_fetchadd_##name(ptr, val));		\
439 	}
440 
441 #define	_CSAN_ATOMIC_FUNC_LOAD(name, type)				\
442 	type kcsan_atomic_load_##name(volatile type *ptr)		\
443 	{								\
444 		kcsan_access((uintptr_t)ptr, sizeof(type), false, true,	\
445 		    __RET_ADDR);					\
446 		return (atomic_load_##name(ptr));			\
447 	}
448 
449 #define	CSAN_ATOMIC_FUNC_LOAD(name, type)				\
450 	_CSAN_ATOMIC_FUNC_LOAD(name, type)				\
451 	_CSAN_ATOMIC_FUNC_LOAD(acq_##name, type)			\
452 
453 #define	CSAN_ATOMIC_FUNC_READANDCLEAR(name, type)			\
454 	type kcsan_atomic_readandclear_##name(volatile type *ptr)	\
455 	{								\
456 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
457 		    __RET_ADDR);					\
458 		return (atomic_readandclear_##name(ptr));		\
459 	}
460 
461 #define	_CSAN_ATOMIC_FUNC_SET(name, type)				\
462 	void kcsan_atomic_set_##name(volatile type *ptr, type val)	\
463 	{								\
464 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
465 		    __RET_ADDR);					\
466 		atomic_set_##name(ptr, val); 				\
467 	}
468 
469 #define	CSAN_ATOMIC_FUNC_SET(name, type)				\
470 	_CSAN_ATOMIC_FUNC_SET(name, type)				\
471 	_CSAN_ATOMIC_FUNC_SET(acq_##name, type)				\
472 	_CSAN_ATOMIC_FUNC_SET(rel_##name, type)
473 
474 #define	_CSAN_ATOMIC_FUNC_SUBTRACT(name, type)				\
475 	void kcsan_atomic_subtract_##name(volatile type *ptr, type val)	\
476 	{								\
477 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
478 		    __RET_ADDR);					\
479 		atomic_subtract_##name(ptr, val); 			\
480 	}
481 
482 #define	CSAN_ATOMIC_FUNC_SUBTRACT(name, type)				\
483 	_CSAN_ATOMIC_FUNC_SUBTRACT(name, type)				\
484 	_CSAN_ATOMIC_FUNC_SUBTRACT(acq_##name, type)			\
485 	_CSAN_ATOMIC_FUNC_SUBTRACT(rel_##name, type)
486 
487 #define	_CSAN_ATOMIC_FUNC_STORE(name, type)				\
488 	void kcsan_atomic_store_##name(volatile type *ptr, type val)	\
489 	{								\
490 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
491 		    __RET_ADDR);					\
492 		atomic_store_##name(ptr, val); 				\
493 	}
494 
495 #define	CSAN_ATOMIC_FUNC_STORE(name, type)				\
496 	_CSAN_ATOMIC_FUNC_STORE(name, type)				\
497 	_CSAN_ATOMIC_FUNC_STORE(rel_##name, type)
498 
499 #define	CSAN_ATOMIC_FUNC_SWAP(name, type)				\
500 	type kcsan_atomic_swap_##name(volatile type *ptr, type val)	\
501 	{								\
502 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
503 		    __RET_ADDR);					\
504 		return(atomic_swap_##name(ptr, val)); 			\
505 	}
506 
507 #define	CSAN_ATOMIC_FUNC_TESTANDCLEAR(name, type)			\
508 	int kcsan_atomic_testandclear_##name(volatile type *ptr, u_int val) \
509 	{								\
510 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
511 		    __RET_ADDR);					\
512 		return(atomic_testandclear_##name(ptr, val)); 		\
513 	}
514 
515 #define	CSAN_ATOMIC_FUNC_TESTANDSET(name, type)				\
516 	int kcsan_atomic_testandset_##name(volatile type *ptr, u_int val) \
517 	{								\
518 		kcsan_access((uintptr_t)ptr, sizeof(type), true, true,	\
519 		    __RET_ADDR);					\
520 		return (atomic_testandset_##name(ptr, val)); 		\
521 	}
522 
523 CSAN_ATOMIC_FUNC_ADD(8, uint8_t)
524 CSAN_ATOMIC_FUNC_CLEAR(8, uint8_t)
525 CSAN_ATOMIC_FUNC_CMPSET(8, uint8_t)
526 CSAN_ATOMIC_FUNC_FCMPSET(8, uint8_t)
527 CSAN_ATOMIC_FUNC_LOAD(8, uint8_t)
528 CSAN_ATOMIC_FUNC_SET(8, uint8_t)
529 CSAN_ATOMIC_FUNC_SUBTRACT(8, uint8_t)
530 _CSAN_ATOMIC_FUNC_STORE(8, uint8_t)
531 #if 0
532 CSAN_ATOMIC_FUNC_FETCHADD(8, uint8_t)
533 CSAN_ATOMIC_FUNC_READANDCLEAR(8, uint8_t)
534 CSAN_ATOMIC_FUNC_SWAP(8, uint8_t)
535 CSAN_ATOMIC_FUNC_TESTANDCLEAR(8, uint8_t)
536 CSAN_ATOMIC_FUNC_TESTANDSET(8, uint8_t)
537 #endif
538 
539 CSAN_ATOMIC_FUNC_ADD(16, uint16_t)
540 CSAN_ATOMIC_FUNC_CLEAR(16, uint16_t)
541 CSAN_ATOMIC_FUNC_CMPSET(16, uint16_t)
542 CSAN_ATOMIC_FUNC_FCMPSET(16, uint16_t)
543 CSAN_ATOMIC_FUNC_LOAD(16, uint16_t)
544 CSAN_ATOMIC_FUNC_SET(16, uint16_t)
545 CSAN_ATOMIC_FUNC_SUBTRACT(16, uint16_t)
546 _CSAN_ATOMIC_FUNC_STORE(16, uint16_t)
547 #if 0
548 CSAN_ATOMIC_FUNC_FETCHADD(16, uint16_t)
549 CSAN_ATOMIC_FUNC_READANDCLEAR(16, uint16_t)
550 CSAN_ATOMIC_FUNC_SWAP(16, uint16_t)
551 CSAN_ATOMIC_FUNC_TESTANDCLEAR(16, uint16_t)
552 CSAN_ATOMIC_FUNC_TESTANDSET(16, uint16_t)
553 #endif
554 
555 CSAN_ATOMIC_FUNC_ADD(32, uint32_t)
556 CSAN_ATOMIC_FUNC_CLEAR(32, uint32_t)
557 CSAN_ATOMIC_FUNC_CMPSET(32, uint32_t)
558 CSAN_ATOMIC_FUNC_FCMPSET(32, uint32_t)
559 CSAN_ATOMIC_FUNC_FETCHADD(32, uint32_t)
560 CSAN_ATOMIC_FUNC_LOAD(32, uint32_t)
561 CSAN_ATOMIC_FUNC_READANDCLEAR(32, uint32_t)
562 CSAN_ATOMIC_FUNC_SET(32, uint32_t)
563 CSAN_ATOMIC_FUNC_SUBTRACT(32, uint32_t)
564 CSAN_ATOMIC_FUNC_STORE(32, uint32_t)
565 CSAN_ATOMIC_FUNC_SWAP(32, uint32_t)
566 CSAN_ATOMIC_FUNC_TESTANDCLEAR(32, uint32_t)
567 CSAN_ATOMIC_FUNC_TESTANDSET(32, uint32_t)
568 
569 CSAN_ATOMIC_FUNC_ADD(64, uint64_t)
570 CSAN_ATOMIC_FUNC_CLEAR(64, uint64_t)
571 CSAN_ATOMIC_FUNC_CMPSET(64, uint64_t)
572 CSAN_ATOMIC_FUNC_FCMPSET(64, uint64_t)
573 CSAN_ATOMIC_FUNC_FETCHADD(64, uint64_t)
574 CSAN_ATOMIC_FUNC_LOAD(64, uint64_t)
575 CSAN_ATOMIC_FUNC_READANDCLEAR(64, uint64_t)
576 CSAN_ATOMIC_FUNC_SET(64, uint64_t)
577 CSAN_ATOMIC_FUNC_SUBTRACT(64, uint64_t)
578 CSAN_ATOMIC_FUNC_STORE(64, uint64_t)
579 CSAN_ATOMIC_FUNC_SWAP(64, uint64_t)
580 CSAN_ATOMIC_FUNC_TESTANDCLEAR(64, uint64_t)
581 CSAN_ATOMIC_FUNC_TESTANDSET(64, uint64_t)
582 
583 CSAN_ATOMIC_FUNC_ADD(char, uint8_t)
584 CSAN_ATOMIC_FUNC_CLEAR(char, uint8_t)
585 CSAN_ATOMIC_FUNC_CMPSET(char, uint8_t)
586 CSAN_ATOMIC_FUNC_FCMPSET(char, uint8_t)
587 CSAN_ATOMIC_FUNC_LOAD(char, uint8_t)
588 CSAN_ATOMIC_FUNC_SET(char, uint8_t)
589 CSAN_ATOMIC_FUNC_SUBTRACT(char, uint8_t)
590 _CSAN_ATOMIC_FUNC_STORE(char, uint8_t)
591 #if 0
592 CSAN_ATOMIC_FUNC_FETCHADD(char, uint8_t)
593 CSAN_ATOMIC_FUNC_READANDCLEAR(char, uint8_t)
594 CSAN_ATOMIC_FUNC_SWAP(char, uint8_t)
595 CSAN_ATOMIC_FUNC_TESTANDCLEAR(char, uint8_t)
596 CSAN_ATOMIC_FUNC_TESTANDSET(char, uint8_t)
597 #endif
598 
599 CSAN_ATOMIC_FUNC_ADD(short, uint16_t)
600 CSAN_ATOMIC_FUNC_CLEAR(short, uint16_t)
601 CSAN_ATOMIC_FUNC_CMPSET(short, uint16_t)
602 CSAN_ATOMIC_FUNC_FCMPSET(short, uint16_t)
603 CSAN_ATOMIC_FUNC_LOAD(short, uint16_t)
604 CSAN_ATOMIC_FUNC_SET(short, uint16_t)
605 CSAN_ATOMIC_FUNC_SUBTRACT(short, uint16_t)
606 _CSAN_ATOMIC_FUNC_STORE(short, uint16_t)
607 #if 0
608 CSAN_ATOMIC_FUNC_FETCHADD(short, uint16_t)
609 CSAN_ATOMIC_FUNC_READANDCLEAR(short, uint16_t)
610 CSAN_ATOMIC_FUNC_SWAP(short, uint16_t)
611 CSAN_ATOMIC_FUNC_TESTANDCLEAR(short, uint16_t)
612 CSAN_ATOMIC_FUNC_TESTANDSET(short, uint16_t)
613 #endif
614 
615 CSAN_ATOMIC_FUNC_ADD(int, u_int)
616 CSAN_ATOMIC_FUNC_CLEAR(int, u_int)
617 CSAN_ATOMIC_FUNC_CMPSET(int, u_int)
618 CSAN_ATOMIC_FUNC_FCMPSET(int, u_int)
619 CSAN_ATOMIC_FUNC_FETCHADD(int, u_int)
620 CSAN_ATOMIC_FUNC_LOAD(int, u_int)
621 CSAN_ATOMIC_FUNC_READANDCLEAR(int, u_int)
622 CSAN_ATOMIC_FUNC_SET(int, u_int)
623 CSAN_ATOMIC_FUNC_SUBTRACT(int, u_int)
624 CSAN_ATOMIC_FUNC_STORE(int, u_int)
625 CSAN_ATOMIC_FUNC_SWAP(int, u_int)
626 CSAN_ATOMIC_FUNC_TESTANDCLEAR(int, u_int)
627 CSAN_ATOMIC_FUNC_TESTANDSET(int, u_int)
628 
629 CSAN_ATOMIC_FUNC_ADD(long, u_long)
630 CSAN_ATOMIC_FUNC_CLEAR(long, u_long)
631 CSAN_ATOMIC_FUNC_CMPSET(long, u_long)
632 CSAN_ATOMIC_FUNC_FCMPSET(long, u_long)
633 CSAN_ATOMIC_FUNC_FETCHADD(long, u_long)
634 CSAN_ATOMIC_FUNC_LOAD(long, u_long)
635 CSAN_ATOMIC_FUNC_READANDCLEAR(long, u_long)
636 CSAN_ATOMIC_FUNC_SET(long, u_long)
637 CSAN_ATOMIC_FUNC_SUBTRACT(long, u_long)
638 CSAN_ATOMIC_FUNC_STORE(long, u_long)
639 CSAN_ATOMIC_FUNC_SWAP(long, u_long)
640 CSAN_ATOMIC_FUNC_TESTANDCLEAR(long, u_long)
641 CSAN_ATOMIC_FUNC_TESTANDSET(long, u_long)
642 CSAN_ATOMIC_FUNC_TESTANDSET(acq_long, u_long)
643 
644 CSAN_ATOMIC_FUNC_ADD(ptr, uintptr_t)
645 CSAN_ATOMIC_FUNC_CLEAR(ptr, uintptr_t)
646 CSAN_ATOMIC_FUNC_CMPSET(ptr, uintptr_t)
647 CSAN_ATOMIC_FUNC_FCMPSET(ptr, uintptr_t)
648 #if !defined(__amd64__)
649 CSAN_ATOMIC_FUNC_FETCHADD(ptr, uintptr_t)
650 #endif
651 CSAN_ATOMIC_FUNC_LOAD(ptr, uintptr_t)
652 CSAN_ATOMIC_FUNC_READANDCLEAR(ptr, uintptr_t)
653 CSAN_ATOMIC_FUNC_SET(ptr, uintptr_t)
654 CSAN_ATOMIC_FUNC_SUBTRACT(ptr, uintptr_t)
655 CSAN_ATOMIC_FUNC_STORE(ptr, uintptr_t)
656 CSAN_ATOMIC_FUNC_SWAP(ptr, uintptr_t)
657 #if 0
658 CSAN_ATOMIC_FUNC_TESTANDCLEAR(ptr, uintptr_t)
659 CSAN_ATOMIC_FUNC_TESTANDSET(ptr, uintptr_t)
660 #endif
661 
662 #define	CSAN_ATOMIC_FUNC_THREAD_FENCE(name)				\
663 	void kcsan_atomic_thread_fence_##name(void)			\
664 	{								\
665 		atomic_thread_fence_##name();				\
666 	}
667 
668 CSAN_ATOMIC_FUNC_THREAD_FENCE(acq)
669 CSAN_ATOMIC_FUNC_THREAD_FENCE(acq_rel)
670 CSAN_ATOMIC_FUNC_THREAD_FENCE(rel)
671 CSAN_ATOMIC_FUNC_THREAD_FENCE(seq_cst)
672 
673 void
674 kcsan_atomic_interrupt_fence(void)
675 {
676 	atomic_interrupt_fence();
677 }
678 
679 /* -------------------------------------------------------------------------- */
680 
681 #include <sys/bus.h>
682 #include <machine/bus.h>
683 #include <sys/bus_san.h>
684 
685 int
686 kcsan_bus_space_map(bus_space_tag_t tag, bus_addr_t hnd, bus_size_t size,
687     int flags, bus_space_handle_t *handlep)
688 {
689 
690 	return (bus_space_map(tag, hnd, size, flags, handlep));
691 }
692 
693 void
694 kcsan_bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t hnd,
695     bus_size_t size)
696 {
697 
698 	bus_space_unmap(tag, hnd, size);
699 }
700 
701 int
702 kcsan_bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t hnd,
703     bus_size_t offset, bus_size_t size, bus_space_handle_t *handlep)
704 {
705 
706 	return (bus_space_subregion(tag, hnd, offset, size, handlep));
707 }
708 
709 #if !defined(__amd64__)
710 int
711 kcsan_bus_space_alloc(bus_space_tag_t tag, bus_addr_t reg_start,
712     bus_addr_t reg_end, bus_size_t size, bus_size_t alignment,
713     bus_size_t boundary, int flags, bus_addr_t *addrp,
714     bus_space_handle_t *handlep)
715 {
716 
717 	return (bus_space_alloc(tag, reg_start, reg_end, size, alignment,
718 	    boundary, flags, addrp, handlep));
719 }
720 #endif
721 
722 void
723 kcsan_bus_space_free(bus_space_tag_t tag, bus_space_handle_t hnd,
724     bus_size_t size)
725 {
726 
727 	bus_space_free(tag, hnd, size);
728 }
729 
730 void
731 kcsan_bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t hnd,
732     bus_size_t offset, bus_size_t size, int flags)
733 {
734 
735 	bus_space_barrier(tag, hnd, offset, size, flags);
736 }
737 
738 #define CSAN_BUS_READ_FUNC(func, width, type)				\
739 	type kcsan_bus_space_read##func##_##width(bus_space_tag_t tag,	\
740 	    bus_space_handle_t hnd, bus_size_t offset)			\
741 	{								\
742 		return (bus_space_read##func##_##width(tag, hnd,	\
743 		    offset));						\
744 	}								\
745 
746 #define CSAN_BUS_READ_PTR_FUNC(func, width, type)			\
747 	void kcsan_bus_space_read_##func##_##width(bus_space_tag_t tag,	\
748 	    bus_space_handle_t hnd, bus_size_t size, type *buf,		\
749 	    bus_size_t count)						\
750 	{								\
751 		kcsan_access((uintptr_t)buf, sizeof(type) * count,	\
752 		    false, false, __RET_ADDR);				\
753 		bus_space_read_##func##_##width(tag, hnd, size, buf, 	\
754 		    count);						\
755 	}
756 
757 CSAN_BUS_READ_FUNC(, 1, uint8_t)
758 CSAN_BUS_READ_FUNC(_stream, 1, uint8_t)
759 CSAN_BUS_READ_PTR_FUNC(multi, 1, uint8_t)
760 CSAN_BUS_READ_PTR_FUNC(multi_stream, 1, uint8_t)
761 CSAN_BUS_READ_PTR_FUNC(region, 1, uint8_t)
762 CSAN_BUS_READ_PTR_FUNC(region_stream, 1, uint8_t)
763 
764 CSAN_BUS_READ_FUNC(, 2, uint16_t)
765 CSAN_BUS_READ_FUNC(_stream, 2, uint16_t)
766 CSAN_BUS_READ_PTR_FUNC(multi, 2, uint16_t)
767 CSAN_BUS_READ_PTR_FUNC(multi_stream, 2, uint16_t)
768 CSAN_BUS_READ_PTR_FUNC(region, 2, uint16_t)
769 CSAN_BUS_READ_PTR_FUNC(region_stream, 2, uint16_t)
770 
771 CSAN_BUS_READ_FUNC(, 4, uint32_t)
772 CSAN_BUS_READ_FUNC(_stream, 4, uint32_t)
773 CSAN_BUS_READ_PTR_FUNC(multi, 4, uint32_t)
774 CSAN_BUS_READ_PTR_FUNC(multi_stream, 4, uint32_t)
775 CSAN_BUS_READ_PTR_FUNC(region, 4, uint32_t)
776 CSAN_BUS_READ_PTR_FUNC(region_stream, 4, uint32_t)
777 
778 CSAN_BUS_READ_FUNC(, 8, uint64_t)
779 #if defined(__aarch64__)
780 CSAN_BUS_READ_FUNC(_stream, 8, uint64_t)
781 CSAN_BUS_READ_PTR_FUNC(multi, 8, uint64_t)
782 CSAN_BUS_READ_PTR_FUNC(multi_stream, 8, uint64_t)
783 CSAN_BUS_READ_PTR_FUNC(region, 8, uint64_t)
784 CSAN_BUS_READ_PTR_FUNC(region_stream, 8, uint64_t)
785 #endif
786 
787 #define CSAN_BUS_WRITE_FUNC(func, width, type)				\
788 	void kcsan_bus_space_write##func##_##width(bus_space_tag_t tag,		\
789 	    bus_space_handle_t hnd, bus_size_t offset, type value)	\
790 	{								\
791 		bus_space_write##func##_##width(tag, hnd, offset, value); \
792 	}								\
793 
794 #define CSAN_BUS_WRITE_PTR_FUNC(func, width, type)			\
795 	void kcsan_bus_space_write_##func##_##width(bus_space_tag_t tag, \
796 	    bus_space_handle_t hnd, bus_size_t size, const type *buf,	\
797 	    bus_size_t count)						\
798 	{								\
799 		kcsan_access((uintptr_t)buf, sizeof(type) * count,	\
800 		    true, false, __RET_ADDR);				\
801 		bus_space_write_##func##_##width(tag, hnd, size, buf, 	\
802 		    count);						\
803 	}
804 
805 CSAN_BUS_WRITE_FUNC(, 1, uint8_t)
806 CSAN_BUS_WRITE_FUNC(_stream, 1, uint8_t)
807 CSAN_BUS_WRITE_PTR_FUNC(multi, 1, uint8_t)
808 CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 1, uint8_t)
809 CSAN_BUS_WRITE_PTR_FUNC(region, 1, uint8_t)
810 CSAN_BUS_WRITE_PTR_FUNC(region_stream, 1, uint8_t)
811 
812 CSAN_BUS_WRITE_FUNC(, 2, uint16_t)
813 CSAN_BUS_WRITE_FUNC(_stream, 2, uint16_t)
814 CSAN_BUS_WRITE_PTR_FUNC(multi, 2, uint16_t)
815 CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 2, uint16_t)
816 CSAN_BUS_WRITE_PTR_FUNC(region, 2, uint16_t)
817 CSAN_BUS_WRITE_PTR_FUNC(region_stream, 2, uint16_t)
818 
819 CSAN_BUS_WRITE_FUNC(, 4, uint32_t)
820 CSAN_BUS_WRITE_FUNC(_stream, 4, uint32_t)
821 CSAN_BUS_WRITE_PTR_FUNC(multi, 4, uint32_t)
822 CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 4, uint32_t)
823 CSAN_BUS_WRITE_PTR_FUNC(region, 4, uint32_t)
824 CSAN_BUS_WRITE_PTR_FUNC(region_stream, 4, uint32_t)
825 
826 CSAN_BUS_WRITE_FUNC(, 8, uint64_t)
827 #if defined(__aarch64__)
828 CSAN_BUS_WRITE_FUNC(_stream, 8, uint64_t)
829 CSAN_BUS_WRITE_PTR_FUNC(multi, 8, uint64_t)
830 CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 8, uint64_t)
831 CSAN_BUS_WRITE_PTR_FUNC(region, 8, uint64_t)
832 CSAN_BUS_WRITE_PTR_FUNC(region_stream, 8, uint64_t)
833 #endif
834 
835 #define CSAN_BUS_SET_FUNC(func, width, type)				\
836 	void kcsan_bus_space_set_##func##_##width(bus_space_tag_t tag,	\
837 	    bus_space_handle_t hnd, bus_size_t offset, type value,	\
838 	    bus_size_t count)						\
839 	{								\
840 		bus_space_set_##func##_##width(tag, hnd, offset, value,	\
841 		    count);						\
842 	}
843 
844 CSAN_BUS_SET_FUNC(multi, 1, uint8_t)
845 CSAN_BUS_SET_FUNC(region, 1, uint8_t)
846 #if !defined(__aarch64__)
847 CSAN_BUS_SET_FUNC(multi_stream, 1, uint8_t)
848 CSAN_BUS_SET_FUNC(region_stream, 1, uint8_t)
849 #endif
850 
851 CSAN_BUS_SET_FUNC(multi, 2, uint16_t)
852 CSAN_BUS_SET_FUNC(region, 2, uint16_t)
853 #if !defined(__aarch64__)
854 CSAN_BUS_SET_FUNC(multi_stream, 2, uint16_t)
855 CSAN_BUS_SET_FUNC(region_stream, 2, uint16_t)
856 #endif
857 
858 CSAN_BUS_SET_FUNC(multi, 4, uint32_t)
859 CSAN_BUS_SET_FUNC(region, 4, uint32_t)
860 #if !defined(__aarch64__)
861 CSAN_BUS_SET_FUNC(multi_stream, 4, uint32_t)
862 CSAN_BUS_SET_FUNC(region_stream, 4, uint32_t)
863 #endif
864 
865 #if !defined(__amd64__)
866 CSAN_BUS_SET_FUNC(multi, 8, uint64_t)
867 CSAN_BUS_SET_FUNC(region, 8, uint64_t)
868 #if !defined(__aarch64__)
869 CSAN_BUS_SET_FUNC(multi_stream, 8, uint64_t)
870 CSAN_BUS_SET_FUNC(region_stream, 8, uint64_t)
871 #endif
872 #endif
873 
874 #define CSAN_BUS_PEEK_FUNC(width, type)					\
875 	int kcsan_bus_space_peek_##width(bus_space_tag_t tag,		\
876 	    bus_space_handle_t hnd, bus_size_t offset, type *value)	\
877 	{								\
878 		kcsan_access((uintptr_t)value, sizeof(type), true, false, \
879 		    __RET_ADDR);					\
880 		return (bus_space_peek_##width(tag, hnd, offset, value)); \
881 	}
882 
883 CSAN_BUS_PEEK_FUNC(1, uint8_t)
884 CSAN_BUS_PEEK_FUNC(2, uint16_t)
885 CSAN_BUS_PEEK_FUNC(4, uint32_t)
886 #if !defined(__i386__)
887 CSAN_BUS_PEEK_FUNC(8, uint64_t)
888 #endif
889 
890 #define CSAN_BUS_POKE_FUNC(width, type)					\
891 	int kcsan_bus_space_poke_##width(bus_space_tag_t tag,		\
892 	    bus_space_handle_t hnd, bus_size_t offset, type value)	\
893 	{								\
894 		return (bus_space_poke_##width(tag, hnd, offset, value)); \
895 	}
896 
897 CSAN_BUS_POKE_FUNC(1, uint8_t)
898 CSAN_BUS_POKE_FUNC(2, uint16_t)
899 CSAN_BUS_POKE_FUNC(4, uint32_t)
900 #if !defined(__i386__)
901 CSAN_BUS_POKE_FUNC(8, uint64_t)
902 #endif
903