summaryrefslogtreecommitdiffstats
path: root/kernel/kcsan
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-04-24 20:46:53 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2023-04-24 20:46:53 +0200
commit022e32094ed2a688dcb2721534abd0a291905f29 (patch)
treeb61a6e646556fb9e70bc638b0487fe1122d96adb /kernel/kcsan
parentMerge tag 'tpmdd-v6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/j... (diff)
parentkcsan: Avoid READ_ONCE() in read_instrumented_memory() (diff)
downloadlinux-022e32094ed2a688dcb2721534abd0a291905f29.tar.xz
linux-022e32094ed2a688dcb2721534abd0a291905f29.zip
Merge tag 'kcsan.2023.04.04a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu
Pull KCSAN updates from Paul McKenney: "Kernel concurrency sanitizer (KCSAN) updates for v6.4 This fixes kernel-doc warnings and also updates instrumentation from READ_ONCE() to volatile in order to avoid unaligned load-acquire instructions on arm64 in kernels built with LTO" * tag 'kcsan.2023.04.04a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu: kcsan: Avoid READ_ONCE() in read_instrumented_memory() instrumented.h: Fix all kernel-doc format warnings
Diffstat (limited to 'kernel/kcsan')
-rw-r--r--kernel/kcsan/core.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/kernel/kcsan/core.c b/kernel/kcsan/core.c
index 54d077e1a2dc..5a60cc52adc0 100644
--- a/kernel/kcsan/core.c
+++ b/kernel/kcsan/core.c
@@ -337,11 +337,20 @@ static void delay_access(int type)
*/
static __always_inline u64 read_instrumented_memory(const volatile void *ptr, size_t size)
{
+ /*
+ * In the below we don't necessarily need the read of the location to
+ * be atomic, and we don't use READ_ONCE(), since all we need for race
+ * detection is to observe 2 different values.
+ *
+ * Furthermore, on certain architectures (such as arm64), READ_ONCE()
+ * may turn into more complex instructions than a plain load that cannot
+ * do unaligned accesses.
+ */
switch (size) {
- case 1: return READ_ONCE(*(const u8 *)ptr);
- case 2: return READ_ONCE(*(const u16 *)ptr);
- case 4: return READ_ONCE(*(const u32 *)ptr);
- case 8: return READ_ONCE(*(const u64 *)ptr);
+ case 1: return *(const volatile u8 *)ptr;
+ case 2: return *(const volatile u16 *)ptr;
+ case 4: return *(const volatile u32 *)ptr;
+ case 8: return *(const volatile u64 *)ptr;
default: return 0; /* Ignore; we do not diff the values. */
}
}