authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-09-21 23:10:45+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-21 19:53:39-04:00
loga11c20e26a6efd977656459710ae3d37fcbb2846
tree9d21b66b14be4cd8349f95bece5e4b8c8ac8aef6
parent4dd17a7c9e3e5220a088087b3729354d6b85b279

Fix TLS for VariantI arches with a twist


1 files changed, 14 insertions(+), 5 deletions(-)

std/os/linux/tls.zig+14-5
...@@ -47,7 +47,7 @@ const TLSVariant = enum {...@@ -47,7 +47,7 @@ const TLSVariant = enum {
47};47};
4848
49const tls_variant = switch (builtin.arch) {49const tls_variant = switch (builtin.arch) {
50 .arm, .armeb, .aarch64, .aarch64_be, .riscv32, .riscv64 => TLSVariant.VariantI,50 .arm, .armeb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mipsel => TLSVariant.VariantI,
51 .x86_64, .i386 => TLSVariant.VariantII,51 .x86_64, .i386 => TLSVariant.VariantII,
52 else => @compileError("undefined tls_variant for this architecture"),52 else => @compileError("undefined tls_variant for this architecture"),
53};53};
...@@ -57,8 +57,7 @@ const tls_tcb_size = switch (builtin.arch) {...@@ -57,8 +57,7 @@ const tls_tcb_size = switch (builtin.arch) {
57 // ARM EABI mandates enough space for two pointers: the first one points to57 // ARM EABI mandates enough space for two pointers: the first one points to
58 // the DTV while the second one is unspecified but reserved58 // the DTV while the second one is unspecified but reserved
59 .arm, .armeb, .aarch64, .aarch64_be => 2 * @sizeOf(usize),59 .arm, .armeb, .aarch64, .aarch64_be => 2 * @sizeOf(usize),
60 .i386, .x86_64 => @sizeOf(usize),60 else => @sizeOf(usize),
61 else => 0,
62};61};
6362
64// Controls if the TCB should be aligned according to the TLS segment p_align63// Controls if the TCB should be aligned according to the TLS segment p_align
...@@ -67,6 +66,12 @@ const tls_tcb_align_size = switch (builtin.arch) {...@@ -67,6 +66,12 @@ const tls_tcb_align_size = switch (builtin.arch) {
67 else => false,66 else => false,
68};67};
6968
69// Controls if the TP points to the end of the TCB instead of its beginning
70const tls_tp_points_past_tcb = switch (builtin.arch) {
71 .riscv32, .riscv64, .mipsel, .powerpc64, .powerpc64le => true,
72 else => false,
73};
74
70// Check if the architecture-specific parameters look correct75// Check if the architecture-specific parameters look correct
71comptime {76comptime {
72 if (tls_tcb_align_size and tls_variant != TLSVariant.VariantI) {77 if (tls_tcb_align_size and tls_variant != TLSVariant.VariantI) {
...@@ -78,10 +83,12 @@ comptime {...@@ -78,10 +83,12 @@ comptime {
78// make the generated code more efficient83// make the generated code more efficient
7984
80const tls_tp_offset = switch (builtin.arch) {85const tls_tp_offset = switch (builtin.arch) {
86 .mipsel => 0x7000,
81 else => 0,87 else => 0,
82};88};
8389
84const tls_dtv_offset = switch (builtin.arch) {90const tls_dtv_offset = switch (builtin.arch) {
91 .mipsel => 0x8000,
85 else => 0,92 else => 0,
86};93};
8794
...@@ -119,7 +126,8 @@ pub fn setThreadPointer(addr: usize) void {...@@ -119,7 +126,8 @@ pub fn setThreadPointer(addr: usize) void {
119 );126 );
120 },127 },
121 .arm => |arm| {128 .arm => |arm| {
122 _ = std.os.linux.syscall1(std.os.linux.SYS_set_tls, addr);129 const rc = std.os.linux.syscall1(std.os.linux.SYS_set_tls, addr);
130 assert(rc == 0);
123 },131 },
124 .riscv64 => {132 .riscv64 => {
125 asm volatile (133 asm volatile (
...@@ -251,7 +259,8 @@ pub fn copyTLS(addr: usize) usize {...@@ -251,7 +259,8 @@ pub fn copyTLS(addr: usize) usize {
251 @memcpy(@intToPtr([*]u8, addr + tls_img.data_offset), tls_img.data_src.ptr, tls_img.data_src.len);259 @memcpy(@intToPtr([*]u8, addr + tls_img.data_offset), tls_img.data_src.ptr, tls_img.data_src.len);
252260
253 // Return the corrected (if needed) value for the tp register261 // Return the corrected (if needed) value for the tp register
254 return addr + tls_img.tcb_offset + tls_tp_offset;262 return addr + tls_tp_offset +
263 if (tls_tp_points_past_tcb) tls_img.data_offset else tls_img.tcb_offset;
255}264}
256265
257var main_thread_tls_buffer: [256]u8 align(32) = undefined;266var main_thread_tls_buffer: [256]u8 align(32) = undefined;