Skip to content

Commit 2e986b8

Browse files
melverpaulmckrcu
authored andcommitted
kcsan: Optimize debugfs stats counters
Remove kcsan_counter_inc/dec() functions, as they perform no other logic, and are no longer needed. This avoids several calls in kcsan_setup_watchpoint() and kcsan_found_watchpoint(), as well as lets the compiler warn us about potential out-of-bounds accesses as the array's size is known at all usage sites at compile-time. Signed-off-by: Marco Elver <elver@google.com> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
1 parent 178a187 commit 2e986b8

4 files changed

Lines changed: 23 additions & 34 deletions

File tree

kernel/kcsan/core.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -367,13 +367,13 @@ static noinline void kcsan_found_watchpoint(const volatile void *ptr,
367367
* already removed the watchpoint, or another thread consumed
368368
* the watchpoint before this thread.
369369
*/
370-
kcsan_counter_inc(KCSAN_COUNTER_REPORT_RACES);
370+
atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_REPORT_RACES]);
371371
}
372372

373373
if ((type & KCSAN_ACCESS_ASSERT) != 0)
374-
kcsan_counter_inc(KCSAN_COUNTER_ASSERT_FAILURES);
374+
atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_ASSERT_FAILURES]);
375375
else
376-
kcsan_counter_inc(KCSAN_COUNTER_DATA_RACES);
376+
atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_DATA_RACES]);
377377

378378
user_access_restore(flags);
379379
}
@@ -414,7 +414,7 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type)
414414
goto out;
415415

416416
if (!check_encodable((unsigned long)ptr, size)) {
417-
kcsan_counter_inc(KCSAN_COUNTER_UNENCODABLE_ACCESSES);
417+
atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_UNENCODABLE_ACCESSES]);
418418
goto out;
419419
}
420420

@@ -434,12 +434,12 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type)
434434
* with which should_watch() returns true should be tweaked so
435435
* that this case happens very rarely.
436436
*/
437-
kcsan_counter_inc(KCSAN_COUNTER_NO_CAPACITY);
437+
atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_NO_CAPACITY]);
438438
goto out_unlock;
439439
}
440440

441-
kcsan_counter_inc(KCSAN_COUNTER_SETUP_WATCHPOINTS);
442-
kcsan_counter_inc(KCSAN_COUNTER_USED_WATCHPOINTS);
441+
atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_SETUP_WATCHPOINTS]);
442+
atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_USED_WATCHPOINTS]);
443443

444444
/*
445445
* Read the current value, to later check and infer a race if the data
@@ -541,16 +541,16 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type)
541541
* increment this counter.
542542
*/
543543
if (is_assert && value_change == KCSAN_VALUE_CHANGE_TRUE)
544-
kcsan_counter_inc(KCSAN_COUNTER_ASSERT_FAILURES);
544+
atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_ASSERT_FAILURES]);
545545

546546
kcsan_report(ptr, size, type, value_change, KCSAN_REPORT_RACE_SIGNAL,
547547
watchpoint - watchpoints);
548548
} else if (value_change == KCSAN_VALUE_CHANGE_TRUE) {
549549
/* Inferring a race, since the value should not have changed. */
550550

551-
kcsan_counter_inc(KCSAN_COUNTER_RACES_UNKNOWN_ORIGIN);
551+
atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_RACES_UNKNOWN_ORIGIN]);
552552
if (is_assert)
553-
kcsan_counter_inc(KCSAN_COUNTER_ASSERT_FAILURES);
553+
atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_ASSERT_FAILURES]);
554554

555555
if (IS_ENABLED(CONFIG_KCSAN_REPORT_RACE_UNKNOWN_ORIGIN) || is_assert)
556556
kcsan_report(ptr, size, type, KCSAN_VALUE_CHANGE_TRUE,
@@ -563,7 +563,7 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type)
563563
* reused after this point.
564564
*/
565565
remove_watchpoint(watchpoint);
566-
kcsan_counter_dec(KCSAN_COUNTER_USED_WATCHPOINTS);
566+
atomic_long_dec(&kcsan_counters[KCSAN_COUNTER_USED_WATCHPOINTS]);
567567
out_unlock:
568568
if (!kcsan_interrupt_watcher)
569569
local_irq_restore(irq_flags);

