aboutsummaryrefslogtreecommitdiff
path: root/std/os/linux
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-09-04 14:39:36 -0400
committerGitHub <noreply@github.com>2019-09-04 14:39:36 -0400
commit090f2ffb820ab10773322636d3c940bbfd6028be (patch)
tree7a36bef3a48854cb08cb9bbc6a727212f0ff7858 /std/os/linux
parente540e5b8ec1d90b86d6f41814507e6ae4ae5edd8 (diff)
parentdf06976e73e37a36009fb5f43c2310ad610a4a2e (diff)
downloadzig-090f2ffb820ab10773322636d3c940bbfd6028be.tar.gz
zig-090f2ffb820ab10773322636d3c940bbfd6028be.zip
Merge pull request #3152 from Snektron/arm-support-improvement
Arm support improvement (part 1)
Diffstat (limited to 'std/os/linux')
-rw-r--r--std/os/linux/arm-eabi.zig96
-rw-r--r--std/os/linux/arm64.zig7
-rw-r--r--std/os/linux/tls.zig13
3 files changed, 116 insertions, 0 deletions
diff --git a/std/os/linux/arm-eabi.zig b/std/os/linux/arm-eabi.zig
new file mode 100644
index 0000000000..c8a5bbe378
--- /dev/null
+++ b/std/os/linux/arm-eabi.zig
@@ -0,0 +1,96 @@
+pub fn syscall0(number: usize) usize {
+ return asm volatile ("svc #0"
+ : [ret] "={r0}" (-> usize)
+ : [number] "{r7}" (number)
+ : "memory"
+ );
+}
+
+pub fn syscall1(number: usize, arg1: usize) usize {
+ return asm volatile ("svc #0"
+ : [ret] "={r0}" (-> usize)
+ : [number] "{r7}" (number),
+ [arg1] "{r0}" (arg1)
+ : "memory"
+ );
+}
+
+pub fn syscall2(number: usize, arg1: usize, arg2: usize) usize {
+ return asm volatile ("svc #0"
+ : [ret] "={r0}" (-> usize)
+ : [number] "{r7}" (number),
+ [arg1] "{r0}" (arg1),
+ [arg2] "{r1}" (arg2)
+ : "memory"
+ );
+}
+
+pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize {
+ return asm volatile ("svc #0"
+ : [ret] "={r0}" (-> usize)
+ : [number] "{r7}" (number),
+ [arg1] "{r0}" (arg1),
+ [arg2] "{r1}" (arg2),
+ [arg3] "{r2}" (arg3)
+ : "memory"
+ );
+}
+
+pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
+ return asm volatile ("svc #0"
+ : [ret] "={r0}" (-> usize)
+ : [number] "{r7}" (number),
+ [arg1] "{r0}" (arg1),
+ [arg2] "{r1}" (arg2),
+ [arg3] "{r2}" (arg3),
+ [arg4] "{r3}" (arg4)
+ : "memory"
+ );
+}
+
+pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
+ return asm volatile ("svc #0"
+ : [ret] "={r0}" (-> usize)
+ : [number] "{r7}" (number),
+ [arg1] "{r0}" (arg1),
+ [arg2] "{r1}" (arg2),
+ [arg3] "{r2}" (arg3),
+ [arg4] "{r3}" (arg4),
+ [arg5] "{r4}" (arg5)
+ : "memory"
+ );
+}
+
+pub fn syscall6(
+ number: usize,
+ arg1: usize,
+ arg2: usize,
+ arg3: usize,
+ arg4: usize,
+ arg5: usize,
+ arg6: usize,
+) usize {
+ return asm volatile ("svc #0"
+ : [ret] "={r0}" (-> usize)
+ : [number] "{r7}" (number),
+ [arg1] "{r0}" (arg1),
+ [arg2] "{r1}" (arg2),
+ [arg3] "{r2}" (arg3),
+ [arg4] "{r3}" (arg4),
+ [arg5] "{r4}" (arg5),
+ [arg6] "{r5}" (arg6)
+ : "memory"
+ );
+}
+
+/// This matches the libc clone function.
+pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
+
+// LLVM calls this when the read-tp-hard feature is set to false. Currently, there is no way to pass
+// that to llvm via zig, see https://github.com/ziglang/zig/issues/2883.
+// LLVM expects libc to provide this function as __aeabi_read_tp, so it is exported if needed from special/c.zig.
+pub extern fn getThreadPointer() usize {
+ return asm volatile("mrc p15, 0, %[ret], c13, c0, 3"
+ : [ret] "=r" (-> usize)
+ );
+} \ No newline at end of file
diff --git a/std/os/linux/arm64.zig b/std/os/linux/arm64.zig
index 94cf8818de..28da9af1c6 100644
--- a/std/os/linux/arm64.zig
+++ b/std/os/linux/arm64.zig
@@ -2,6 +2,7 @@ pub fn syscall0(number: usize) usize {
return asm volatile ("svc #0"
: [ret] "={x0}" (-> usize)
: [number] "{x8}" (number)
+ : "memory", "cc"
);
}
@@ -10,6 +11,7 @@ pub fn syscall1(number: usize, arg1: usize) usize {
: [ret] "={x0}" (-> usize)
: [number] "{x8}" (number),
[arg1] "{x0}" (arg1)
+ : "memory", "cc"
);
}
@@ -19,6 +21,7 @@ pub fn syscall2(number: usize, arg1: usize, arg2: usize) usize {
: [number] "{x8}" (number),
[arg1] "{x0}" (arg1),
[arg2] "{x1}" (arg2)
+ : "memory", "cc"
);
}
@@ -29,6 +32,7 @@ pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize {
[arg1] "{x0}" (arg1),
[arg2] "{x1}" (arg2),
[arg3] "{x2}" (arg3)
+ : "memory", "cc"
);
}
@@ -40,6 +44,7 @@ pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usiz
[arg2] "{x1}" (arg2),
[arg3] "{x2}" (arg3),
[arg4] "{x3}" (arg4)
+ : "memory", "cc"
);
}
@@ -52,6 +57,7 @@ pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usiz
[arg3] "{x2}" (arg3),
[arg4] "{x3}" (arg4),
[arg5] "{x4}" (arg5)
+ : "memory", "cc"
);
}
@@ -73,6 +79,7 @@ pub fn syscall6(
[arg4] "{x3}" (arg4),
[arg5] "{x4}" (arg5),
[arg6] "{x5}" (arg6)
+ : "memory", "cc"
);
}
diff --git a/std/os/linux/tls.zig b/std/os/linux/tls.zig
index a10d68663b..3c55013f47 100644
--- a/std/os/linux/tls.zig
+++ b/std/os/linux/tls.zig
@@ -118,6 +118,9 @@ pub fn setThreadPointer(addr: usize) void {
: [addr] "r" (addr)
);
},
+ .arm => |arm| {
+ _ = std.os.linux.syscall1(std.os.linux.SYS_set_tls, addr);
+ },
else => @compileError("Unsupported architecture"),
}
}
@@ -130,6 +133,7 @@ pub fn initTLS() void {
var at_phent: usize = undefined;
var at_phnum: usize = undefined;
var at_phdr: usize = undefined;
+ var at_hwcap: usize = undefined;
var i: usize = 0;
while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) {
@@ -137,6 +141,7 @@ pub fn initTLS() void {
elf.AT_PHENT => at_phent = auxv[i].a_un.a_val,
elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val,
elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val,
+ elf.AT_HWCAP => at_phdr = auxv[i].a_un.a_val,
else => continue,
}
}
@@ -156,6 +161,14 @@ pub fn initTLS() void {
}
if (tls_phdr) |phdr| {
+ // If the cpu is arm-based, check if it supports the TLS register
+ if (builtin.arch == builtin.Arch.arm and hwcap & std.os.linux.HWCAP_TLS == 0) {
+ // If the CPU does not support TLS via a coprocessor register,
+ // a kernel helper function can be used instead on certain linux kernels.
+ // See linux/arch/arm/include/asm/tls.h and musl/src/thread/arm/__set_thread_area.c.
+ @panic("TODO: Implement ARM fallback TLS functionality");
+ }
+
// Offsets into the allocated TLS area
var tcb_offset: usize = undefined;
var dtv_offset: usize = undefined;