aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/tls_arm.s
diff options
context:
space:
mode:
authorDave Cheney <dave@cheney.net>2014-09-19 02:02:21 +0000
committerDave Cheney <dave@cheney.net>2014-09-19 02:02:21 +0000
commit66795e8ba101fc20916196db6d343b0d927e7dd5 (patch)
tree803a4a08bce09577c31e0c0cf27327116df8847f /src/runtime/tls_arm.s
parent54b63f06478d390d69fc826a16ab19dc6b5d5503 (diff)
downloadgo-66795e8ba101fc20916196db6d343b0d927e7dd5.tar.gz
go-66795e8ba101fc20916196db6d343b0d927e7dd5.zip
runtime: fix GOARM<7 build
Update #8690 If liblink determines that the host doesn't support TLS it replaces the MRC call with a BL runtime.tls_read_fallback. The problem is save_g doesn't expect anyone to make any BL calls and hasn't setup its own link register properly so when runtime.tls_read_fallback returns the LR points to save_g, not save_g's caller so the RET at the end of the function turns into an infinite loop. This fix is only a proof of concept, I think the real fix should go into liblink as its MRC substitution is not as transparent as expected. LGTM=rsc R=rsc, minux CC=golang-codereviews https://golang.org/cl/143050043
Diffstat (limited to 'src/runtime/tls_arm.s')
-rw-r--r--src/runtime/tls_arm.s9
1 files changed, 9 insertions, 0 deletions
diff --git a/src/runtime/tls_arm.s b/src/runtime/tls_arm.s
index 7a247ab195..039b013833 100644
--- a/src/runtime/tls_arm.s
+++ b/src/runtime/tls_arm.s
@@ -29,7 +29,13 @@ TEXT runtimeĀ·save_g(SB),NOSPLIT,$-4
MOVW g, R0 // preserve R0 across call to setg<>
RET
#endif
+ // If the host does not support MRC the linker will replace it with
+ // a call to runtime.read_tls_fallback which jumps to __kuser_get_tls.
+ // Both functions are written to only disturb R0 so it should be safe to
+ // use R11 here to temporarily store LR.
+ MOVW LR, R11
MRC 15, 0, R0, C13, C0, 3 // fetch TLS base pointer
+ MOVW R11, LR
// $runtime.tlsg(SB) is a special linker symbol.
// It is the offset from the TLS base pointer to our
// thread-local storage for g.
@@ -51,7 +57,10 @@ TEXT runtimeĀ·load_g(SB),NOSPLIT,$0
// nothing to do as nacl/arm does not use TLS at all.
RET
#endif
+ // See comment in save_g.
+ MOVW LR, R11
MRC 15, 0, R0, C13, C0, 3 // fetch TLS base pointer
+ MOVW R11, LR
// $runtime.tlsg(SB) is a special linker symbol.
// It is the offset from the TLS base pointer to our
// thread-local storage for g.