| ... | ... | @@ -47,7 +47,7 @@ const TLSVariant = enum { |
| 47 | 47 | }; |
| 48 | 48 | |
| 49 | 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 | 51 | .x86_64, .i386 => TLSVariant.VariantII, |
| 52 | 52 | else => @compileError("undefined tls_variant for this architecture"), |
| 53 | 53 | }; |
| ... | ... | @@ -57,8 +57,7 @@ const tls_tcb_size = switch (builtin.arch) { |
| 57 | 57 | // ARM EABI mandates enough space for two pointers: the first one points to |
| 58 | 58 | // the DTV while the second one is unspecified but reserved |
| 59 | 59 | .arm, .armeb, .aarch64, .aarch64_be => 2 * @sizeOf(usize), |
| 60 | | .i386, .x86_64 => @sizeOf(usize), |
| 61 | | else => 0, |
| 60 | else => @sizeOf(usize), |
| 62 | 61 | }; |
| 63 | 62 | |
| 64 | 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 | 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 | 75 | // Check if the architecture-specific parameters look correct |
| 71 | 76 | comptime { |
| 72 | 77 | if (tls_tcb_align_size and tls_variant != TLSVariant.VariantI) { |
| ... | ... | @@ -78,10 +83,12 @@ comptime { |
| 78 | 83 | // make the generated code more efficient |
| 79 | 84 | |
| 80 | 85 | const tls_tp_offset = switch (builtin.arch) { |
| 86 | .mipsel => 0x7000, |
| 81 | 87 | else => 0, |
| 82 | 88 | }; |
| 83 | 89 | |
| 84 | 90 | const tls_dtv_offset = switch (builtin.arch) { |
| 91 | .mipsel => 0x8000, |
| 85 | 92 | else => 0, |
| 86 | 93 | }; |
| 87 | 94 | |
| ... | ... | @@ -119,7 +126,8 @@ pub fn setThreadPointer(addr: usize) void { |
| 119 | 126 | ); |
| 120 | 127 | }, |
| 121 | 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 | 132 | .riscv64 => { |
| 125 | 133 | asm volatile ( |
| ... | ... | @@ -251,7 +259,8 @@ pub fn copyTLS(addr: usize) usize { |
| 251 | 259 | @memcpy(@intToPtr([*]u8, addr + tls_img.data_offset), tls_img.data_src.ptr, tls_img.data_src.len); |
| 252 | 260 | |
| 253 | 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 | 266 | var main_thread_tls_buffer: [256]u8 align(32) = undefined; |