| ... | @@ -47,7 +47,7 @@ const TLSVariant = enum { | ... | @@ -47,7 +47,7 @@ const TLSVariant = enum { |
| 47 | }; | 47 | }; |
| 48 | | 48 | |
| 49 | const tls_variant = switch (builtin.arch) { | 49 | const 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 to | 57 | // ARM EABI mandates enough space for two pointers: the first one points to |
| 58 | // the DTV while the second one is unspecified but reserved | 58 | // 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 | }; |
| 63 | | 62 | |
| 64 | // Controls if the TCB should be aligned according to the TLS segment p_align | 63 | // 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 | }; |
| 69 | | 68 | |
| | 69 | // Controls if the TP points to the end of the TCB instead of its beginning |
| | 70 | const 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 correct | 75 | // Check if the architecture-specific parameters look correct |
| 71 | comptime { | 76 | comptime { |
| 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 efficient | 83 | // make the generated code more efficient |
| 79 | | 84 | |
| 80 | const tls_tp_offset = switch (builtin.arch) { | 85 | const tls_tp_offset = switch (builtin.arch) { |
| | 86 | .mipsel => 0x7000, |
| 81 | else => 0, | 87 | else => 0, |
| 82 | }; | 88 | }; |
| 83 | | 89 | |
| 84 | const tls_dtv_offset = switch (builtin.arch) { | 90 | const tls_dtv_offset = switch (builtin.arch) { |
| | 91 | .mipsel => 0x8000, |
| 85 | else => 0, | 92 | else => 0, |
| 86 | }; | 93 | }; |
| 87 | | 94 | |
| ... | @@ -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); |
| 252 | | 260 | |
| 253 | // Return the corrected (if needed) value for the tp register | 261 | // 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 | } |
| 256 | | 265 | |
| 257 | var main_thread_tls_buffer: [256]u8 align(32) = undefined; | 266 | var main_thread_tls_buffer: [256]u8 align(32) = undefined; |