1
0
mirror of https://github.com/golang/go synced 2024-11-26 06:27:58 -07:00

runtime/cgo,cmd/internal/obj/ppc64: fix signals with cgo

Recently some tsan tests were enabled on ppc64le which had not
been enabled before. This resulted in failures on systems with
tsan available, and while debugging it was determined that
there were other issues related to the use of signals with cgo.

Signals were not being forwarded within programs linked against
libtsan because the nocgo sigaction was being called for ppc64le
with or without cgo. Adding callCgoSigaction and calling that
allows signals to be registered so that signal forwarding works.

For linux-ppc64 and aix-ppc64, this won't change. On linux-ppc64
there is no cgo. I can't test aix-ppc64 so those owners can enable
it if they want.

In reviewing comments about sigtramp in sys_linux_arm64 it was
noted that a previous issue in arm64 due to missing callee save
registers could also be a problem on ppc64x, so code was added
to save and restore those.

Also, the use of R31 as a temp register in some cases caused an
issue since it is a nonvolatile register in C and was being clobbered
in cases where the C code expected it to be valid. The code sequences to
load these addresses were changed to avoid the use of R31 when loading
such an address.

To get around a vet error, the stubs_ppc64x.go file in runtime
was split into stubs_ppc64.go and stubs_ppc64le.go.

Updates #45040

Change-Id: Ia4ecff950613cbe1b89471790b1d3819d5b5cfb9
Reviewed-on: https://go-review.googlesource.com/c/go/+/306369
Trust: Lynn Boger <laboger@linux.vnet.ibm.com>
Run-TryBot: Lynn Boger <laboger@linux.vnet.ibm.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Carlos Eduardo Seo <carlos.seo@linaro.org>
This commit is contained in:
Lynn Boger 2021-03-31 12:28:47 -05:00
parent deb3403ff5
commit d9e068d289
10 changed files with 223 additions and 31 deletions

View File

@ -41,8 +41,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
MOVDBR (R3)(R4), R5 // 7ca41c28
MOVWBR (R3)(R4), R5 // 7ca41c2c
MOVHBR (R3)(R4), R5 // 7ca41e2c
MOVD $foo+4009806848(FP), R5 // 3fe1ef0138bfcc20
MOVD $foo(SB), R5 // 3fe0000038bf0000
MOVD $foo+4009806848(FP), R5 // 3ca1ef0138a5cc20
MOVD $foo(SB), R5 // 3ca0000038a50000
MOVDU 8(R3), R4 // e8830009
MOVDU (R3)(R4), R5 // 7ca4186a

View File

