Skip to content

runtime: fix crash during VDSO calls on PowerPC #46767

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/runtime/signal_unix.go
Original file line number Diff line number Diff line change
@@ -382,7 +382,7 @@ func preemptM(mp *m) {
//go:nosplit
func sigFetchG(c *sigctxt) *g {
switch GOARCH {
case "arm", "arm64":
case "arm", "arm64", "ppc64", "ppc64le":
if !iscgo && inVDSOPage(c.sigpc()) {
// When using cgo, we save the g on TLS and load it from there
// in sigtramp. Just use that.
86 changes: 73 additions & 13 deletions src/runtime/sys_linux_ppc64x.s
Original file line number Diff line number Diff line change
@@ -216,15 +216,45 @@ TEXT runtime·walltime(SB),NOSPLIT,$16-12
MOVD (g_sched+gobuf_sp)(R7), R1 // Set SP to g0 stack

noswitch:
SUB $16, R1 // Space for results
RLDICR $0, R1, $59, R1 // Align for C code
SUB $16, R1 // Space for results
RLDICR $0, R1, $59, R1 // Align for C code
MOVD R12, CTR
MOVD R1, R4
BL (CTR) // Call from VDSO
MOVD $0, R0 // Restore R0
MOVD 0(R1), R3 // sec
MOVD 8(R1), R5 // nsec
MOVD R15, R1 // Restore SP

// Store g on gsignal's stack, so if we receive a signal
// during VDSO code we can find the g.
// If we don't have a signal stack, we won't receive signal,
// so don't bother saving g.
// When using cgo, we already saved g on TLS, also don't save
// g here.
// Also don't save g if we are already on the signal stack.
// We won't get a nested signal.
MOVBZ runtime·iscgo(SB), R22
CMP R22, $0
BNE nosaveg
MOVD m_gsignal(R21), R22 // g.m.gsignal
CMP R22, $0
BEQ nosaveg

CMP g, R22
BEQ nosaveg
MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
MOVD g, (R22)

BL (CTR) // Call from VDSO

MOVD $0, (R22) // clear g slot, R22 is unchanged by C code

JMP finish

nosaveg:
BL (CTR) // Call from VDSO

finish:
MOVD $0, R0 // Restore R0
MOVD 0(R1), R3 // sec
MOVD 8(R1), R5 // nsec
MOVD R15, R1 // Restore SP

// Restore vdsoPC, vdsoSP
// We don't worry about being signaled between the two stores.
@@ -236,7 +266,7 @@ noswitch:
MOVD 32(R1), R6
MOVD R6, m_vdsoPC(R21)

finish:
return:
MOVD R3, sec+0(FP)
MOVW R5, nsec+8(FP)
RET
@@ -247,7 +277,7 @@ fallback:
SYSCALL $SYS_clock_gettime
MOVD 32(R1), R3
MOVD 40(R1), R5
JMP finish
JMP return

TEXT runtime·nanotime1(SB),NOSPLIT,$16-8
MOVD $1, R3 // CLOCK_MONOTONIC
@@ -283,7 +313,37 @@ noswitch:
RLDICR $0, R1, $59, R1 // Align for C code
MOVD R12, CTR
MOVD R1, R4
BL (CTR) // Call from VDSO

// Store g on gsignal's stack, so if we receive a signal
// during VDSO code we can find the g.
// If we don't have a signal stack, we won't receive signal,
// so don't bother saving g.
// When using cgo, we already saved g on TLS, also don't save
// g here.
// Also don't save g if we are already on the signal stack.
// We won't get a nested signal.
MOVBZ runtime·iscgo(SB), R22
CMP R22, $0
BNE nosaveg
MOVD m_gsignal(R21), R22 // g.m.gsignal
CMP R22, $0
BEQ nosaveg

CMP g, R22
BEQ nosaveg
MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
MOVD g, (R22)

BL (CTR) // Call from VDSO

MOVD $0, (R22) // clear g slot, R22 is unchanged by C code

JMP finish

nosaveg:
BL (CTR) // Call from VDSO

finish:
MOVD $0, R0 // Restore R0
MOVD 0(R1), R3 // sec
MOVD 8(R1), R5 // nsec
@@ -299,7 +359,7 @@ noswitch:
MOVD 32(R1), R6
MOVD R6, m_vdsoPC(R21)

finish:
return:
// sec is in R3, nsec in R5
// return nsec in R3
MOVD $1000000000, R4
@@ -314,7 +374,7 @@ fallback:
SYSCALL $SYS_clock_gettime
MOVD 32(R1), R3
MOVD 40(R1), R5
JMP finish
JMP return

TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28
MOVW how+0(FP), R3
@@ -469,7 +529,7 @@ TEXT sigtramp<>(SB),NOSPLIT|NOFRAME,$0
// this might be called in external code context,
// where g is not set.
MOVBZ runtime·iscgo(SB), R6
CMP R6, $0
CMP R6, $0
BEQ 2(PC)
BL runtime·load_g(SB)