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/atomic.h> 12 #include <linux/kcsan.h> 13 #include <linux/sched.h> 14 15 /* The number of adjacent watchpoints to check. */ 16 #define KCSAN_CHECK_ADJACENT 1 17 #define NUM_SLOTS (1 + 2*KCSAN_CHECK_ADJACENT) 18 19 extern unsigned int kcsan_udelay_task; 20 extern unsigned int kcsan_udelay_interrupt; 21 22 /* 23 * Globally enable and disable KCSAN. 24 */ 25 extern bool kcsan_enabled; 26 27 /* 28 * Save/restore IRQ flags state trace dirtied by KCSAN. 29 */ 30 void kcsan_save_irqtrace(struct task_struct *task); 31 void kcsan_restore_irqtrace(struct task_struct *task); 32 33 /* 34 * Statistics counters displayed via debugfs; should only be modified in 35 * slow-paths. 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 extern atomic_long_t kcsan_counters[KCSAN_COUNTER_COUNT]; 90 91 /* 92 * Returns true if data races in the function symbol that maps to func_addr 93 * (offsets are ignored) should *not* be reported. 94 */ 95 extern bool kcsan_skip_report_debugfs(unsigned long func_addr); 96 97 /* 98 * Value-change states. 99 */ 100 enum kcsan_value_change { 101 /* 102 * Did not observe a value-change, however, it is valid to report the 103 * race, depending on preferences. 104 */ 105 KCSAN_VALUE_CHANGE_MAYBE, 106 107 /* 108 * Did not observe a value-change, and it is invalid to report the race. 109 */ 110 KCSAN_VALUE_CHANGE_FALSE, 111 112 /* 113 * The value was observed to change, and the race should be reported. 114 */ 115 KCSAN_VALUE_CHANGE_TRUE, 116 }; 117 118 enum kcsan_report_type { 119 /* 120 * The thread that set up the watchpoint and briefly stalled was 121 * signalled that another thread triggered the watchpoint. 122 */ 123 KCSAN_REPORT_RACE_SIGNAL, 124 125 /* 126 * A thread found and consumed a matching watchpoint. 127 */ 128 KCSAN_REPORT_CONSUMED_WATCHPOINT, 129 130 /* 131 * No other thread was observed to race with the access, but the data 132 * value before and after the stall differs. 133 */ 134 KCSAN_REPORT_RACE_UNKNOWN_ORIGIN, 135 }; 136 137 /* 138 * Print a race report from thread that encountered the race. 139 */ 140 extern void kcsan_report(const volatile void *ptr, size_t size, int access_type, 141 enum kcsan_value_change value_change, 142 enum kcsan_report_type type, int watchpoint_idx); 143 144 #endif /* _KERNEL_KCSAN_KCSAN_H */ 145