Force GCC to find new location of TLS base

GCC will sometimes optimise accesses to TLS across function calls
assuming that the TLS base address has not been changed and thus none of
the TLS variables have been relocated.

Given initialising musl libc explicitly creates a new TLS region,
updating __sel4_ipc_buffer requires us to force GCC to find its address
in the new TLS region rather than re-using the address it already
determined.

Signed-off-by: Curtis Millar <curtis.millar@data61.csiro.au>
diff --git a/libsel4muslcsys/src/vsyscall.c b/libsel4muslcsys/src/vsyscall.c
index bad8ace..d48d58b 100644
--- a/libsel4muslcsys/src/vsyscall.c
+++ b/libsel4muslcsys/src/vsyscall.c
@@ -299,10 +299,23 @@
  * environment. */
 extern void __init_libc(char const *const *envp, char const *pn);
 
+/* This is needed to force GCC to re-read the TLS base address on some
+ * platforms when setting the IPC buffer address after it has changed.
+ *
+ * At higher optimisation levels on aarch64, GCC will read the location
+ * for `__sel4_ipc_buffer` only once in the same function, even across
+ * function calls, and thus will not update any newly created TLS region
+ * with the IPC buffer address.
+ */
+static void NO_INLINE update_ipc_buffer(seL4_IPCBuffer *tmp)
+{
+    __sel4_ipc_buffer = tmp;
+}
+
 /* Initialise muslc environment */
 void CONSTRUCTOR(CONFIG_LIB_SEL4_MUSLC_SYS_CONSTRUCTOR_PRIORITY) muslcsys_init_muslc(void)
 {
     seL4_IPCBuffer *tmp = __sel4_ipc_buffer;
     __init_libc(sel4runtime_envp(), sel4runtime_argv()[0]);
-    __sel4_ipc_buffer = tmp;
+    update_ipc_buffer(tmp);
 }