1 /* SPDX-License-Identifier: GPL-2.0 */ 2 3 /* 4 * The Kernel Concurrency Sanitizer (KCSAN) infrastructure. For more info please 5 * see Documentation/dev-tools/kcsan.rst. 6 */ 7 8 #ifndef _KERNEL_KCSAN_KCSAN_H 9 #define _KERNEL_KCSAN_KCSAN_H 10 11 #include <linux/kcsan.h> 12 #include <linux/sched.h> 13 14 /* The number of adjacent watchpoints to check. */ 15 #define KCSAN_CHECK_ADJACENT 1 16 #define NUM_SLOTS (1 + 2*KCSAN_CHECK_ADJACENT) 17 18 extern unsigned int kcsan_udelay_task; 19 extern unsigned int kcsan_udelay_interrupt; 20 21 /* 22 * Globally enable and disable KCSAN. 23 */ 24 extern bool kcsan_enabled; 25 26 /* 27 * Save/restore IRQ flags state trace dirtied by KCSAN. 28 */ 29 void kcsan_save_irqtrace(struct task_struct *task); 30 void kcsan_restore_irqtrace(struct task_struct *task); 31 32 /* 33 * Initialize debugfs file. 34 */ 35 void kcsan_debugfs_init(void); 36 37 enum kcsan_counter_id { 38 /* 39 * Number of watchpoints currently in use. 40 */ 41 KCSAN_COUNTER_USED_WATCHPOINTS, 42 43 /* 44 * Total number of watchpoints set up. 45 */ 46 KCSAN_COUNTER_SETUP_WATCHPOINTS, 47 48 /* 49 * Total number of data races. 50 */ 51 KCSAN_COUNTER_DATA_RACES, 52 53 /* 54 * Total number of ASSERT failures due to races. If the observed race is 55 * due to two conflicting ASSERT type accesses, then both will be 56 * counted. 57 */ 58 KCSAN_COUNTER_ASSERT_FAILURES, 59 60 /* 61 * Number of times no watchpoints were available. 62 */ 63 KCSAN_COUNTER_NO_CAPACITY, 64 65 /* 66 * A thread checking a watchpoint raced with another checking thread; 67 * only one will be reported. 68 */ 69 KCSAN_COUNTER_REPORT_RACES, 70 71 /* 72 * Observed data value change, but writer thread unknown. 73 */ 74 KCSAN_COUNTER_RACES_UNKNOWN_ORIGIN, 75 76 /* 77 * The access cannot be encoded to a valid watchpoint. 78 */ 79 KCSAN_COUNTER_UNENCODABLE_ACCESSES, 80 81 /* 82 * Watchpoint encoding caused a watchpoint to fire on mismatching 83 * accesses. 84 */ 85 KCSAN_COUNTER_ENCODING_FALSE_POSITIVES, 86 87 KCSAN_COUNTER_COUNT, /* number of counters */ 88 }; 89 90 /* 91 * Increment/decrement counter with given id; avoid calling these in fast-path. 92 */ 93 extern void kcsan_counter_inc(enum kcsan_counter_id id); 94 extern void kcsan_counter_dec(enum kcsan_counter_id id); 95 96 /* 97 * Returns true if data races in the function symbol that maps to func_addr 98 * (offsets are ignored) should *not* be reported. 99 */ 100 extern bool kcsan_skip_report_debugfs(unsigned long func_addr); 101 102 /* 103 * Value-change states. 104 */ 105 enum kcsan_value_change { 106 /* 107 * Did not observe a value-change, however, it is valid to report the 108 * race, depending on preferences. 109 */ 110 KCSAN_VALUE_CHANGE_MAYBE, 111 112 /* 113 * Did not observe a value-change, and it is invalid to report the race. 114 */ 115 KCSAN_VALUE_CHANGE_FALSE, 116 117 /* 118 * The value was observed to change, and the race should be reported. 119 */ 120 KCSAN_VALUE_CHANGE_TRUE, 121 }; 122 123 enum kcsan_report_type { 124 /* 125 * The thread that set up the watchpoint and briefly stalled was 126 * signalled that another thread triggered the watchpoint. 127 */ 128 KCSAN_REPORT_RACE_SIGNAL, 129 130 /* 131 * A thread found and consumed a matching watchpoint. 132 */ 133 KCSAN_REPORT_CONSUMED_WATCHPOINT, 134 135 /* 136 * No other thread was observed to race with the access, but the data 137 * value before and after the stall differs. 138 */ 139 KCSAN_REPORT_RACE_UNKNOWN_ORIGIN, 140 }; 141 142 /* 143 * Print a race report from thread that encountered the race. 144 */ 145 extern void kcsan_report(const volatile void *ptr, size_t size, int access_type, 146 enum kcsan_value_change value_change, 147 enum kcsan_report_type type, int watchpoint_idx); 148 149 #endif /* _KERNEL_KCSAN_KCSAN_H */ 150