@ -2220,7 +2220,7 @@ func (c *ctxt9) opform(insn uint32) int {
// Encode instructions and create relocation for accessing s+d according to the
// instruction op with source or destination (as appropriate) register reg.
func (c *ctxt9) symbolAccess(s *obj.LSym, d int64, reg int16, op uint32) (o1, o2 uint32) {
func (c *ctxt9) symbolAccess(s *obj.LSym, d int64, reg int16, op uint32, reuse bool) (o1, o2 uint32) {
if c.ctxt.Headtype == objabi.Haix {
// Every symbol access must be made via a TOC anchor.
c.ctxt.Diag("symbolAccess called for %s", s.Name)
@ -2232,8 +2232,15 @@ func (c *ctxt9) symbolAccess(s *obj.LSym, d int64, reg int16, op uint32) (o1, o2
} else {
base = REG_R0
}
// If reg can be reused when computing the symbol address,
// use it instead of REGTMP.
if !reuse {
o1 = AOP_IRR(OP_ADDIS, REGTMP, base, 0)
o2 = AOP_IRR(op, uint32(reg), REGTMP, 0)
} else {
o1 = AOP_IRR(OP_ADDIS, uint32(reg), base, 0)
o2 = AOP_IRR(op, uint32(reg), uint32(reg), 0)
}
rel := obj.Addrel(c.cursym)
rel.Off = int32(c.pc)
rel.Siz = 8
@ -2877,14 +2884,14 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
switch p.From.Name {
case obj.NAME_EXTERN, obj.NAME_STATIC:
// Load a 32 bit constant, or relocation depending on if a symbol is attached
o1, o2 = c.symbolAccess(p.From.Sym, v, p.To.Reg, OP_ADDI)
o1, o2 = c.symbolAccess(p.From.Sym, v, p.To.Reg, OP_ADDI, true)
default:
if r == 0 {
r = c.getimpliedreg(&p.From, p)
}
// Add a 32 bit offset to a register.
o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(int32(v))))
o2 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGTMP, uint32(v))
o1 = AOP_IRR(OP_ADDIS, uint32(p.To.Reg), uint32(r), uint32(high16adjusted(int32(v))))
o2 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), uint32(p.To.Reg), uint32(v))
}
case 27: /* subc ra,$simm,rd => subfic rd,ra,$simm */
@ -3043,10 +3050,10 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
if r == 0 {
r = c.getimpliedreg(&p.From, p)
}
o1 = AOP_IRR(OP_ADDIS, REGTMP, uint32(r), uint32(high16adjusted(v)))
o2 = AOP_IRR(c.opload(p.As), uint32(p.To.Reg), REGTMP, uint32(v))
o1 = AOP_IRR(OP_ADDIS, uint32(p.To.Reg), uint32(r), uint32(high16adjusted(v)))
o2 = AOP_IRR(c.opload(p.As), uint32(p.To.Reg), uint32(p.To.Reg), uint32(v))
// Sign extend MOVB operations. This is ignored for other cases (o.size == 8).
// Sign extend MOVB if needed
o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
case 40: /* word */
@ -3404,7 +3411,8 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
if c.opform(inst) == DS_FORM && v&0x3 != 0 {
log.Fatalf("invalid offset for DS form load/store %v", p)
}
o1, o2 = c.symbolAccess(p.To.Sym, v, p.From.Reg, inst)
// Can't reuse base for store instructions.
o1, o2 = c.symbolAccess(p.To.Sym, v, p.From.Reg, inst, false)
case 75: // 32 bit offset symbol loads (got/toc/addr)
v := p.From.Offset
@ -3432,10 +3440,11 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
rel.Type = objabi.R_ADDRPOWER_TOCREL_DS
}
default:
o1, o2 = c.symbolAccess(p.From.Sym, v, p.To.Reg, inst)
reuseBaseReg := p.As != AFMOVD && p.As != AFMOVS
// Reuse To.Reg as base register if not FP move.
o1, o2 = c.symbolAccess(p.From.Sym, v, p.To.Reg, inst, reuseBaseReg)
}
// Sign extend MOVB operations. This is ignored for other cases (o.size == 8).
o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
case 79:

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux,amd64 linux,arm64
// +build linux,amd64 linux,arm64 linux,ppc64le
#include <errno.h>
#include <stdint.h>

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux,amd64 linux,arm64
// +build linux,amd64 linux,arm64 linux,ppc64le
#include <errno.h>
#include <stddef.h>

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (linux && amd64) || (freebsd && amd64) || (linux && arm64)
// +build linux,amd64 freebsd,amd64 linux,arm64
//go:build (linux && amd64) || (freebsd && amd64) || (linux && arm64) || (linux && ppc64le)
// +build linux,amd64 freebsd,amd64 linux,arm64 linux,ppc64le
package cgo
@ -11,8 +11,8 @@ package cgo
import _ "unsafe"
// When using cgo, call the C library for sigaction, so that we call into
// any sanitizer interceptors. This supports using the memory
// sanitizer with Go programs. The memory sanitizer only applies to
// any sanitizer interceptors. This supports using the sanitizers
// with Go programs. The thread and memory sanitizers only apply to
// C/C++ code; this permits that code to see the Go runtime's existing signal
// handlers when registering new signal handlers for the process.

View File

@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Support for memory sanitizer. See runtime/cgo/sigaction.go.
// Support for sanitizers. See runtime/cgo/sigaction.go.
//go:build (linux && amd64) || (freebsd && amd64) || (linux && arm64)
// +build linux,amd64 freebsd,amd64 linux,arm64
//go:build (linux && amd64) || (freebsd && amd64) || (linux && arm64) || (linux && ppc64le)
// +build linux,amd64 freebsd,amd64 linux,arm64 linux,ppc64le
package runtime

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (linux && !amd64 && !arm64) || (freebsd && !amd64)
// +build linux,!amd64,!arm64 freebsd,!amd64
//go:build (linux && !amd64 && !arm64 && !ppc64le) || (freebsd && !amd64)
// +build linux,!amd64,!arm64,!ppc64le freebsd,!amd64
package runtime

