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