summaryrefslogtreecommitdiff
path: root/src/thread/aarch64
diff options
context:
space:
mode:
Diffstat (limited to 'src/thread/aarch64')
-rw-r--r--src/thread/aarch64/__set_thread_area.c27
-rw-r--r--src/thread/aarch64/__set_thread_area.s7
-rw-r--r--src/thread/aarch64/clone.s3
3 files changed, 29 insertions, 8 deletions
diff --git a/src/thread/aarch64/__set_thread_area.c b/src/thread/aarch64/__set_thread_area.c
new file mode 100644
index 00000000..2ec788e8
--- /dev/null
+++ b/src/thread/aarch64/__set_thread_area.c
@@ -0,0 +1,27 @@
+#include <elf.h>
+#include "libc.h"
+
+#define BITRANGE(a,b) (2*(1UL<<(b))-(1UL<<(a)))
+
+int __set_thread_area(void *p)
+{
+ __asm__ __volatile__ ("msr tpidr_el0,%0" : : "r"(p) : "memory");
+
+ /* Mask off hwcap bits for SME and unknown future features. This is
+ * necessary because SME is not safe to use without libc support for
+ * it, and we do not (yet) have such support. */
+ for (size_t *v = libc.auxv; *v; v+=2) {
+ if (v[0]==AT_HWCAP) {
+ v[1] &= ~BITRANGE(42,63); /* 42-47 are SME */
+ } else if (v[0]==AT_HWCAP2) {
+ v[1] &= ~(BITRANGE(23,30)
+ | BITRANGE(37,42)
+ | BITRANGE(57,62));
+ } else if (v[0]==AT_HWCAP3 || v[0]==AT_HWCAP4) {
+ v[0] = AT_IGNORE;
+ v[1] = 0;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/thread/aarch64/__set_thread_area.s b/src/thread/aarch64/__set_thread_area.s
deleted file mode 100644
index fd0df34b..00000000
--- a/src/thread/aarch64/__set_thread_area.s
+++ /dev/null
@@ -1,7 +0,0 @@
-.global __set_thread_area
-.hidden __set_thread_area
-.type __set_thread_area,@function
-__set_thread_area:
- msr tpidr_el0,x0
- mov w0,#0
- ret
diff --git a/src/thread/aarch64/clone.s b/src/thread/aarch64/clone.s
index e3c83395..aff8155b 100644
--- a/src/thread/aarch64/clone.s
+++ b/src/thread/aarch64/clone.s
@@ -24,7 +24,8 @@ __clone:
// parent
ret
// child
-1: ldp x1,x0,[sp],#16
+1: mov x29, 0
+ ldp x1,x0,[sp],#16
blr x1
mov x8,#93 // SYS_exit
svc #0