kernel/kcsan/debugfs.c

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@
1717

1818
#include "kcsan.h"
1919

20-
/*
21-
* Statistics counters.
22-
*/
23-
static atomic_long_t counters[KCSAN_COUNTER_COUNT];
20+
atomic_long_t kcsan_counters[KCSAN_COUNTER_COUNT];
2421
static const char *const counter_names[] = {
2522
[KCSAN_COUNTER_USED_WATCHPOINTS] = "used_watchpoints",
2623
[KCSAN_COUNTER_SETUP_WATCHPOINTS] = "setup_watchpoints",
@@ -53,16 +50,6 @@ static struct {
5350
};
5451
static DEFINE_SPINLOCK(report_filterlist_lock);
5552

56-
void kcsan_counter_inc(enum kcsan_counter_id id)
57-
{
58-
atomic_long_inc(&counters[id]);
59-
}
60-
61-
void kcsan_counter_dec(enum kcsan_counter_id id)
62-
{
63-
atomic_long_dec(&counters[id]);
64-
}
65-
6653
/*
6754
* The microbenchmark allows benchmarking KCSAN core runtime only. To run
6855
* multiple threads, pipe 'microbench=<iters>' from multiple tasks into the
@@ -206,8 +193,10 @@ static int show_info(struct seq_file *file, void *v)
206193

207194
/* show stats */
208195
seq_printf(file, "enabled: %i\n", READ_ONCE(kcsan_enabled));
209-
for (i = 0; i < KCSAN_COUNTER_COUNT; ++i)
210-
seq_printf(file, "%s: %ld\n", counter_names[i], atomic_long_read(&counters[i]));
196+
for (i = 0; i < KCSAN_COUNTER_COUNT; ++i) {
197+
seq_printf(file, "%s: %ld\n", counter_names[i],
198+
atomic_long_read(&kcsan_counters[i]));
199+
}
211200

212201
/* show filter functions, and filter type */
213202
spin_lock_irqsave(&report_filterlist_lock, flags);

kernel/kcsan/kcsan.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#ifndef _KERNEL_KCSAN_KCSAN_H
99
#define _KERNEL_KCSAN_KCSAN_H
1010

11+
#include <linux/atomic.h>
1112
#include <linux/kcsan.h>
1213
#include <linux/sched.h>
1314

@@ -34,6 +35,10 @@ void kcsan_restore_irqtrace(struct task_struct *task);
3435
*/
3536
void kcsan_debugfs_init(void);
3637

38+
/*
39+
* Statistics counters displayed via debugfs; should only be modified in
40+
* slow-paths.
41+
*/
3742
enum kcsan_counter_id {
3843
/*
3944
* Number of watchpoints currently in use.
@@ -86,12 +91,7 @@ enum kcsan_counter_id {
8691

8792
KCSAN_COUNTER_COUNT, /* number of counters */
8893
};
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);
94+
extern atomic_long_t kcsan_counters[KCSAN_COUNTER_COUNT];
9595

9696
/*
9797
* Returns true if data races in the function symbol that maps to func_addr

kernel/kcsan/report.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ static bool prepare_report_consumer(unsigned long *flags,
559559
* If the actual accesses to not match, this was a false
560560
* positive due to watchpoint encoding.
561561
*/
562-
kcsan_counter_inc(KCSAN_COUNTER_ENCODING_FALSE_POSITIVES);
562+
atomic_long_inc(&kcsan_counters[KCSAN_COUNTER_ENCODING_FALSE_POSITIVES]);
563563
goto discard;
564564
}
565565

0 commit comments

Comments
 (0)