| ... | @@ -1146,6 +1146,13 @@ const LinuxThreadImpl = struct { | ... | @@ -1146,6 +1146,13 @@ const LinuxThreadImpl = struct { |
| 1146 | parent_tid: i32 = undefined, | 1146 | parent_tid: i32 = undefined, |
| 1147 | mapped: []align(std.heap.page_size_min) u8, | 1147 | mapped: []align(std.heap.page_size_min) u8, |
| 1148 | | 1148 | |
| | 1149 | // On SPARC, the kernel needs to be able to restore the current register window from the |
| | 1150 | // stack when returning from a syscall. That presents a bit of a problem in `freeAndExit` |
| | 1151 | // since we're deallocating the stack! The good news is that, since we do not care about |
| | 1152 | // the contents of the incoming and local registers at that point, we can just tell the |
| | 1153 | // kernel that our stack is this undefined global buffer. |
| | 1154 | var sparc_exit_stack: [192]u8 align(16) = undefined; |
| | 1155 | |
| 1149 | /// Calls `munmap(mapped.ptr, mapped.len)` then `exit(1)` without touching the stack (which lives in `mapped.ptr`). | 1156 | /// Calls `munmap(mapped.ptr, mapped.len)` then `exit(1)` without touching the stack (which lives in `mapped.ptr`). |
| 1150 | /// Ported over from musl libc's pthread detached implementation: | 1157 | /// Ported over from musl libc's pthread detached implementation: |
| 1151 | /// https://github.com/ifduyue/musl/search?q=__unmapself | 1158 | /// https://github.com/ifduyue/musl/search?q=__unmapself |
| ... | @@ -1365,51 +1372,39 @@ const LinuxThreadImpl = struct { | ... | @@ -1365,51 +1372,39 @@ const LinuxThreadImpl = struct { |
| 1365 | [len] "{r5}" (self.mapped.len), | 1372 | [len] "{r5}" (self.mapped.len), |
| 1366 | ), | 1373 | ), |
| 1367 | .sparc => asm volatile ( | 1374 | .sparc => asm volatile ( |
| 1368 | \\ # See sparc64 comments below. | 1375 | \\ // See sparc64 comments below. |
| 1369 | \\ 1: | 1376 | \\ t 0x3 // ST_FLUSH_WINDOWS |
| 1370 | \\ cmp %%fp, 0 | 1377 | \\ mov %%g3, %%sp |
| 1371 | \\ beq 2f | 1378 | \\ mov %%g1, %%o0 |
| 1372 | \\ nop | 1379 | \\ mov %%g2, %%o1 |
| 1373 | \\ ba 1b | 1380 | \\ mov 73, %%g1 // SYS_munmap |
| 1374 | \\ restore | 1381 | \\ t 0x10 |
| 1375 | \\ 2: | 1382 | \\ mov 1, %%g1 // SYS_exit |
| 1376 | \\ mov %%g1, %%o0 // ptr | 1383 | \\ mov 0, %%o0 |
| 1377 | \\ mov %%g2, %%o1 // len | 1384 | \\ t 0x10 |
| 1378 | \\ mov 73, %%g1 // SYS_munmap | | |
| 1379 | \\ t 0x3 // ST_FLUSH_WINDOWS | | |
| 1380 | \\ t 0x10 | | |
| 1381 | \\ mov 1, %%g1 // SYS_exit | | |
| 1382 | \\ mov 0, %%o0 | | |
| 1383 | \\ t 0x10 | | |
| 1384 | : | 1385 | : |
| 1385 | : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)), | 1386 | : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)), |
| 1386 | [len] "{g2}" (self.mapped.len), | 1387 | [len] "{g2}" (self.mapped.len), |
| | 1388 | [stack] "{g3}" (&sparc_exit_stack), |
| 1387 | : .{ .memory = true }), | 1389 | : .{ .memory = true }), |
| 1388 | .sparc64 => asm volatile ( | 1390 | .sparc64 => asm volatile ( |
| 1389 | \\ # SPARCs really don't like it when active stack frames | 1391 | \\ // Ensure that the kernel only has to flush the current register window. |
| 1390 | \\ # is unmapped (it will result in a segfault), so we | 1392 | \\ flushw |
| 1391 | \\ # force-deactivate it by running `restore` until | 1393 | \\ // Set up a fake stack for the syscall to restore l/i registers from. Local |
| 1392 | \\ # all frames are cleared. | 1394 | \\ // and incoming registers must be treated as effectively garbage past this |
| 1393 | \\ 1: | 1395 | \\ // instruction! |
| 1394 | \\ cmp %%fp, 0 | 1396 | \\ sub %%g3, 2047, %%sp |
| 1395 | \\ beq 2f | 1397 | \\ mov %%g1, %%o0 |
| 1396 | \\ nop | 1398 | \\ mov %%g2, %%o1 |
| 1397 | \\ ba 1b | 1399 | \\ mov 73, %%g1 // SYS_munmap |
| 1398 | \\ restore | 1400 | \\ t 0x6d |
| 1399 | \\ 2: | 1401 | \\ mov 1, %%g1 // SYS_exit |
| 1400 | \\ mov %%g1, %%o0 // ptr | 1402 | \\ mov 0, %%o0 |
| 1401 | \\ mov %%g2, %%o1 // len | 1403 | \\ t 0x6d |
| 1402 | \\ mov 73, %%g1 // SYS_munmap | | |
| 1403 | \\ # Flush register window contents to prevent background | | |
| 1404 | \\ # memory access before unmapping the stack. | | |
| 1405 | \\ flushw | | |
| 1406 | \\ t 0x6d | | |
| 1407 | \\ mov 1, %%g1 // SYS_exit | | |
| 1408 | \\ mov 0, %%o0 | | |
| 1409 | \\ t 0x6d | | |
| 1410 | : | 1404 | : |
| 1411 | : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)), | 1405 | : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)), |
| 1412 | [len] "{g2}" (self.mapped.len), | 1406 | [len] "{g2}" (self.mapped.len), |
| | 1407 | [stack] "{g3}" (&sparc_exit_stack), |
| 1413 | : .{ .memory = true }), | 1408 | : .{ .memory = true }), |
| 1414 | .loongarch32, .loongarch64 => asm volatile ( | 1409 | .loongarch32, .loongarch64 => asm volatile ( |
| 1415 | \\ ori $a7, $zero, 215 # SYS_munmap | 1410 | \\ ori $a7, $zero, 215 # SYS_munmap |