Skip to content

Commit 75d75b7

Browse files
melverKAGA-KOKO
authored andcommitted
kcsan: Support distinguishing volatile accesses
In the kernel, the "volatile" keyword is used in various concurrent contexts, whether in low-level synchronization primitives or for legacy reasons. If supported by the compiler, it will be assumed that aligned volatile accesses up to sizeof(long long) (matching compiletime_assert_rwonce_type()) are atomic. Recent versions of Clang [1] (GCC tentative [2]) can instrument volatile accesses differently. Add the option (required) to enable the instrumentation, and provide the necessary runtime functions. None of the updated compilers are widely available yet (Clang 11 will be the first release to support the feature). [1] llvm/llvm-project@5a2c311 [2] https://gcc.gnu.org/pipermail/gcc-patches/2020-April/544452.html This change allows removing of any explicit checks in primitives such as READ_ONCE() and WRITE_ONCE(). [ bp: Massage commit message a bit. ] Signed-off-by: Marco Elver <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Acked-by: Will Deacon <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 0e1aa5b commit 75d75b7

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

kernel/kcsan/core.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,49 @@ void __tsan_write_range(void *ptr, size_t size)
789789
}
790790
EXPORT_SYMBOL(__tsan_write_range);
791791

792+
/*
793+
* Use of explicit volatile is generally disallowed [1], however, volatile is
794+
* still used in various concurrent context, whether in low-level
795+
* synchronization primitives or for legacy reasons.
796+
* [1] https://lwn.net/Articles/233479/
797+
*
798+
* We only consider volatile accesses atomic if they are aligned and would pass
799+
* the size-check of compiletime_assert_rwonce_type().
800+
*/
801+
#define DEFINE_TSAN_VOLATILE_READ_WRITE(size) \
802+
void __tsan_volatile_read##size(void *ptr) \
803+
{ \
804+
const bool is_atomic = size <= sizeof(long long) && \
805+
IS_ALIGNED((unsigned long)ptr, size); \
806+
if (IS_ENABLED(CONFIG_KCSAN_IGNORE_ATOMICS) && is_atomic) \
807+
return; \
808+
check_access(ptr, size, is_atomic ? KCSAN_ACCESS_ATOMIC : 0); \
809+
} \
810+
EXPORT_SYMBOL(__tsan_volatile_read##size); \
811+
void __tsan_unaligned_volatile_read##size(void *ptr) \
812+
__alias(__tsan_volatile_read##size); \
813+
EXPORT_SYMBOL(__tsan_unaligned_volatile_read##size); \
814+
void __tsan_volatile_write##size(void *ptr) \
815+
{ \
816+
const bool is_atomic = size <= sizeof(long long) && \
817+
IS_ALIGNED((unsigned long)ptr, size); \
818+
if (IS_ENABLED(CONFIG_KCSAN_IGNORE_ATOMICS) && is_atomic) \
819+
return; \
820+
check_access(ptr, size, \
821+
KCSAN_ACCESS_WRITE | \
822+
(is_atomic ? KCSAN_ACCESS_ATOMIC : 0)); \
823+
} \
824+
EXPORT_SYMBOL(__tsan_volatile_write##size); \
825+
void __tsan_unaligned_volatile_write##size(void *ptr) \
826+
__alias(__tsan_volatile_write##size); \
827+
EXPORT_SYMBOL(__tsan_unaligned_volatile_write##size)
828+
829+
DEFINE_TSAN_VOLATILE_READ_WRITE(1);
830+
DEFINE_TSAN_VOLATILE_READ_WRITE(2);
831+
DEFINE_TSAN_VOLATILE_READ_WRITE(4);
832+
DEFINE_TSAN_VOLATILE_READ_WRITE(8);
833+
DEFINE_TSAN_VOLATILE_READ_WRITE(16);
834+
792835
/*
793836
* The below are not required by KCSAN, but can still be emitted by the
794837
* compiler.

scripts/Makefile.kcsan

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ else
99
cc-param = --param -$(1)
1010
endif
1111

12+
# Keep most options here optional, to allow enabling more compilers if absence
13+
# of some options does not break KCSAN nor causes false positive reports.
1214
CFLAGS_KCSAN := -fsanitize=thread \
13-
$(call cc-option,$(call cc-param,tsan-instrument-func-entry-exit=0) -fno-optimize-sibling-calls)
15+
$(call cc-option,$(call cc-param,tsan-instrument-func-entry-exit=0) -fno-optimize-sibling-calls) \
16+
$(call cc-param,tsan-distinguish-volatile=1)
1417

1518
endif # CONFIG_KCSAN

0 commit comments

Comments
 (0)