Skip to content

Commit 6de2d61

Browse files
committed
std.debug: work around latest SPARC register window not being spilled on signal
I have no idea if this is a QEMU bug or real kernel behavior. Either way, the register save area specifically exists for asynchronous spilling of incoming and local registers, so there should be no harm in doing this.
1 parent 78bc5d4 commit 6de2d61

1 file changed

Lines changed: 16 additions & 0 deletions

File tree

lib/std/debug.zig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,6 +1438,22 @@ fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopa
14381438
break :info .{ addr, name };
14391439
};
14401440
const opt_cpu_context: ?cpu_context.Native = cpu_context.fromPosixSignalContext(ctx_ptr);
1441+
1442+
if (native_arch.isSPARC()) {
1443+
// It's unclear to me whether this is a QEMU bug or also real kernel behavior, but in the
1444+
// former, I observed that the most recent register window wasn't getting spilled on the
1445+
// stack as expected when a signal arrived. A `flushw` from the signal handler does not
1446+
// appear to be sufficient either. On the other hand, when doing a synchronous stack trace
1447+
// and using `flushw`, this all appears to work as expected. So, *probably* a QEMU bug, but
1448+
// someone with real SPARC hardware should verify.
1449+
//
1450+
// In any case, the register save area exists specifically so that register windows can be
1451+
// spilled asynchronously. This means that it should be perfectly fine for us to manually do
1452+
// so here.
1453+
const ctx = opt_cpu_context.?;
1454+
@as(*[16]usize, @ptrFromInt(ctx.o[6] + StackIterator.stack_bias)).* = ctx.l ++ ctx.i;
1455+
}
1456+
14411457
handleSegfault(addr, name, if (opt_cpu_context) |*ctx| ctx else null);
14421458
}
14431459

0 commit comments

Comments
 (0)