[compiler-rt] [tsan][riscv] add Go race detector support for RISC-V sv39 VMA (PR #154701)

Joel Sing via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 21 02:02:37 PDT 2025


https://github.com/4a6f656c created https://github.com/llvm/llvm-project/pull/154701

The majority of readily available RISC-V hardware provides sv39, rather than
sv48. Add a memory mapping for sv39, which will allow the Go race detector
to be used on more hardware.

>From 5a46c94cb88ec4b8652ec975feed4a58cdea2936 Mon Sep 17 00:00:00 2001
From: Joel Sing <joel at sing.id.au>
Date: Thu, 21 Aug 2025 18:49:31 +1000
Subject: [PATCH] [tsan][riscv] add Go race detector support for RISC-V sv39
 VMA

The majority of readily available RISC-V hardware provides sv39,
rather than sv48. Add a memory mapping for sv39, which will allow
the Go race detector to be used on more hardware.
---
 compiler-rt/lib/tsan/go/test.c                |  7 ++++
 compiler-rt/lib/tsan/rtl/tsan_platform.h      | 39 +++++++++++++++++--
 .../lib/tsan/rtl/tsan_platform_linux.cpp      |  4 +-
 3 files changed, 45 insertions(+), 5 deletions(-)

diff --git a/compiler-rt/lib/tsan/go/test.c b/compiler-rt/lib/tsan/go/test.c
index 1b0d828c90447..d328ab1b331d7 100644
--- a/compiler-rt/lib/tsan/go/test.c
+++ b/compiler-rt/lib/tsan/go/test.c
@@ -63,6 +63,13 @@ int main(void) {
   __tsan_init(&thr0, &proc0, symbolize_cb);
   current_proc = proc0;
 
+#if defined(__riscv) && (__riscv_xlen == 64) && defined(__linux__)
+  // Use correct go_heap for riscv64 sv39.
+  if (65 - __builtin_clzl((unsigned long)__builtin_frame_address(0)) == 39) {
+    go_heap = (void *)0x511100000;
+  }
+#endif
+
   // Allocate something resembling a heap in Go.
   buf0 = mmap(go_heap, 16384, PROT_READ | PROT_WRITE,
               MAP_PRIVATE | MAP_FIXED | MAP_ANON, -1, 0);
diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform.h b/compiler-rt/lib/tsan/rtl/tsan_platform.h
index ada594bc11fc7..158ed58809a72 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_platform.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_platform.h
@@ -681,6 +681,33 @@ struct MappingGoMips64_47 {
   static const uptr kShadowAdd = 0x200000000000ull;
 };
 
+/* Go on linux/riscv64 (39-bit VMA)
+0000 0000 0000 - 000a 0000 0000: executable and heap (40 GiB)
+000a 0000 0000 - 000c 0000 0000: -
+000c 0000 0000 - 0034 0000 0000: shadow - 160 GiB ( ~ 4 * app)
+0034 0000 0000 - 0035 0000 0000: -
+0035 0000 0000 - 0039 0000 0000: metainfo - 40 GiB ( ~ 1 * app)
+0039 0000 0000 - 0040 0000 0000: -
+*/
+struct MappingGoRiscv64_39 {
+  static const uptr kMetaShadowBeg = 0x003500000000ull;
+  static const uptr kMetaShadowEnd = 0x003900000000ull;
+  static const uptr kShadowBeg = 0x000c00000000ull;
+  static const uptr kShadowEnd = 0x003400000000ull;
+  static const uptr kLoAppMemBeg = 0x000000010000ull;
+  static const uptr kLoAppMemEnd = 0x000a00000000ull;
+  static const uptr kMidAppMemBeg = 0;
+  static const uptr kMidAppMemEnd = 0;
+  static const uptr kHiAppMemBeg = 0;
+  static const uptr kHiAppMemEnd = 0;
+  static const uptr kHeapMemBeg = 0;
+  static const uptr kHeapMemEnd = 0;
+  static const uptr kVdsoBeg = 0;
+  static const uptr kShadowMsk = 0;
+  static const uptr kShadowXor = 0;
+  static const uptr kShadowAdd = 0x000c00000000ull;
+};
+
 /* Go on linux/riscv64 (48-bit VMA)
 0000 0001 0000 - 00e0 0000 0000: executable and heap (896 GiB)
 00e0 0000 0000 - 2000 0000 0000: -
@@ -689,7 +716,7 @@ struct MappingGoMips64_47 {
 3000 0000 0000 - 3100 0000 0000: metainfo - 1 TiB ( ~ 1 * app)
 3100 0000 0000 - 8000 0000 0000: -
 */
-struct MappingGoRiscv64 {
+struct MappingGoRiscv64_48 {
   static const uptr kMetaShadowBeg = 0x300000000000ull;
   static const uptr kMetaShadowEnd = 0x310000000000ull;
   static const uptr kShadowBeg = 0x200000000000ull;
@@ -756,7 +783,12 @@ ALWAYS_INLINE auto SelectMapping(Arg arg) {
 #  elif defined(__loongarch_lp64)
   return Func::template Apply<MappingGoLoongArch64_47>(arg);
 #  elif SANITIZER_RISCV64
-  return Func::template Apply<MappingGoRiscv64>(arg);
+  switch (vmaSize) {
+    case 39:
+      return Func::template Apply<MappingGoRiscv64_39>(arg);
+    case 48:
+      return Func::template Apply<MappingGoRiscv64_48>(arg);
+   }
 #  elif SANITIZER_WINDOWS
   return Func::template Apply<MappingGoWindows>(arg);
 #  else
@@ -827,7 +859,8 @@ void ForEachMapping() {
   Func::template Apply<MappingGoAarch64>();
   Func::template Apply<MappingGoLoongArch64_47>();
   Func::template Apply<MappingGoMips64_47>();
-  Func::template Apply<MappingGoRiscv64>();
+  Func::template Apply<MappingGoRiscv64_39>();
+  Func::template Apply<MappingGoRiscv64_48>();
   Func::template Apply<MappingGoS390x>();
 }
 
diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
index 2c55645a15479..4b55aab49a2b9 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
@@ -393,9 +393,9 @@ void InitializePlatformEarly() {
     Die();
   }
 #    else
-  if (vmaSize != 48) {
+  if (vmaSize != 39 && vmaSize != 48) {
     Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
-    Printf("FATAL: Found %zd - Supported 48\n", vmaSize);
+    Printf("FATAL: Found %zd - Supported 39 and 48\n", vmaSize);
     Die();
   }
 #    endif



More information about the llvm-commits mailing list