|
| 1 | +From fa6e00abe9be4a451d81a29309c933435db8fe40 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Adeel Mujahid <3840695+am11@users.noreply.github.com> |
| 3 | +Date: Sat, 15 Nov 2025 22:15:48 +0200 |
| 4 | +Subject: [PATCH] Disable TLS optimization for musl riscv64 (#121662) |
| 5 | + |
| 6 | +On linux-musl-riscv64, when corehost (dotnet) dlopen()s libcoreclr, we |
| 7 | +get: |
| 8 | + |
| 9 | +> \# dotnet --version |
| 10 | +> Failed to load |
| 11 | +/root/.dotnet/shared/Microsoft.NETCore.App/10.0.0-rtm.25564.199/libcoreclr.so, |
| 12 | +error: Error relocating |
| 13 | +/root/.dotnet/shared/Microsoft.NETCore.App/10.0.0-rtm.25564.199/libcoreclr.so: |
| 14 | +Uq???&?J?N?R?V?Z? .????: initial-exec TLS resolves to dynamic definition |
| 15 | +in |
| 16 | +/root/.dotnet/shared/Microsoft.NETCore.App/10.0.0-rtm.25564.199/libcoreclr.so |
| 17 | +Failed to bind to CoreCLR at |
| 18 | +'/root/.dotnet/shared/Microsoft.NETCore.App/10.0.0-rtm.25564.199/' |
| 19 | +Failed to create CoreCLR, HRESULT: 0x80008088 |
| 20 | + |
| 21 | +musl maintainer described the issue on this golang thread: |
| 22 | +https://github.com/golang/go/issues/54805#issuecomment-1253972041. When |
| 23 | +I tried |
| 24 | +`LD_PRELOAD=/root/.dotnet/shared/Microsoft.NETCore.App/10.0.0-rtm.25564.199/libcoreclr.so |
| 25 | +dotnet --version`, it started working and SDK started working. |
| 26 | + |
| 27 | +By disabling the optimization as we have done for linux-musl-arm64 and |
| 28 | +removing `la.tls.ie` from binary works without the `LD_PRELOAD` hack. |
| 29 | + |
| 30 | +--------- |
| 31 | + |
| 32 | +Co-authored-by: Jan Kotas <jkotas@microsoft.com> |
| 33 | +--- |
| 34 | + src/coreclr/vm/riscv64/asmhelpers.S | 4 ++++ |
| 35 | + src/coreclr/vm/threadstatics.cpp | 5 +++++ |
| 36 | + 2 files changed, 9 insertions(+) |
| 37 | + |
| 38 | +diff --git a/src/coreclr/vm/riscv64/asmhelpers.S b/src/coreclr/vm/riscv64/asmhelpers.S |
| 39 | +index 1c03436880c0cc..e9c049f1b64197 100644 |
| 40 | +--- a/src/coreclr/vm/riscv64/asmhelpers.S |
| 41 | ++++ b/src/coreclr/vm/riscv64/asmhelpers.S |
| 42 | +@@ -844,10 +844,14 @@ LEAF_END JIT_PatchpointForced, _TEXT |
| 43 | + // size_t GetThreadStaticsVariableOffset() |
| 44 | + |
| 45 | + // Load offset of native thread local variable `t_ThreadStatics` in TCB and return it in `a0` register. |
| 46 | ++#if !defined(TARGET_LINUX_MUSL) |
| 47 | ++// Uses initial-exec TLS model which is faster but incompatible with musl's dynamic loading. |
| 48 | ++// On musl, this function is not compiled and the optimization is disabled in threadstatics.cpp. |
| 49 | + LEAF_ENTRY GetThreadStaticsVariableOffset, _TEXT |
| 50 | + la.tls.ie a0, t_ThreadStatics |
| 51 | + EPILOG_RETURN |
| 52 | + LEAF_END GetThreadStaticsVariableOffset, _TEXT |
| 53 | ++#endif // !TARGET_LINUX_MUSL |
| 54 | + |
| 55 | + LEAF_ENTRY JIT_PollGC, _TEXT |
| 56 | + PREPARE_EXTERNAL_VAR g_TrapReturningThreads, t0 |
| 57 | +diff --git a/src/coreclr/vm/threadstatics.cpp b/src/coreclr/vm/threadstatics.cpp |
| 58 | +index 5847cc5c13bb47..0f45787cd8f92b 100644 |
| 59 | +--- a/src/coreclr/vm/threadstatics.cpp |
| 60 | ++++ b/src/coreclr/vm/threadstatics.cpp |
| 61 | +@@ -916,6 +916,8 @@ bool CanJITOptimizeTLSAccess() |
| 62 | + // Optimization is disabled for linux/x86 |
| 63 | + #elif defined(TARGET_LINUX_MUSL) && defined(TARGET_ARM64) |
| 64 | + // Optimization is disabled for linux musl arm64 |
| 65 | ++#elif defined(TARGET_LINUX_MUSL) && defined(TARGET_RISCV64) |
| 66 | ++ // Optimization is disabled for linux musl riscv64 |
| 67 | + #elif defined(TARGET_FREEBSD) && defined(TARGET_ARM64) |
| 68 | + // Optimization is disabled for FreeBSD/arm64 |
| 69 | + #elif defined(TARGET_ANDROID) |
| 70 | +@@ -1095,7 +1097,10 @@ void GetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) |
| 71 | + // For Linux arm64/loongarch64/riscv64, just get the offset of thread static variable, and during execution, |
| 72 | + // this offset, arm64 taken from trpid_elp0 system register gives back the thread variable address. |
| 73 | + // this offset, loongarch64 taken from $tp register gives back the thread variable address. |
| 74 | ++#if !(defined(TARGET_LINUX_MUSL) && defined(TARGET_RISCV64)) |
| 75 | ++ // On musl riscv64, this optimization is disabled due to initial-exec TLS incompatibility. |
| 76 | + threadStaticBaseOffset = GetThreadStaticsVariableOffset(); |
| 77 | ++#endif |
| 78 | + |
| 79 | + #else |
| 80 | + _ASSERTE_MSG(false, "Unsupported scenario of optimizing TLS access on Linux Arm32/x86 and Android"); |
0 commit comments