Skip to content

Commit a11c20e

Browse files
LemonBoyandrewrk
authored andcommittedSep 21, 2019
Fix TLS for VariantI arches with a twist
1 parent 4dd17a7 commit a11c20e

File tree

1 file changed

+14
-5
lines changed

1 file changed

+14
-5
lines changed
 

‎std/os/linux/tls.zig

+14-5
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const TLSVariant = enum {
4747
};
4848

4949
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,
5151
.x86_64, .i386 => TLSVariant.VariantII,
5252
else => @compileError("undefined tls_variant for this architecture"),
5353
};
@@ -57,8 +57,7 @@ const tls_tcb_size = switch (builtin.arch) {
5757
// ARM EABI mandates enough space for two pointers: the first one points to
5858
// the DTV while the second one is unspecified but reserved
5959
.arm, .armeb, .aarch64, .aarch64_be => 2 * @sizeOf(usize),
60-
.i386, .x86_64 => @sizeOf(usize),
61-
else => 0,
60+
else => @sizeOf(usize),
6261
};
6362

6463
// 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) {
6766
else => false,
6867
};
6968

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+
7075
// Check if the architecture-specific parameters look correct
7176
comptime {
7277
if (tls_tcb_align_size and tls_variant != TLSVariant.VariantI) {
@@ -78,10 +83,12 @@ comptime {
7883
// make the generated code more efficient
7984

8085
const tls_tp_offset = switch (builtin.arch) {
86+
.mipsel => 0x7000,
8187
else => 0,
8288
};
8389

8490
const tls_dtv_offset = switch (builtin.arch) {
91+
.mipsel => 0x8000,
8592
else => 0,
8693
};
8794

@@ -119,7 +126,8 @@ pub fn setThreadPointer(addr: usize) void {
119126
);
120127
},
121128
.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);
123131
},
124132
.riscv64 => {
125133
asm volatile (
@@ -251,7 +259,8 @@ pub fn copyTLS(addr: usize) usize {
251259
@memcpy(@intToPtr([*]u8, addr + tls_img.data_offset), tls_img.data_src.ptr, tls_img.data_src.len);
252260

253261
// 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;
255264
}
256265

257266
var main_thread_tls_buffer: [256]u8 align(32) = undefined;

0 commit comments

Comments
 (0)
Please sign in to comment.