FreeBSD kernel kern code
subr_csan.c
Go to the documentation of this file.
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
59typedef struct {
60 uintptr_t addr;
61 uint32_t size;
62 bool write:1;
63 bool atomic:1;
64 uintptr_t pc;
66
67typedef struct {
68 bool inited;
69 uint32_t cnt;
72
73static csan_cpu_t kcsan_cpus[MAXCPU];
74static 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
88static void
89kcsan_enable(void *dummy __unused)
90{
91
92 printf("Enabling KCSCAN, expect reduced performance.\n");
93 kcsan_enabled = true;
94}
95SYSINIT(kcsan_enable, SI_SUB_SMP, SI_ORDER_SECOND, kcsan_enable, NULL);
96
97void
99{
100 kcsan_cpus[cpu].inited = true;
101}
102
103/* -------------------------------------------------------------------------- */
104
105static inline void
106kcsan_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
134static inline bool
136{
137 if (new->write && !new->atomic)
138 return false;
139 if (old->write && !old->atomic)
140 return false;
141 return true;
142}
143
144static inline void
145kcsan_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
197out:
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
213CSAN_READ(1)
214CSAN_READ(2)
215CSAN_READ(4)
216CSAN_READ(8)
217CSAN_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
231CSAN_WRITE(1)
232CSAN_WRITE(2)
233CSAN_WRITE(4)
234CSAN_WRITE(8)
235CSAN_WRITE(16)
236
237void __tsan_read_range(uintptr_t, size_t);
238void __tsan_write_range(uintptr_t, size_t);
239
240void
241__tsan_read_range(uintptr_t addr, size_t size)
242{
243 kcsan_access(addr, size, false, false, __RET_ADDR);
244}
245
246void
247__tsan_write_range(uintptr_t addr, size_t size)
248{
249 kcsan_access(addr, size, true, false, __RET_ADDR);
250}
251
252void __tsan_init(void);
253void __tsan_func_entry(void *);
254void __tsan_func_exit(void);
255
256void
258{
259}
260
261void
262__tsan_func_entry(void *call_pc)
263{
264}
265
266void
268{
269}
270
271/* -------------------------------------------------------------------------- */
272
273void *
274kcsan_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
281int
282kcsan_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
289void *
290kcsan_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
296void *
297kcsan_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
304char *
305kcsan_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
321int
322kcsan_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
337size_t
338kcsan_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
353int
354kcsan_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
360int
361kcsan_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
367int
368kcsan_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
523CSAN_ATOMIC_FUNC_ADD(8, uint8_t)
524CSAN_ATOMIC_FUNC_CLEAR(8, uint8_t)
525CSAN_ATOMIC_FUNC_CMPSET(8, uint8_t)
526CSAN_ATOMIC_FUNC_FCMPSET(8, uint8_t)
527CSAN_ATOMIC_FUNC_LOAD(8, uint8_t)
528CSAN_ATOMIC_FUNC_SET(8, uint8_t)
530_CSAN_ATOMIC_FUNC_STORE(8, uint8_t)
531#if 0
534CSAN_ATOMIC_FUNC_SWAP(8, uint8_t)
537#endif
538
539CSAN_ATOMIC_FUNC_ADD(16, uint16_t)
540CSAN_ATOMIC_FUNC_CLEAR(16, uint16_t)
541CSAN_ATOMIC_FUNC_CMPSET(16, uint16_t)
542CSAN_ATOMIC_FUNC_FCMPSET(16, uint16_t)
543CSAN_ATOMIC_FUNC_LOAD(16, uint16_t)
544CSAN_ATOMIC_FUNC_SET(16, uint16_t)
545CSAN_ATOMIC_FUNC_SUBTRACT(16, uint16_t)
546_CSAN_ATOMIC_FUNC_STORE(16, uint16_t)
547#if 0
548CSAN_ATOMIC_FUNC_FETCHADD(16, uint16_t)
550CSAN_ATOMIC_FUNC_SWAP(16, uint16_t)
552CSAN_ATOMIC_FUNC_TESTANDSET(16, uint16_t)
553#endif
554
555CSAN_ATOMIC_FUNC_ADD(32, uint32_t)
556CSAN_ATOMIC_FUNC_CLEAR(32, uint32_t)
557CSAN_ATOMIC_FUNC_CMPSET(32, uint32_t)
558CSAN_ATOMIC_FUNC_FCMPSET(32, uint32_t)
559CSAN_ATOMIC_FUNC_FETCHADD(32, uint32_t)
560CSAN_ATOMIC_FUNC_LOAD(32, uint32_t)
562CSAN_ATOMIC_FUNC_SET(32, uint32_t)
563CSAN_ATOMIC_FUNC_SUBTRACT(32, uint32_t)
564CSAN_ATOMIC_FUNC_STORE(32, uint32_t)
565CSAN_ATOMIC_FUNC_SWAP(32, uint32_t)
567CSAN_ATOMIC_FUNC_TESTANDSET(32, uint32_t)
568
569CSAN_ATOMIC_FUNC_ADD(64, uint64_t)
570CSAN_ATOMIC_FUNC_CLEAR(64, uint64_t)
571CSAN_ATOMIC_FUNC_CMPSET(64, uint64_t)
572CSAN_ATOMIC_FUNC_FCMPSET(64, uint64_t)
573CSAN_ATOMIC_FUNC_FETCHADD(64, uint64_t)
574CSAN_ATOMIC_FUNC_LOAD(64, uint64_t)
576CSAN_ATOMIC_FUNC_SET(64, uint64_t)
577CSAN_ATOMIC_FUNC_SUBTRACT(64, uint64_t)
578CSAN_ATOMIC_FUNC_STORE(64, uint64_t)
579CSAN_ATOMIC_FUNC_SWAP(64, uint64_t)
581CSAN_ATOMIC_FUNC_TESTANDSET(64, uint64_t)
582
583CSAN_ATOMIC_FUNC_ADD(char, uint8_t)
584CSAN_ATOMIC_FUNC_CLEAR(char, uint8_t)
585CSAN_ATOMIC_FUNC_CMPSET(char, uint8_t)
586CSAN_ATOMIC_FUNC_FCMPSET(char, uint8_t)
587CSAN_ATOMIC_FUNC_LOAD(char, uint8_t)
588CSAN_ATOMIC_FUNC_SET(char, uint8_t)
589CSAN_ATOMIC_FUNC_SUBTRACT(char, uint8_t)
590_CSAN_ATOMIC_FUNC_STORE(char, uint8_t)
591#if 0
592CSAN_ATOMIC_FUNC_FETCHADD(char, uint8_t)
594CSAN_ATOMIC_FUNC_SWAP(char, uint8_t)
596CSAN_ATOMIC_FUNC_TESTANDSET(char, uint8_t)
597#endif
598
599CSAN_ATOMIC_FUNC_ADD(short, uint16_t)
600CSAN_ATOMIC_FUNC_CLEAR(short, uint16_t)
601CSAN_ATOMIC_FUNC_CMPSET(short, uint16_t)
602CSAN_ATOMIC_FUNC_FCMPSET(short, uint16_t)
603CSAN_ATOMIC_FUNC_LOAD(short, uint16_t)
604CSAN_ATOMIC_FUNC_SET(short, uint16_t)
605CSAN_ATOMIC_FUNC_SUBTRACT(short, uint16_t)
606_CSAN_ATOMIC_FUNC_STORE(short, uint16_t)
607#if 0
608CSAN_ATOMIC_FUNC_FETCHADD(short, uint16_t)
609CSAN_ATOMIC_FUNC_READANDCLEAR(short, uint16_t)
610CSAN_ATOMIC_FUNC_SWAP(short, uint16_t)
611CSAN_ATOMIC_FUNC_TESTANDCLEAR(short, uint16_t)
612CSAN_ATOMIC_FUNC_TESTANDSET(short, uint16_t)
613#endif
614
615CSAN_ATOMIC_FUNC_ADD(int, u_int)
616CSAN_ATOMIC_FUNC_CLEAR(int, u_int)
617CSAN_ATOMIC_FUNC_CMPSET(int, u_int)
618CSAN_ATOMIC_FUNC_FCMPSET(int, u_int)
620CSAN_ATOMIC_FUNC_LOAD(int, u_int)
622CSAN_ATOMIC_FUNC_SET(int, u_int)
624CSAN_ATOMIC_FUNC_STORE(int, u_int)
625CSAN_ATOMIC_FUNC_SWAP(int, u_int)
628
629CSAN_ATOMIC_FUNC_ADD(long, u_long)
630CSAN_ATOMIC_FUNC_CLEAR(long, u_long)
631CSAN_ATOMIC_FUNC_CMPSET(long, u_long)
632CSAN_ATOMIC_FUNC_FCMPSET(long, u_long)
633CSAN_ATOMIC_FUNC_FETCHADD(long, u_long)
634CSAN_ATOMIC_FUNC_LOAD(long, u_long)
636CSAN_ATOMIC_FUNC_SET(long, u_long)
637CSAN_ATOMIC_FUNC_SUBTRACT(long, u_long)
638CSAN_ATOMIC_FUNC_STORE(long, u_long)
639CSAN_ATOMIC_FUNC_SWAP(long, u_long)
641CSAN_ATOMIC_FUNC_TESTANDSET(long, u_long)
642CSAN_ATOMIC_FUNC_TESTANDSET(acq_long, u_long)
643
644CSAN_ATOMIC_FUNC_ADD(ptr, uintptr_t)
645CSAN_ATOMIC_FUNC_CLEAR(ptr, uintptr_t)
646CSAN_ATOMIC_FUNC_CMPSET(ptr, uintptr_t)
647CSAN_ATOMIC_FUNC_FCMPSET(ptr, uintptr_t)
648#if !defined(__amd64__)
649CSAN_ATOMIC_FUNC_FETCHADD(ptr, uintptr_t)
650#endif
651CSAN_ATOMIC_FUNC_LOAD(ptr, uintptr_t)
652CSAN_ATOMIC_FUNC_READANDCLEAR(ptr, uintptr_t)
653CSAN_ATOMIC_FUNC_SET(ptr, uintptr_t)
654CSAN_ATOMIC_FUNC_SUBTRACT(ptr, uintptr_t)
655CSAN_ATOMIC_FUNC_STORE(ptr, uintptr_t)
656CSAN_ATOMIC_FUNC_SWAP(ptr, uintptr_t)
657#if 0
658CSAN_ATOMIC_FUNC_TESTANDCLEAR(ptr, uintptr_t)
659CSAN_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
672
673void
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
685int
686kcsan_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
693void
694kcsan_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
701int
702kcsan_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__)
710int
711kcsan_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
722void
723kcsan_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
730void
731kcsan_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
757CSAN_BUS_READ_FUNC(, 1, uint8_t)
758CSAN_BUS_READ_FUNC(_stream, 1, uint8_t)
759CSAN_BUS_READ_PTR_FUNC(multi, 1, uint8_t)
760CSAN_BUS_READ_PTR_FUNC(multi_stream, 1, uint8_t)
762CSAN_BUS_READ_PTR_FUNC(region_stream, 1, uint8_t)
763
764CSAN_BUS_READ_FUNC(, 2, uint16_t)
765CSAN_BUS_READ_FUNC(_stream, 2, uint16_t)
766CSAN_BUS_READ_PTR_FUNC(multi, 2, uint16_t)
767CSAN_BUS_READ_PTR_FUNC(multi_stream, 2, uint16_t)
768CSAN_BUS_READ_PTR_FUNC(region, 2, uint16_t)
769CSAN_BUS_READ_PTR_FUNC(region_stream, 2, uint16_t)
770
771CSAN_BUS_READ_FUNC(, 4, uint32_t)
772CSAN_BUS_READ_FUNC(_stream, 4, uint32_t)
773CSAN_BUS_READ_PTR_FUNC(multi, 4, uint32_t)
774CSAN_BUS_READ_PTR_FUNC(multi_stream, 4, uint32_t)
775CSAN_BUS_READ_PTR_FUNC(region, 4, uint32_t)
776CSAN_BUS_READ_PTR_FUNC(region_stream, 4, uint32_t)
777
778CSAN_BUS_READ_FUNC(, 8, uint64_t)
779#if defined(__aarch64__)
780CSAN_BUS_READ_FUNC(_stream, 8, uint64_t)
781CSAN_BUS_READ_PTR_FUNC(multi, 8, uint64_t)
782CSAN_BUS_READ_PTR_FUNC(multi_stream, 8, uint64_t)
783CSAN_BUS_READ_PTR_FUNC(region, 8, uint64_t)
784CSAN_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
805CSAN_BUS_WRITE_FUNC(, 1, uint8_t)
806CSAN_BUS_WRITE_FUNC(_stream, 1, uint8_t)
807CSAN_BUS_WRITE_PTR_FUNC(multi, 1, uint8_t)
808CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 1, uint8_t)
810CSAN_BUS_WRITE_PTR_FUNC(region_stream, 1, uint8_t)
811
812CSAN_BUS_WRITE_FUNC(, 2, uint16_t)
813CSAN_BUS_WRITE_FUNC(_stream, 2, uint16_t)
814CSAN_BUS_WRITE_PTR_FUNC(multi, 2, uint16_t)
815CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 2, uint16_t)
817CSAN_BUS_WRITE_PTR_FUNC(region_stream, 2, uint16_t)
818
819CSAN_BUS_WRITE_FUNC(, 4, uint32_t)
820CSAN_BUS_WRITE_FUNC(_stream, 4, uint32_t)
821CSAN_BUS_WRITE_PTR_FUNC(multi, 4, uint32_t)
822CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 4, uint32_t)
824CSAN_BUS_WRITE_PTR_FUNC(region_stream, 4, uint32_t)
825
826CSAN_BUS_WRITE_FUNC(, 8, uint64_t)
827#if defined(__aarch64__)
828CSAN_BUS_WRITE_FUNC(_stream, 8, uint64_t)
829CSAN_BUS_WRITE_PTR_FUNC(multi, 8, uint64_t)
830CSAN_BUS_WRITE_PTR_FUNC(multi_stream, 8, uint64_t)
832CSAN_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
844CSAN_BUS_SET_FUNC(multi, 1, uint8_t)
845CSAN_BUS_SET_FUNC(region, 1, uint8_t)
846#if !defined(__aarch64__)
847CSAN_BUS_SET_FUNC(multi_stream, 1, uint8_t)
848CSAN_BUS_SET_FUNC(region_stream, 1, uint8_t)
849#endif
850
851CSAN_BUS_SET_FUNC(multi, 2, uint16_t)
852CSAN_BUS_SET_FUNC(region, 2, uint16_t)
853#if !defined(__aarch64__)
854CSAN_BUS_SET_FUNC(multi_stream, 2, uint16_t)
855CSAN_BUS_SET_FUNC(region_stream, 2, uint16_t)
856#endif
857
858CSAN_BUS_SET_FUNC(multi, 4, uint32_t)
859CSAN_BUS_SET_FUNC(region, 4, uint32_t)
860#if !defined(__aarch64__)
861CSAN_BUS_SET_FUNC(multi_stream, 4, uint32_t)
862CSAN_BUS_SET_FUNC(region_stream, 4, uint32_t)
863#endif
864
865#if !defined(__amd64__)
866CSAN_BUS_SET_FUNC(multi, 8, uint64_t)
867CSAN_BUS_SET_FUNC(region, 8, uint64_t)
868#if !defined(__aarch64__)
869CSAN_BUS_SET_FUNC(multi_stream, 8, uint64_t)
870CSAN_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
883CSAN_BUS_PEEK_FUNC(1, uint8_t)
884CSAN_BUS_PEEK_FUNC(2, uint16_t)
885CSAN_BUS_PEEK_FUNC(4, uint32_t)
886#if !defined(__i386__)
887CSAN_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
897CSAN_BUS_POKE_FUNC(1, uint8_t)
898CSAN_BUS_POKE_FUNC(2, uint16_t)
899CSAN_BUS_POKE_FUNC(4, uint32_t)
900#if !defined(__i386__)
901CSAN_BUS_POKE_FUNC(8, uint64_t)
902#endif
c_linker_sym_t sym
Definition: linker_if.m:51
uint64_t * addr
Definition: msi_if.m:89
struct intr_irqsrc ** src
Definition: msi_if.m:76
uintptr_t pc
Definition: subr_csan.c:64
uintptr_t addr
Definition: subr_csan.c:60
uint32_t size
Definition: subr_csan.c:61
bool atomic
Definition: subr_csan.c:63
bool write
Definition: subr_csan.c:62
bool inited
Definition: subr_csan.c:68
csan_cell_t cell
Definition: subr_csan.c:70
uint32_t cnt
Definition: subr_csan.c:69
int kcsan_copyout(const void *kaddr, void *uaddr, size_t len)
Definition: subr_csan.c:368
void * kcsan_memset(void *b, int c, size_t len)
Definition: subr_csan.c:290
#define CSAN_ATOMIC_FUNC_CMPSET(name, type)
Definition: subr_csan.c:414
int kcsan_bus_space_alloc(bus_space_tag_t tag, bus_addr_t reg_start, bus_addr_t reg_end, bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags, bus_addr_t *addrp, bus_space_handle_t *handlep)
Definition: subr_csan.c:711
#define CSAN_BUS_SET_FUNC(func, width, type)
Definition: subr_csan.c:835
char * kcsan_strcpy(char *dst, const char *src)
Definition: subr_csan.c:305
static bool kcsan_access_is_atomic(csan_cell_t *new, csan_cell_t *old)
Definition: subr_csan.c:135
#define CSAN_ATOMIC_FUNC_SUBTRACT(name, type)
Definition: subr_csan.c:482
int kcsan_copyin(const void *uaddr, void *kaddr, size_t len)
Definition: subr_csan.c:354
static void kcsan_report(csan_cell_t *new, u_int newcpu, csan_cell_t *old, u_int oldcpu)
Definition: subr_csan.c:106
#define CSAN_ATOMIC_FUNC_SET(name, type)
Definition: subr_csan.c:469
static void kcsan_enable(void *dummy __unused)
Definition: subr_csan.c:89
void kcsan_bus_space_free(bus_space_tag_t tag, bus_space_handle_t hnd, bus_size_t size)
Definition: subr_csan.c:723
#define CSAN_BUS_WRITE_FUNC(func, width, type)
Definition: subr_csan.c:787
#define CSAN_ATOMIC_FUNC_TESTANDSET(name, type)
Definition: subr_csan.c:515
void * kcsan_memmove(void *dst, const void *src, size_t len)
Definition: subr_csan.c:297
#define CSAN_BUS_PEEK_FUNC(width, type)
Definition: subr_csan.c:874
static bool kcsan_enabled __read_mostly
Definition: subr_csan.c:74
#define _CSAN_ATOMIC_FUNC_STORE(name, type)
Definition: subr_csan.c:487
#define CSAN_ATOMIC_FUNC_CLEAR(name, type)
Definition: subr_csan.c:400
int kcsan_bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t hnd, bus_size_t offset, bus_size_t size, bus_space_handle_t *handlep)
Definition: subr_csan.c:702
#define CSAN_ATOMIC_FUNC_TESTANDCLEAR(name, type)
Definition: subr_csan.c:507
void kcsan_bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t hnd, bus_size_t offset, bus_size_t size, int flags)
Definition: subr_csan.c:731
#define KCSAN_NACCESSES
Definition: subr_csan.c:78
void __tsan_func_exit(void)
Definition: subr_csan.c:267
static csan_cpu_t kcsan_cpus[MAXCPU]
Definition: subr_csan.c:73
void kcsan_bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t hnd, bus_size_t size)
Definition: subr_csan.c:694
void __tsan_func_entry(void *)
Definition: subr_csan.c:262
static void kcsan_access(uintptr_t addr, size_t size, bool write, bool atomic, uintptr_t pc)
Definition: subr_csan.c:145
#define CSAN_BUS_READ_FUNC(func, width, type)
Definition: subr_csan.c:738
#define REPORT
Definition: subr_csan.c:56
#define CSAN_ATOMIC_FUNC_SWAP(name, type)
Definition: subr_csan.c:499
#define CSAN_WRITE(size)
Definition: subr_csan.c:219
#define CSAN_READ(size)
Definition: subr_csan.c:201
void __tsan_init(void)
Definition: subr_csan.c:257
size_t kcsan_strlen(const char *str)
Definition: subr_csan.c:338
#define CSAN_ATOMIC_FUNC_FCMPSET(name, type)
Definition: subr_csan.c:428
int kcsan_strcmp(const char *s1, const char *s2)
Definition: subr_csan.c:322
void __tsan_write_range(uintptr_t, size_t)
Definition: subr_csan.c:247
#define CSAN_ATOMIC_FUNC_STORE(name, type)
Definition: subr_csan.c:495
__FBSDID("$FreeBSD$")
#define CSAN_BUS_WRITE_PTR_FUNC(func, width, type)
Definition: subr_csan.c:794
#define CSAN_ATOMIC_FUNC_ADD(name, type)
Definition: subr_csan.c:387
#define CSAN_ATOMIC_FUNC_LOAD(name, type)
Definition: subr_csan.c:449
void kcsan_cpu_init(u_int cpu)
Definition: subr_csan.c:98
void __tsan_read_range(uintptr_t, size_t)
Definition: subr_csan.c:241
#define __RET_ADDR
Definition: subr_csan.c:76
int kcsan_memcmp(const void *b1, const void *b2, size_t len)
Definition: subr_csan.c:282
int kcsan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
Definition: subr_csan.c:361
#define KCSAN_DELAY
Definition: subr_csan.c:79
void * kcsan_memcpy(void *dst, const void *src, size_t len)
Definition: subr_csan.c:274
SYSINIT(kcsan_enable, SI_SUB_SMP, SI_ORDER_SECOND, kcsan_enable, NULL)
#define CSAN_ATOMIC_FUNC_READANDCLEAR(name, type)
Definition: subr_csan.c:453
#define CSAN_ATOMIC_FUNC_FETCHADD(name, type)
Definition: subr_csan.c:433
int kcsan_bus_space_map(bus_space_tag_t tag, bus_addr_t hnd, bus_size_t size, int flags, bus_space_handle_t *handlep)
Definition: subr_csan.c:686
#define CSAN_BUS_READ_PTR_FUNC(func, width, type)
Definition: subr_csan.c:746
#define CSAN_BUS_POKE_FUNC(width, type)
Definition: subr_csan.c:890
#define CSAN_ATOMIC_FUNC_THREAD_FENCE(name)
Definition: subr_csan.c:662
void kcsan_atomic_interrupt_fence(void)
Definition: subr_csan.c:674
int printf(const char *fmt,...)
Definition: subr_prf.c:397
uint16_t flags
Definition: subr_stats.c:2
static int dummy