Skip to content

Commit 31f605a

Browse files
melverpaulmckrcu
authored andcommitted
kcsan, compiler_types: Introduce __data_racy type qualifier
Based on the discussion at [1], it would be helpful to mark certain variables as explicitly "data racy", which would result in KCSAN not reporting data races involving any accesses on such variables. To do that, introduce the __data_racy type qualifier: struct foo { ... int __data_racy bar; ... }; In KCSAN-kernels, __data_racy turns into volatile, which KCSAN already treats specially by considering them "marked". In non-KCSAN kernels the type qualifier turns into no-op. The generated code between KCSAN-instrumented kernels and non-KCSAN kernels is already huge (inserted calls into runtime for every memory access), so the extra generated code (if any) due to volatile for few such __data_racy variables are unlikely to have measurable impact on performance. Link: https://lore.kernel.org/all/CAHk-=wi3iondeh_9V2g3Qz5oHTRjLsOpoy83hb58MVh=nRZe0A@mail.gmail.com/ [1] Suggested-by: Linus Torvalds <[email protected]> Signed-off-by: Marco Elver <[email protected]> Cc: Paul E. McKenney <[email protected]> Cc: Tetsuo Handa <[email protected]> Signed-off-by: Paul E. McKenney <[email protected]>
1 parent 39cd87c commit 31f605a

File tree

3 files changed

+34
-0
lines changed

3 files changed

+34
-0
lines changed

Documentation/dev-tools/kcsan.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,16 @@ the below options are available:
9191
behaviour when encountering a data race is deemed safe. Please see
9292
`"Marking Shared-Memory Accesses" in the LKMM`_ for more information.
9393

94+
* Similar to ``data_race(...)``, the type qualifier ``__data_racy`` can be used
95+
to document that all data races due to accesses to a variable are intended
96+
and should be ignored by KCSAN::
97+
98+
struct foo {
99+
...
100+
int __data_racy stats_counter;
101+
...
102+
};
103+
94104
* Disabling data race detection for entire functions can be accomplished by
95105
using the function attribute ``__no_kcsan``::
96106

include/linux/compiler_types.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,16 @@ struct ftrace_likely_data {
273273
* disable all instrumentation. See Kconfig.kcsan where this is mandatory.
274274
*/
275275
# define __no_kcsan __no_sanitize_thread __disable_sanitizer_instrumentation
276+
/*
277+
* Type qualifier to mark variables where all data-racy accesses should be
278+
* ignored by KCSAN. Note, the implementation simply marks these variables as
279+
* volatile, since KCSAN will treat such accesses as "marked".
280+
*/
281+
# define __data_racy volatile
276282
# define __no_sanitize_or_inline __no_kcsan notrace __maybe_unused
277283
#else
278284
# define __no_kcsan
285+
# define __data_racy
279286
#endif
280287

281288
#ifndef __no_sanitize_or_inline

kernel/kcsan/kcsan_test.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ static long test_array[3 * PAGE_SIZE / sizeof(long)];
304304
static struct {
305305
long val[8];
306306
} test_struct;
307+
static long __data_racy test_data_racy;
307308
static DEFINE_SEQLOCK(test_seqlock);
308309
static DEFINE_SPINLOCK(test_spinlock);
309310
static DEFINE_MUTEX(test_mutex);
@@ -358,6 +359,8 @@ static noinline void test_kernel_write_uninstrumented(void) { test_var++; }
358359

359360
static noinline void test_kernel_data_race(void) { data_race(test_var++); }
360361

362+
static noinline void test_kernel_data_racy_qualifier(void) { test_data_racy++; }
363+
361364
static noinline void test_kernel_assert_writer(void)
362365
{
363366
ASSERT_EXCLUSIVE_WRITER(test_var);
@@ -1009,6 +1012,19 @@ static void test_data_race(struct kunit *test)
10091012
KUNIT_EXPECT_FALSE(test, match_never);
10101013
}
10111014

1015+
/* Test the __data_racy type qualifier. */
1016+
__no_kcsan
1017+
static void test_data_racy_qualifier(struct kunit *test)
1018+
{
1019+
bool match_never = false;
1020+
1021+
begin_test_checks(test_kernel_data_racy_qualifier, test_kernel_data_racy_qualifier);
1022+
do {
1023+
match_never = report_available();
1024+
} while (!end_test_checks(match_never));
1025+
KUNIT_EXPECT_FALSE(test, match_never);
1026+
}
1027+
10121028
__no_kcsan
10131029
static void test_assert_exclusive_writer(struct kunit *test)
10141030
{
@@ -1424,6 +1440,7 @@ static struct kunit_case kcsan_test_cases[] = {
14241440
KCSAN_KUNIT_CASE(test_read_plain_atomic_rmw),
14251441
KCSAN_KUNIT_CASE(test_zero_size_access),
14261442
KCSAN_KUNIT_CASE(test_data_race),
1443+
KCSAN_KUNIT_CASE(test_data_racy_qualifier),
14271444
KCSAN_KUNIT_CASE(test_assert_exclusive_writer),
14281445
KCSAN_KUNIT_CASE(test_assert_exclusive_access),
14291446
KCSAN_KUNIT_CASE(test_assert_exclusive_access_writer),

0 commit comments

Comments
 (0)