View File

@ -0,0 +1,16 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build linux
// +build linux
package runtime
// Called from assembly only; declared for go vet.
func load_g()
func save_g()
func reginit()
//go:noescape
func callCgoSigaction(sig uintptr, new, old *sigactiont) int32

View File

@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build ppc64 || ppc64le
// +build ppc64 ppc64le
package runtime
// Called from assembly only; declared for go vet.

View File

@ -336,6 +336,26 @@ TEXT runtime·rt_sigaction(SB),NOSPLIT|NOFRAME,$0-36
MOVW R3, ret+32(FP)
RET
#ifdef GOARCH_ppc64le
// Call the function stored in _cgo_sigaction using the GCC calling convention.
TEXT runtime·callCgoSigaction(SB),NOSPLIT,$0
MOVD sig+0(FP), R3
MOVD new+8(FP), R4
MOVD old+16(FP), R5
MOVD _cgo_sigaction(SB), R12
MOVD R12, CTR // R12 should contain the function address
MOVD R1, R15 // Save R1
MOVD R2, 24(R1) // Save R2
SUB $48, R1 // reserve 32 (frame) + 16 bytes for sp-8 where fp may be saved.
RLDICR $0, R1, $59, R1 // Align to 16 bytes for C code
BL (CTR)
XOR R0, R0, R0 // Clear R0 as Go expects
MOVD R15, R1 // Restore R1
MOVD 24(R1), R2 // Restore R2
MOVW R3, ret+24(FP) // Return result
RET
#endif
TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
MOVW sig+8(FP), R3
MOVD info+16(FP), R4
@ -351,15 +371,97 @@ TEXT runtime·sigreturn(SB),NOSPLIT,$0-0
#ifdef GOARCH_ppc64le
// ppc64le doesn't need function descriptors
TEXT runtime·sigtramp(SB),NOSPLIT,$64
// Save callee-save registers in the case of signal forwarding.
// Same as on ARM64 https://golang.org/issue/31827 .
TEXT runtime·sigtramp(SB),NOSPLIT|NOFRAME,$0
#else
// function descriptor for the real sigtramp
TEXT runtime·sigtramp(SB),NOSPLIT|NOFRAME,$0
DWORD $sigtramp<>(SB)
DWORD $0
DWORD $0
TEXT sigtramp<>(SB),NOSPLIT,$64
TEXT sigtramp<>(SB),NOSPLIT|NOFRAME,$0
#endif
// Start with standard C stack frame layout and linkage.
MOVD LR, R0
MOVD R0, 16(R1) // Save LR in caller's frame.
MOVW CR, R0 // Save CR in caller's frame
MOVD R0, 8(R1)
// The stack must be acquired here and not
// in the automatic way based on stack size
// since that sequence clobbers R31 before it
// gets saved.
// We are being ultra safe here in saving the
// Vregs. The case where they might need to
// be saved is very unlikely.
MOVDU R1, -544(R1)
MOVD R14, 64(R1)
MOVD R15, 72(R1)
MOVD R16, 80(R1)
MOVD R17, 88(R1)
MOVD R18, 96(R1)
MOVD R19, 104(R1)
MOVD R20, 112(R1)
MOVD R21, 120(R1)
MOVD R22, 128(R1)
MOVD R23, 136(R1)
MOVD R24, 144(R1)
MOVD R25, 152(R1)
MOVD R26, 160(R1)
MOVD R27, 168(R1)
MOVD R28, 176(R1)
MOVD R29, 184(R1)
MOVD g, 192(R1) // R30
MOVD R31, 200(R1)
FMOVD F14, 208(R1)
FMOVD F15, 216(R1)
FMOVD F16, 224(R1)
FMOVD F17, 232(R1)
FMOVD F18, 240(R1)
FMOVD F19, 248(R1)
FMOVD F20, 256(R1)
FMOVD F21, 264(R1)
FMOVD F22, 272(R1)
FMOVD F23, 280(R1)
FMOVD F24, 288(R1)
FMOVD F25, 296(R1)
FMOVD F26, 304(R1)
FMOVD F27, 312(R1)
FMOVD F28, 320(R1)
FMOVD F29, 328(R1)
FMOVD F30, 336(R1)
FMOVD F31, 344(R1)
// Save V regs
// STXVD2X and LXVD2X used since
// we aren't sure of alignment.
// Endianness doesn't matter
// if we are just loading and
// storing values.
MOVD $352, R7 // V20
STXVD2X VS52, (R7)(R1)
ADD $16, R7 // V21 368
STXVD2X VS53, (R7)(R1)
ADD $16, R7 // V22 384
STXVD2X VS54, (R7)(R1)
ADD $16, R7 // V23 400
STXVD2X VS55, (R7)(R1)
ADD $16, R7 // V24 416
STXVD2X VS56, (R7)(R1)
ADD $16, R7 // V25 432
STXVD2X VS57, (R7)(R1)
ADD $16, R7 // V26 448
STXVD2X VS58, (R7)(R1)
ADD $16, R7 // V27 464
STXVD2X VS59, (R7)(R1)
ADD $16, R7 // V28 480
STXVD2X VS60, (R7)(R1)
ADD $16, R7 // V29 496
STXVD2X VS61, (R7)(R1)
ADD $16, R7 // V30 512
STXVD2X VS62, (R7)(R1)
ADD $16, R7 // V31 528
STXVD2X VS63, (R7)(R1)
// initialize essential registers (just in case)
BL runtime·reginit(SB)
@ -376,7 +478,74 @@ TEXT sigtramp<>(SB),NOSPLIT,$64
MOVD $runtime·sigtrampgo(SB), R12
MOVD R12, CTR
BL (CTR)
MOVD 24(R1), R2
MOVD 24(R1), R2 // Should this be here? Where is it saved?
// Starts at 64; FIXED_FRAME is 32
MOVD 64(R1), R14
MOVD 72(R1), R15
MOVD 80(R1), R16
MOVD 88(R1), R17
MOVD 96(R1), R18
MOVD 104(R1), R19
MOVD 112(R1), R20
MOVD 120(R1), R21
MOVD 128(R1), R22
MOVD 136(R1), R23
MOVD 144(R1), R24
MOVD 152(R1), R25
MOVD 160(R1), R26
MOVD 168(R1), R27
MOVD 176(R1), R28
MOVD 184(R1), R29
MOVD 192(R1), g // R30
MOVD 200(R1), R31
FMOVD 208(R1), F14
FMOVD 216(R1), F15
FMOVD 224(R1), F16
FMOVD 232(R1), F17
FMOVD 240(R1), F18
FMOVD 248(R1), F19
FMOVD 256(R1), F20
FMOVD 264(R1), F21
FMOVD 272(R1), F22
FMOVD 280(R1), F23
FMOVD 288(R1), F24
FMOVD 292(R1), F25
FMOVD 300(R1), F26
FMOVD 308(R1), F27
FMOVD 316(R1), F28
FMOVD 328(R1), F29
FMOVD 336(R1), F30
FMOVD 344(R1), F31
MOVD $352, R7
LXVD2X (R7)(R1), VS52
ADD $16, R7 // 368 V21
LXVD2X (R7)(R1), VS53
ADD $16, R7 // 384 V22
LXVD2X (R7)(R1), VS54
ADD $16, R7 // 400 V23
LXVD2X (R7)(R1), VS55
ADD $16, R7 // 416 V24
LXVD2X (R7)(R1), VS56
ADD $16, R7 // 432 V25
LXVD2X (R7)(R1), VS57
ADD $16, R7 // 448 V26
LXVD2X (R7)(R1), VS58
ADD $16, R8 // 464 V27
LXVD2X (R7)(R1), VS59
ADD $16, R7 // 480 V28
LXVD2X (R7)(R1), VS60
ADD $16, R7 // 496 V29
LXVD2X (R7)(R1), VS61
ADD $16, R7 // 512 V30
LXVD2X (R7)(R1), VS62
ADD $16, R7 // 528 V31
LXVD2X (R7)(R1), VS63
ADD $544, R1
MOVD 8(R1), R0
MOVFL R0, $0xff
MOVD 16(R1), R0
MOVD R0, LR
RET
#ifdef GOARCH_ppc64le
@ -406,6 +575,7 @@ TEXT runtime·cgoSigtramp(SB),NOSPLIT|NOFRAME,$0
// Figure out if we are currently in a cgo call.
// If not, just do usual sigtramp.
// compared to ARM64 and others.
CMP $0, g
BEQ sigtrampnog // g == nil
MOVD g_m(g), R6