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