]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/kern/subr_csan.c
ssh: Update to OpenSSH 9.4p1
[FreeBSD/FreeBSD.git] / sys / kern / subr_csan.c
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 __strong_reference(kcsan_memcpy, __tsan_memcpy);
305 __strong_reference(kcsan_memset, __tsan_memset);
306 __strong_reference(kcsan_memmove, __tsan_memmove);
307
308 char *
309 kcsan_strcpy(char *dst, const char *src)
310 {
311         char *save = dst;
312
313         while (1) {
314                 kcsan_access((uintptr_t)src, 1, false, false, __RET_ADDR);
315                 kcsan_access((uintptr_t)dst, 1, true, false, __RET_ADDR);
316                 *dst = *src;
317                 if (*src == '\0')
318                         break;
319                 src++, dst++;
320         }
321
322         return save;
323 }
324
325 int
326 kcsan_strcmp(const char *s1, const char *s2)
327 {
328         while (1) {
329                 kcsan_access((uintptr_t)s1, 1, false, false, __RET_ADDR);
330                 kcsan_access((uintptr_t)s2, 1, false, false, __RET_ADDR);
331                 if (*s1 != *s2)
332                         break;
333                 if (*s1 == '\0')
334                         return 0;
335                 s1++, s2++;
336         }
337
338         return (*(const unsigned char *)s1 - *(const unsigned char *)s2);
339 }
340
341 size_t
342 kcsan_strlen(const char *str)
343 {
344         const char *s;
345
346         s = str;
347         while (1) {
348                 kcsan_access((uintptr_t)s, 1, false, false, __RET_ADDR);
349                 if (*s == '\0')
350                         break;
351                 s++;
352         }
353
354         return (s - str);
355 }
356
357 int
358 kcsan_copyin(const void *uaddr, void *kaddr, size_t len)
359 {
360         kcsan_access((uintptr_t)kaddr, len, true, false, __RET_ADDR);
361         return copyin(uaddr, kaddr, len);
362 }
363
364 int
365 kcsan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
366 {
367         kcsan_access((uintptr_t)kaddr, len, true, false, __RET_ADDR);
368         return copyinstr(uaddr, kaddr, len, done);
369 }
370
371 int
372 kcsan_copyout(const void *kaddr, void *uaddr, size_t len)
373 {
374         kcsan_access((uintptr_t)kaddr, len, false, false, __RET_ADDR);
375         return copyout(kaddr, uaddr, len);
376 }
377
378 /* -------------------------------------------------------------------------- */
379
380 #include <machine/atomic.h>
381 #include <sys/atomic_san.h>
382
383 #define _CSAN_ATOMIC_FUNC_ADD(name, type)                               \
384         void kcsan_atomic_add_##name(volatile type *ptr, type val)      \
385         {                                                               \
386                 kcsan_access((uintptr_t)ptr, sizeof(type), true, true,  \
387                     __RET_ADDR);                                        \
388                 atomic_add_##name(ptr, val);                            \
389         }
390
391 #define CSAN_ATOMIC_FUNC_ADD(name, type)                                \
392         _CSAN_ATOMIC_FUNC_ADD(name, type)                               \
393         _CSAN_ATOMIC_FUNC_ADD(acq_##name, type)                         \
394         _CSAN_ATOMIC_FUNC_ADD(rel_##name, type)
395
396 #define _CSAN_ATOMIC_FUNC_CLEAR(name, type)                             \
397         void kcsan_atomic_clear_##name(volatile type *ptr, type val)    \
398         {                                                               \
399                 kcsan_access((uintptr_t)ptr, sizeof(type), true, true,  \
400                     __RET_ADDR);                                        \
401                 atomic_clear_##name(ptr, val);                          \
402         }
403
404 #define CSAN_ATOMIC_FUNC_CLEAR(name, type)                              \
405         _CSAN_ATOMIC_FUNC_CLEAR(name, type)                             \
406         _CSAN_ATOMIC_FUNC_CLEAR(acq_##name, type)                       \
407         _CSAN_ATOMIC_FUNC_CLEAR(rel_##name, type)
408
409 #define _CSAN_ATOMIC_FUNC_CMPSET(name, type)                            \
410         int kcsan_atomic_cmpset_##name(volatile type *ptr, type val1,   \
411             type val2)                                                  \
412         {                                                               \
413                 kcsan_access((uintptr_t)ptr, sizeof(type), true, true,  \
414                     __RET_ADDR);                                        \
415                 return (atomic_cmpset_##name(ptr, val1, val2));         \
416         }
417
418 #define CSAN_ATOMIC_FUNC_CMPSET(name, type)                             \
419         _CSAN_ATOMIC_FUNC_CMPSET(name, type)                            \
420         _CSAN_ATOMIC_FUNC_CMPSET(acq_##name, type)                      \
421         _CSAN_ATOMIC_FUNC_CMPSET(rel_##name, type)
422
423 #define _CSAN_ATOMIC_FUNC_FCMPSET(name, type)                           \
424         int kcsan_atomic_fcmpset_##name(volatile type *ptr, type *val1, \
425             type val2)                                                  \
426         {                                                               \
427                 kcsan_access((uintptr_t)ptr, sizeof(type), true, true,  \
428                     __RET_ADDR);                                        \
429                 return (atomic_fcmpset_##name(ptr, val1, val2));        \
430         }
431
432 #define CSAN_ATOMIC_FUNC_FCMPSET(name, type)                            \
433         _CSAN_ATOMIC_FUNC_FCMPSET(name, type)                           \
434         _CSAN_ATOMIC_FUNC_FCMPSET(acq_##name, type)                     \
435         _CSAN_ATOMIC_FUNC_FCMPSET(rel_##name, type)
436
437 #define CSAN_ATOMIC_FUNC_FETCHADD(name, type)                           \
438         type kcsan_atomic_fetchadd_##name(volatile type *ptr, type val) \
439         {                                                               \
440                 kcsan_access((uintptr_t)ptr, sizeof(type), true, true,  \
441                     __RET_ADDR);                                        \
442                 return (atomic_fetchadd_##name(ptr, val));              \
443         }
444
445 #define _CSAN_ATOMIC_FUNC_LOAD(name, type)                              \
446         type kcsan_atomic_load_##name(volatile type *ptr)               \
447         {                                                               \
448                 kcsan_access((uintptr_t)ptr, sizeof(type), false, true, \
449                     __RET_ADDR);                                        \
450                 return (atomic_load_##name(ptr));                       \
451         }
452
453 #define CSAN_ATOMIC_FUNC_LOAD(name, type)                               \
454         _CSAN_ATOMIC_FUNC_LOAD(name, type)                              \
455         _CSAN_ATOMIC_FUNC_LOAD(acq_##name, type)                        \
456
457 #define CSAN_ATOMIC_FUNC_READANDCLEAR(name, type)                       \
458         type kcsan_atomic_readandclear_##name(volatile type *ptr)       \
459         {                                                               \
460                 kcsan_access((uintptr_t)ptr, sizeof(type), true, true,  \
461                     __RET_ADDR);                                        \
462                 return (atomic_readandclear_##name(ptr));               \
463         }
464
465 #define _CSAN_ATOMIC_FUNC_SET(name, type)                               \
466         void kcsan_atomic_set_##name(volatile type *ptr, type val)      \
467         {                                                               \
468                 kcsan_access((uintptr_t)ptr, sizeof(type), true, true,  \
469                     __RET_ADDR);                                        \
470                 atomic_set_##name(ptr, val);                            \
471         }
472
473 #define CSAN_ATOMIC_FUNC_SET(name, type)                                \
474         _CSAN_ATOMIC_FUNC_SET(name, type)                               \
475         _CSAN_ATOMIC_FUNC_SET(acq_##name, type)                         \
476         _CSAN_ATOMIC_FUNC_SET(rel_##name, type)
477
478 #define _CSAN_ATOMIC_FUNC_SUBTRACT(name, type)                          \
479         void kcsan_atomic_subtract_##name(volatile type *ptr, type val) \
480         {                                                               \
481                 kcsan_access((uintptr_t)ptr, sizeof(type), true, true,  \
482                     __RET_ADDR);                                        \
483                 atomic_subtract_##name(ptr, val);                       \
484         }
485
486 #define CSAN_ATOMIC_FUNC_SUBTRACT(name, type)                           \
487         _CSAN_ATOMIC_FUNC_SUBTRACT(name, type)                          \
488         _CSAN_ATOMIC_FUNC_SUBTRACT(acq_##name, type)                    \
489         _CSAN_ATOMIC_FUNC_SUBTRACT(rel_##name, type)
490
491 #define _CSAN_ATOMIC_FUNC_STORE(name, type)                             \
492         void kcsan_atomic_store_##name(volatile type *ptr, type val)    \
493         {                                                               \
494                 kcsan_access((uintptr_t)ptr, sizeof(type), true, true,  \
495                     __RET_ADDR);                                        \
496                 atomic_store_##name(ptr, val);                          \
497         }
498
499 #define CSAN_ATOMIC_FUNC_STORE(name, type)                              \
500         _CSAN_ATOMIC_FUNC_STORE(name, type)                             \
501         _CSAN_ATOMIC_FUNC_STORE(rel_##name, type)
502
503 #define CSAN_ATOMIC_FUNC_SWAP(name, type)                               \
504         type kcsan_atomic_swap_##name(volatile type *ptr, type val)     \
505         {                                                               \
506                 kcsan_access((uintptr_t)ptr, sizeof(type), true, true,  \
507                     __RET_ADDR);                                        \
508                 return(atomic_swap_##name(ptr, val));                   \
509         }
510
511 #define CSAN_ATOMIC_FUNC_TESTANDCLEAR(name, type)                       \
512         int kcsan_atomic_testandclear_##name(volatile type *ptr, u_int val) \
513         {                                                               \
514                 kcsan_access((uintptr_t)ptr, sizeof(type), true, true,  \
515                     __RET_ADDR);                                        \
516                 return(atomic_testandclear_##name(ptr, val));           \
517         }
518
519 #define CSAN_ATOMIC_FUNC_TESTANDSET(name, type)                         \
520         int kcsan_atomic_testandset_##name(volatile type *ptr, u_int val) \
521         {                                                               \
522                 kcsan_access((uintptr_t)ptr, sizeof(type), true, true,  \
523                     __RET_ADDR);                                        \
524                 return (atomic_testandset_##name(ptr, val));            \
525         }
526
527 _CSAN_ATOMIC_FUNC_LOAD(bool, bool)
528 _CSAN_ATOMIC_FUNC_STORE(bool, bool)
529
530 CSAN_ATOMIC_FUNC_ADD(8, uint8_t)
531 CSAN_ATOMIC_FUNC_CLEAR(8, uint8_t)
532 CSAN_ATOMIC_FUNC_CMPSET(8, uint8_t)
533 CSAN_ATOMIC_FUNC_FCMPSET(8, uint8_t)
534 CSAN_ATOMIC_FUNC_LOAD(8, uint8_t)
535 CSAN_ATOMIC_FUNC_SET(8, uint8_t)
536 CSAN_ATOMIC_FUNC_SUBTRACT(8, uint8_t)
537 _CSAN_ATOMIC_FUNC_STORE(8, uint8_t)
538 #if 0
539 CSAN_ATOMIC_FUNC_FETCHADD(8, uint8_t)
540 CSAN_ATOMIC_FUNC_READANDCLEAR(8, uint8_t)
541 CSAN_ATOMIC_FUNC_SWAP(8, uint8_t)
542 CSAN_ATOMIC_FUNC_TESTANDCLEAR(8, uint8_t)
543 CSAN_ATOMIC_FUNC_TESTANDSET(8, uint8_t)
544 #endif
545
546 CSAN_ATOMIC_FUNC_ADD(16, uint16_t)
547 CSAN_ATOMIC_FUNC_CLEAR(16, uint16_t)
548 CSAN_ATOMIC_FUNC_CMPSET(16, uint16_t)
549 CSAN_ATOMIC_FUNC_FCMPSET(16, uint16_t)
550 CSAN_ATOMIC_FUNC_LOAD(16, uint16_t)
551 CSAN_ATOMIC_FUNC_SET(16, uint16_t)
552 CSAN_ATOMIC_FUNC_SUBTRACT(16, uint16_t)
553 _CSAN_ATOMIC_FUNC_STORE(16, uint16_t)
554 #if 0
555 CSAN_ATOMIC_FUNC_FETCHADD(16, uint16_t)
556 CSAN_ATOMIC_FUNC_READANDCLEAR(16, uint16_t)
557 CSAN_ATOMIC_FUNC_SWAP(16, uint16_t)
558 CSAN_ATOMIC_FUNC_TESTANDCLEAR(16, uint16_t)
559 CSAN_ATOMIC_FUNC_TESTANDSET(16, uint16_t)
560 #endif
561
562 CSAN_ATOMIC_FUNC_ADD(32, uint32_t)
563 CSAN_ATOMIC_FUNC_CLEAR(32, uint32_t)
564 CSAN_ATOMIC_FUNC_CMPSET(32, uint32_t)
565 CSAN_ATOMIC_FUNC_FCMPSET(32, uint32_t)
566 CSAN_ATOMIC_FUNC_FETCHADD(32, uint32_t)
567 CSAN_ATOMIC_FUNC_LOAD(32, uint32_t)
568 CSAN_ATOMIC_FUNC_READANDCLEAR(32, uint32_t)
569 CSAN_ATOMIC_FUNC_SET(32, uint32_t)
570 CSAN_ATOMIC_FUNC_SUBTRACT(32, uint32_t)
571 CSAN_ATOMIC_FUNC_STORE(32, uint32_t)
572 CSAN_ATOMIC_FUNC_SWAP(32, uint32_t)
573 CSAN_ATOMIC_FUNC_TESTANDCLEAR(32, uint32_t)
574 CSAN_ATOMIC_FUNC_TESTANDSET(32, uint32_t)
575
576 CSAN_ATOMIC_FUNC_ADD(64, uint64_t)
577 CSAN_ATOMIC_FUNC_CLEAR(64, uint64_t)
578 CSAN_ATOMIC_FUNC_CMPSET(64, uint64_t)
579 CSAN_ATOMIC_FUNC_FCMPSET(64, uint64_t)
580 CSAN_ATOMIC_FUNC_FETCHADD(64, uint64_t)
581 CSAN_ATOMIC_FUNC_LOAD(64, uint64_t)
582 CSAN_ATOMIC_FUNC_READANDCLEAR(64, uint64_t)
583 CSAN_ATOMIC_FUNC_SET(64, uint64_t)
584 CSAN_ATOMIC_FUNC_SUBTRACT(64, uint64_t)
585 CSAN_ATOMIC_FUNC_STORE(64, uint64_t)
586 CSAN_ATOMIC_FUNC_SWAP(64, uint64_t)
587 CSAN_ATOMIC_FUNC_TESTANDCLEAR(64, uint64_t)
588 CSAN_ATOMIC_FUNC_TESTANDSET(64, uint64_t)
589
590 CSAN_ATOMIC_FUNC_ADD(char, uint8_t)
591 CSAN_ATOMIC_FUNC_CLEAR(char, uint8_t)
592 CSAN_ATOMIC_FUNC_CMPSET(char, uint8_t)
593 CSAN_ATOMIC_FUNC_FCMPSET(char, uint8_t)
594 CSAN_ATOMIC_FUNC_LOAD(char, uint8_t)
595 CSAN_ATOMIC_FUNC_SET(char, uint8_t)
596 CSAN_ATOMIC_FUNC_SUBTRACT(char, uint8_t)
597 _CSAN_ATOMIC_FUNC_STORE(char, uint8_t)
598 #if 0
599 CSAN_ATOMIC_FUNC_FETCHADD(char, uint8_t)
600 CSAN_ATOMIC_FUNC_READANDCLEAR(char, uint8_t)
601 CSAN_ATOMIC_FUNC_SWAP(char, uint8_t)
602 CSAN_ATOMIC_FUNC_TESTANDCLEAR(char, uint8_t)
603 CSAN_ATOMIC_FUNC_TESTANDSET(char, uint8_t)
604 #endif
605
606 CSAN_ATOMIC_FUNC_ADD(short, uint16_t)
607 CSAN_ATOMIC_FUNC_CLEAR(short, uint16_t)
608 CSAN_ATOMIC_FUNC_CMPSET(short, uint16_t)
609 CSAN_ATOMIC_FUNC_FCMPSET(short, uint16_t)
610 CSAN_ATOMIC_FUNC_LOAD(short, uint16_t)
611 CSAN_ATOMIC_FUNC_SET(short, uint16_t)
612 CSAN_ATOMIC_FUNC_SUBTRACT(short, uint16_t)
613 _CSAN_ATOMIC_FUNC_STORE(short, uint16_t)
614 #if 0
615 CSAN_ATOMIC_FUNC_FETCHADD(short, uint16_t)
616 CSAN_ATOMIC_FUNC_READANDCLEAR(short, uint16_t)
617 CSAN_ATOMIC_FUNC_SWAP(short, uint16_t)
618 CSAN_ATOMIC_FUNC_TESTANDCLEAR(short, uint16_t)
619 CSAN_ATOMIC_FUNC_TESTANDSET(short, uint16_t)
620 #endif
621
622 CSAN_ATOMIC_FUNC_ADD(int, u_int)
623 CSAN_ATOMIC_FUNC_CLEAR(int, u_int)
624 CSAN_ATOMIC_FUNC_CMPSET(int, u_int)
625 CSAN_ATOMIC_FUNC_FCMPSET(int, u_int)
626 CSAN_ATOMIC_FUNC_FETCHADD(int, u_int)
627 CSAN_ATOMIC_FUNC_LOAD(int, u_int)
628 CSAN_ATOMIC_FUNC_READANDCLEAR(int, u_int)
629 CSAN_ATOMIC_FUNC_SET(int, u_int)
630 CSAN_ATOMIC_FUNC_SUBTRACT(int, u_int)
631 CSAN_ATOMIC_FUNC_STORE(int, u_int)
632 CSAN_ATOMIC_FUNC_SWAP(int, u_int)
633 CSAN_ATOMIC_FUNC_TESTANDCLEAR(int, u_int)
634 CSAN_ATOMIC_FUNC_TESTANDSET(int, u_int)
635
636 CSAN_ATOMIC_FUNC_ADD(long, u_long)
637 CSAN_ATOMIC_FUNC_CLEAR(long, u_long)
638 CSAN_ATOMIC_FUNC_CMPSET(long, u_long)
639 CSAN_ATOMIC_FUNC_FCMPSET(long, u_long)
640 CSAN_ATOMIC_FUNC_FETCHADD(long, u_long)
641 CSAN_ATOMIC_FUNC_LOAD(long, u_long)
642 CSAN_ATOMIC_FUNC_READANDCLEAR(long, u_long)
643 CSAN_ATOMIC_FUNC_SET(long, u_long)
644 CSAN_ATOMIC_FUNC_SUBTRACT(long, u_long)
645 CSAN_ATOMIC_FUNC_STORE(long, u_long)
646 CSAN_ATOMIC_FUNC_SWAP(long, u_long)
647 CSAN_ATOMIC_FUNC_TESTANDCLEAR(long, u_long)
648 CSAN_ATOMIC_FUNC_TESTANDSET(long, u_long)
649 CSAN_ATOMIC_FUNC_TESTANDSET(acq_long, u_long)
650
651 CSAN_ATOMIC_FUNC_ADD(ptr, uintptr_t)
652 CSAN_ATOMIC_FUNC_CLEAR(ptr, uintptr_t)
653 CSAN_ATOMIC_FUNC_CMPSET(ptr, uintptr_t)
654 CSAN_ATOMIC_FUNC_FCMPSET(ptr, uintptr_t)
655 #if !defined(__amd64__)
656 CSAN_ATOMIC_FUNC_FETCHADD(ptr, uintptr_t)
657 #endif
658 CSAN_ATOMIC_FUNC_LOAD(ptr, uintptr_t)
659 CSAN_ATOMIC_FUNC_READANDCLEAR(ptr, uintptr_t)
660 CSAN_ATOMIC_FUNC_SET(ptr, uintptr_t)
661 CSAN_ATOMIC_FUNC_SUBTRACT(ptr, uintptr_t)
662 CSAN_ATOMIC_FUNC_STORE(ptr, uintptr_t)
663 CSAN_ATOMIC_FUNC_SWAP(ptr, uintptr_t)
664 #if 0
665 CSAN_ATOMIC_FUNC_TESTANDCLEAR(ptr, uintptr_t)
666 CSAN_ATOMIC_FUNC_TESTANDSET(ptr, uintptr_t)
667 #endif
668
669 #define CSAN_ATOMIC_FUNC_THREAD_FENCE(name)                             \
670         void kcsan_atomic_thread_fence_##name(void)                     \
671         {                                                               \
672                 atomic_thread_fence_##name();                           \
673         }
674
675 CSAN_ATOMIC_FUNC_THREAD_FENCE(acq)
676 CSAN_ATOMIC_FUNC_THREAD_FENCE(acq_rel)
677 CSAN_ATOMIC_FUNC_THREAD_FENCE(rel)
678 CSAN_ATOMIC_FUNC_THREAD_FENCE(seq_cst)
679
680 void
681 kcsan_atomic_interrupt_fence(void)
682 {
683         atomic_interrupt_fence();
684 }
685
686 /* -------------------------------------------------------------------------- */
687
688 #include <sys/bus.h>
689 #include <machine/bus.h>
690 #include <sys/bus_san.h>
691
692 int
693 kcsan_bus_space_map(bus_space_tag_t tag, bus_addr_t hnd, bus_size_t size,
694     int flags, bus_space_handle_t *handlep)
695 {
696
697         return (bus_space_map(tag, hnd, size, flags, handlep));
698 }
699
700 void
701 kcsan_bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t hnd,
702     bus_size_t size)
703 {
704
705         bus_space_unmap(tag, hnd, size);
706 }
707
708 int
709 kcsan_bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t hnd,
710     bus_size_t offset, bus_size_t size, bus_space_handle_t *handlep)
711 {
712
713         return (bus_space_subregion(tag, hnd, offset, size, handlep));
714 }
715
716 #if !defined(__amd64__)
717 int
718 kcsan_bus_space_alloc(bus_space_tag_t tag, bus_addr_t reg_start,
719     bus_addr_t reg_end, bus_size_t size, bus_size_t alignment,
720     bus_size_t boundary, int flags, bus_addr_t *addrp,
721     bus_space_handle_t *handlep)
722 {
723
724         return (bus_space_alloc(tag, reg_start, reg_end, size, alignment,
725             boundary, flags, addrp, handlep));
726 }
727 #endif
728
729 void
730 kcsan_bus_space_free(bus_space_tag_t tag, bus_space_handle_t hnd,
731     bus_size_t size)
732 {
733
734         bus_space_free(tag, hnd, size);
735 }
736
737 void
738 kcsan_bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t hnd,
739     bus_size_t offset, bus_size_t size, int flags)
740 {
741
742         bus_space_barrier(tag, hnd, offset, size, flags);
743 }
744
745 #define CSAN_BUS_READ_FUNC(func, width, type)                           \
746         type kcsan_bus_space_read##func##_##width(bus_space_tag_t tag,  \
747             bus_space_handle_t hnd, bus_size_t offset)                  \
748         {                                                               \
749                 return (bus_space_read##func##_##width(tag, hnd,        \
750                     offset));                                           \
751         }                                                               \
752
753 #define CSAN_BUS_READ_PTR_FUNC(func, width, type)                       \
754         void kcsan_bus_space_read_##func##_##width(bus_space_tag_t tag, \
755             bus_space_handle_t hnd, bus_size_t size, type *buf,         \
756             bus_size_t count)                                           \
757         {                                                               \
758                 kcsan_access((uintptr_t)buf, sizeof(type) * count,      \
759                     false, false, __RET_ADDR);                          \
760                 bus_space_read_##func##_##width(tag, hnd, size, buf,    \
761                     count);                                             \
762         }
763
764 CSAN_BUS_READ_FUNC(, 1, uint8_t)
765 CSAN_BUS_READ_FUNC(_stream, 1, uint8_t)
766 CSAN_BUS_READ_PTR_FUNC(multi, 1, uint8_t)
767 CSAN_BUS_READ_PTR_FUNC(multi_stream, 1, uint8_t)
768 CSAN_BUS_READ_PTR_FUNC(region, 1, uint8_t)
769 CSAN_BUS_READ_PTR_FUNC(region_stream, 1, uint8_t)
770
771 CSAN_BUS_READ_FUNC(, 2, uint16_t)
772 CSAN_BUS_READ_FUNC(_stream, 2, uint16_t)
773 CSAN_BUS_READ_PTR_FUNC(multi, 2, uint16_t)
774 CSAN_BUS_READ_PTR_FUNC(multi_stream, 2, uint16_t)
775 CSAN_BUS_READ_PTR_FUNC(region, 2, uint16_t)
776 CSAN_BUS_READ_PTR_FUNC(region_stream, 2, uint16_t)
777
778 CSAN_BUS_READ_FUNC(, 4, uint32_t)
779 CSAN_BUS_READ_FUNC(_stream, 4, uint32_t)
780 CSAN_BUS_READ_PTR_FUNC(multi, 4, uint32_t)
781 CSAN_BUS_READ_PTR_FUNC(multi_stream, 4, uint32_t)
782 CSAN_BUS_READ_PTR_FUNC(region, 4, uint32_t)
783 CSAN_BUS_READ_PTR_FUNC(region_stream, 4, uint32_t)
784
785 CSAN_BUS_READ_FUNC(, 8, uint64_t)
786 #if defined(__aarch64__)
787 CSAN_BUS_READ_FUNC(_stream, 8, uint64_t)
788 CSAN_BUS_READ_PTR_FUNC(multi, 8, uint64_t)
789 CSAN_BUS_READ_PTR_FUNC(multi_stream, 8, uint64_t)
790 CSAN_BUS_READ_PTR_FUNC(region, 8, uint64_t)
791 CSAN_BUS_READ_PTR_FUNC(region_stream, 8, uint64_t)
792 #endif
793
794 #define CSAN_BUS_WRITE_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 offset, type value)      \
797         {                                                               \
798                 bus_space_write##func##_##width(tag, hnd, offset, value); \
799         }                                                               \
800
801 #define CSAN_BUS_WRITE_PTR_FUNC(func, width, type)                      \
802         void kcsan_bus_space_write_##func##_##width(bus_space_tag_t tag, \
803             bus_space_handle_t hnd, bus_size_t size, const type *buf,   \
804             bus_size_t count)                                           \
805         {                                                               \
806                 kcsan_access((uintptr_t)buf, sizeof(type) * count,      \
807                     true, false, __RET_ADDR);                           \
808                 bus_space_write_##func##_##width(tag, hnd, size, buf,   \
809                     count);                                             \
810         }
811
812 CSAN_BUS_WRITE_FUNC(, 1, uint8_t)
813 CSAN_BUS_WRITE_FUNC(_stream, 1, uint8_t)
814 CSAN_BUS_WRITE_PTR_FUNC(multi, 1, uint8_t)
815 CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 1, uint8_t)
816 CSAN_BUS_WRITE_PTR_FUNC(region, 1, uint8_t)
817 CSAN_BUS_WRITE_PTR_FUNC(region_stream, 1, uint8_t)
818
819 CSAN_BUS_WRITE_FUNC(, 2, uint16_t)
820 CSAN_BUS_WRITE_FUNC(_stream, 2, uint16_t)
821 CSAN_BUS_WRITE_PTR_FUNC(multi, 2, uint16_t)
822 CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 2, uint16_t)
823 CSAN_BUS_WRITE_PTR_FUNC(region, 2, uint16_t)
824 CSAN_BUS_WRITE_PTR_FUNC(region_stream, 2, uint16_t)
825
826 CSAN_BUS_WRITE_FUNC(, 4, uint32_t)
827 CSAN_BUS_WRITE_FUNC(_stream, 4, uint32_t)
828 CSAN_BUS_WRITE_PTR_FUNC(multi, 4, uint32_t)
829 CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 4, uint32_t)
830 CSAN_BUS_WRITE_PTR_FUNC(region, 4, uint32_t)
831 CSAN_BUS_WRITE_PTR_FUNC(region_stream, 4, uint32_t)
832
833 CSAN_BUS_WRITE_FUNC(, 8, uint64_t)
834 #if defined(__aarch64__)
835 CSAN_BUS_WRITE_FUNC(_stream, 8, uint64_t)
836 CSAN_BUS_WRITE_PTR_FUNC(multi, 8, uint64_t)
837 CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 8, uint64_t)
838 CSAN_BUS_WRITE_PTR_FUNC(region, 8, uint64_t)
839 CSAN_BUS_WRITE_PTR_FUNC(region_stream, 8, uint64_t)
840 #endif
841
842 #define CSAN_BUS_SET_FUNC(func, width, type)                            \
843         void kcsan_bus_space_set_##func##_##width(bus_space_tag_t tag,  \
844             bus_space_handle_t hnd, bus_size_t offset, type value,      \
845             bus_size_t count)                                           \
846         {                                                               \
847                 bus_space_set_##func##_##width(tag, hnd, offset, value, \
848                     count);                                             \
849         }
850
851 CSAN_BUS_SET_FUNC(multi, 1, uint8_t)
852 CSAN_BUS_SET_FUNC(region, 1, uint8_t)
853 #if !defined(__aarch64__)
854 CSAN_BUS_SET_FUNC(multi_stream, 1, uint8_t)
855 CSAN_BUS_SET_FUNC(region_stream, 1, uint8_t)
856 #endif
857
858 CSAN_BUS_SET_FUNC(multi, 2, uint16_t)
859 CSAN_BUS_SET_FUNC(region, 2, uint16_t)
860 #if !defined(__aarch64__)
861 CSAN_BUS_SET_FUNC(multi_stream, 2, uint16_t)
862 CSAN_BUS_SET_FUNC(region_stream, 2, uint16_t)
863 #endif
864
865 CSAN_BUS_SET_FUNC(multi, 4, uint32_t)
866 CSAN_BUS_SET_FUNC(region, 4, uint32_t)
867 #if !defined(__aarch64__)
868 CSAN_BUS_SET_FUNC(multi_stream, 4, uint32_t)
869 CSAN_BUS_SET_FUNC(region_stream, 4, uint32_t)
870 #endif
871
872 #if !defined(__amd64__)
873 CSAN_BUS_SET_FUNC(multi, 8, uint64_t)
874 CSAN_BUS_SET_FUNC(region, 8, uint64_t)
875 #if !defined(__aarch64__)
876 CSAN_BUS_SET_FUNC(multi_stream, 8, uint64_t)
877 CSAN_BUS_SET_FUNC(region_stream, 8, uint64_t)
878 #endif
879 #endif
880
881 #define CSAN_BUS_PEEK_FUNC(width, type)                                 \
882         int kcsan_bus_space_peek_##width(bus_space_tag_t tag,           \
883             bus_space_handle_t hnd, bus_size_t offset, type *value)     \
884         {                                                               \
885                 kcsan_access((uintptr_t)value, sizeof(type), true, false, \
886                     __RET_ADDR);                                        \
887                 return (bus_space_peek_##width(tag, hnd, offset, value)); \
888         }
889
890 CSAN_BUS_PEEK_FUNC(1, uint8_t)
891 CSAN_BUS_PEEK_FUNC(2, uint16_t)
892 CSAN_BUS_PEEK_FUNC(4, uint32_t)
893 #if !defined(__i386__)
894 CSAN_BUS_PEEK_FUNC(8, uint64_t)
895 #endif
896
897 #define CSAN_BUS_POKE_FUNC(width, type)                                 \
898         int kcsan_bus_space_poke_##width(bus_space_tag_t tag,           \
899             bus_space_handle_t hnd, bus_size_t offset, type value)      \
900         {                                                               \
901                 return (bus_space_poke_##width(tag, hnd, offset, value)); \
902         }
903
904 CSAN_BUS_POKE_FUNC(1, uint8_t)
905 CSAN_BUS_POKE_FUNC(2, uint16_t)
906 CSAN_BUS_POKE_FUNC(4, uint32_t)
907 #if !defined(__i386__)
908 CSAN_BUS_POKE_FUNC(8, uint64_t)
909 #endif