Commit a4855812 authored by Michael Hudson-Doyle's avatar Michael Hudson-Doyle

runtime: add a constant for the smallest possible stack frame

Shared libraries on ppc64le will require a larger minimum stack frame (because
the ABI mandates that the TOC pointer is available at 24(R1)). So to prepare
for this, make a constant for the fixed part of a stack and use that where
necessary.

Change-Id: I447949f4d725003bb82e7d2cf7991c1bca5aa887
Reviewed-on: https://go-review.googlesource.com/15523Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 45c06b27
...@@ -12,6 +12,7 @@ const ( ...@@ -12,6 +12,7 @@ const (
_PCQuantum = 1 _PCQuantum = 1
_Int64Align = 4 _Int64Align = 4
hugePageSize = 1 << 21 hugePageSize = 1 << 21
minFrameSize = 0
) )
type uintreg uint32 type uintreg uint32
......
...@@ -12,6 +12,7 @@ const ( ...@@ -12,6 +12,7 @@ const (
_PCQuantum = 1 _PCQuantum = 1
_Int64Align = 8 _Int64Align = 8
hugePageSize = 1 << 21 hugePageSize = 1 << 21
minFrameSize = 0
) )
type uintreg uint64 type uintreg uint64
......
...@@ -12,6 +12,7 @@ const ( ...@@ -12,6 +12,7 @@ const (
_PCQuantum = 1 _PCQuantum = 1
_Int64Align = 8 _Int64Align = 8
hugePageSize = 1 << 21 hugePageSize = 1 << 21
minFrameSize = 0
) )
type uintreg uint64 type uintreg uint64
......
...@@ -12,6 +12,7 @@ const ( ...@@ -12,6 +12,7 @@ const (
_PCQuantum = 4 _PCQuantum = 4
_Int64Align = 4 _Int64Align = 4
hugePageSize = 0 hugePageSize = 0
minFrameSize = 4
) )
type uintreg uint32 type uintreg uint32
......
...@@ -12,6 +12,7 @@ const ( ...@@ -12,6 +12,7 @@ const (
_PCQuantum = 4 _PCQuantum = 4
_Int64Align = 8 _Int64Align = 8
hugePageSize = 0 hugePageSize = 0
minFrameSize = 8
) )
type uintreg uint64 type uintreg uint64
......
...@@ -12,6 +12,7 @@ const ( ...@@ -12,6 +12,7 @@ const (
_PCQuantum = 4 _PCQuantum = 4
_Int64Align = 8 _Int64Align = 8
hugePageSize = 0 hugePageSize = 0
minFrameSize = 8
) )
type uintreg uint64 type uintreg uint64
......
...@@ -12,6 +12,7 @@ const ( ...@@ -12,6 +12,7 @@ const (
_PCQuantum = 4 _PCQuantum = 4
_Int64Align = 8 _Int64Align = 8
hugePageSize = 0 hugePageSize = 0
minFrameSize = 8
) )
type uintreg uint64 type uintreg uint64
......
...@@ -237,10 +237,22 @@ func cgocallbackg1() { ...@@ -237,10 +237,22 @@ func cgocallbackg1() {
// On 386, stack frame is three words, plus caller PC. // On 386, stack frame is three words, plus caller PC.
cb = (*args)(unsafe.Pointer(sp + 4*ptrSize)) cb = (*args)(unsafe.Pointer(sp + 4*ptrSize))
case "ppc64", "ppc64le": case "ppc64", "ppc64le":
// On ppc64, stack frame is two words and there's a // On ppc64, the callback arguments are in the arguments area of
// saved LR between SP and the stack frame and between // cgocallback's stack frame. The stack looks like this:
// the stack frame and the arguments. // +--------------------+------------------------------+
cb = (*args)(unsafe.Pointer(sp + 4*ptrSize)) // | | ... |
// | cgoexp_$fn +------------------------------+
// | | fixed frame area |
// +--------------------+------------------------------+
// | | arguments area |
// | cgocallback +------------------------------+ <- sp + 2*minFrameSize + 2*ptrSize
// | | fixed frame area |
// +--------------------+------------------------------+ <- sp + minFrameSize + 2*ptrSize
// | | local variables (2 pointers) |
// | cgocallback_gofunc +------------------------------+ <- sp + minFrameSize
// | | fixed frame area |
// +--------------------+------------------------------+ <- sp
cb = (*args)(unsafe.Pointer(sp + 2*minFrameSize + 2*ptrSize))
} }
// Invoke callback. // Invoke callback.
...@@ -271,14 +283,10 @@ func unwindm(restore *bool) { ...@@ -271,14 +283,10 @@ func unwindm(restore *bool) {
switch GOARCH { switch GOARCH {
default: default:
throw("unwindm not implemented") throw("unwindm not implemented")
case "386", "amd64": case "386", "amd64", "arm", "ppc64", "ppc64le":
sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp)) sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + minFrameSize))
case "arm":
sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 4))
case "arm64": case "arm64":
sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 16)) sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 16))
case "ppc64", "ppc64le":
sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 8))
} }
releasem(mp) releasem(mp)
} }
......
...@@ -496,12 +496,10 @@ func scanframeworker(frame *stkframe, unused unsafe.Pointer, gcw *gcWork) { ...@@ -496,12 +496,10 @@ func scanframeworker(frame *stkframe, unused unsafe.Pointer, gcw *gcWork) {
size := frame.varp - frame.sp size := frame.varp - frame.sp
var minsize uintptr var minsize uintptr
switch thechar { switch thechar {
case '6', '8':
minsize = 0
case '7': case '7':
minsize = spAlign minsize = spAlign
default: default:
minsize = ptrSize minsize = minFrameSize
} }
if size > minsize { if size > minsize {
stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps)) stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
......
...@@ -531,8 +531,6 @@ func throw(s string) { ...@@ -531,8 +531,6 @@ func throw(s string) {
//uint32 runtime·panicking; //uint32 runtime·panicking;
var paniclk mutex var paniclk mutex
const hasLinkRegister = GOARCH == "arm" || GOARCH == "arm64" || GOARCH == "ppc64" || GOARCH == "ppc64le"
// Unwind the stack after a deferred function calls recover // Unwind the stack after a deferred function calls recover
// after a panic. Then arrange to continue running as though // after a panic. Then arrange to continue running as though
// the caller of the deferred function returned normally. // the caller of the deferred function returned normally.
......
...@@ -2256,17 +2256,14 @@ func newproc1(fn *funcval, argp *uint8, narg int32, nret int32, callerpc uintptr ...@@ -2256,17 +2256,14 @@ func newproc1(fn *funcval, argp *uint8, narg int32, nret int32, callerpc uintptr
throw("newproc1: new g is not Gdead") throw("newproc1: new g is not Gdead")
} }
totalSize := 4*regSize + uintptr(siz) // extra space in case of reads slightly beyond frame totalSize := 4*regSize + uintptr(siz) + minFrameSize // extra space in case of reads slightly beyond frame
if hasLinkRegister { totalSize += -totalSize & (spAlign - 1) // align to spAlign
totalSize += ptrSize
}
totalSize += -totalSize & (spAlign - 1) // align to spAlign
sp := newg.stack.hi - totalSize sp := newg.stack.hi - totalSize
spArg := sp spArg := sp
if hasLinkRegister { if usesLR {
// caller's LR // caller's LR
*(*unsafe.Pointer)(unsafe.Pointer(sp)) = nil *(*unsafe.Pointer)(unsafe.Pointer(sp)) = nil
spArg += ptrSize spArg += minFrameSize
} }
memmove(unsafe.Pointer(spArg), unsafe.Pointer(argp), uintptr(narg)) memmove(unsafe.Pointer(spArg), unsafe.Pointer(argp), uintptr(narg))
......
...@@ -82,7 +82,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { ...@@ -82,7 +82,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
// functions are correctly handled. This smashes // functions are correctly handled. This smashes
// the stack frame but we're not going back there // the stack frame but we're not going back there
// anyway. // anyway.
sp := c.sp() - ptrSize sp := c.sp() - minFrameSize
c.set_sp(sp) c.set_sp(sp)
*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link() *(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link()
......
...@@ -578,12 +578,10 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool { ...@@ -578,12 +578,10 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
size := frame.varp - frame.sp size := frame.varp - frame.sp
var minsize uintptr var minsize uintptr
switch thechar { switch thechar {
case '6', '8':
minsize = 0
case '7': case '7':
minsize = spAlign minsize = spAlign
default: default:
minsize = ptrSize minsize = minFrameSize
} }
if size > minsize { if size > minsize {
var bv bitvector var bv bitvector
......
...@@ -26,9 +26,10 @@ import "unsafe" ...@@ -26,9 +26,10 @@ import "unsafe"
// stores an 8-byte return PC onto the stack. To accommodate this, we use regSize // stores an 8-byte return PC onto the stack. To accommodate this, we use regSize
// as the size of the architecture-pushed return PC. // as the size of the architecture-pushed return PC.
// //
// usesLR is defined below. ptrSize and regSize are defined in stubs.go. // usesLR is defined below in terms of minFrameSize, which is defined in
// arch_$GOARCH.go. ptrSize and regSize are defined in stubs.go.
const usesLR = GOARCH != "amd64" && GOARCH != "amd64p32" && GOARCH != "386" const usesLR = minFrameSize > 0
var ( var (
// initialized in tracebackinit // initialized in tracebackinit
...@@ -295,10 +296,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in ...@@ -295,10 +296,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
// in package runtime and reflect, and for those we use call-specific // in package runtime and reflect, and for those we use call-specific
// metadata recorded by f's caller. // metadata recorded by f's caller.
if callback != nil || printing { if callback != nil || printing {
frame.argp = frame.fp frame.argp = frame.fp + minFrameSize
if usesLR {
frame.argp += ptrSize
}
setArgInfo(&frame, f, callback != nil) setArgInfo(&frame, f, callback != nil)
} }
...@@ -396,7 +394,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in ...@@ -396,7 +394,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
// before faking a call to sigpanic. // before faking a call to sigpanic.
if usesLR && waspanic { if usesLR && waspanic {
x := *(*uintptr)(unsafe.Pointer(frame.sp)) x := *(*uintptr)(unsafe.Pointer(frame.sp))
frame.sp += ptrSize frame.sp += minFrameSize
if GOARCH == "arm64" { if GOARCH == "arm64" {
// arm64 needs 16-byte aligned SP, always // arm64 needs 16-byte aligned SP, always
frame.sp += ptrSize frame.sp += ptrSize
...@@ -496,10 +494,7 @@ func setArgInfo(frame *stkframe, f *_func, needArgMap bool) { ...@@ -496,10 +494,7 @@ func setArgInfo(frame *stkframe, f *_func, needArgMap bool) {
// Extract argument bitmaps for reflect stubs from the calls they made to reflect. // Extract argument bitmaps for reflect stubs from the calls they made to reflect.
switch funcname(f) { switch funcname(f) {
case "reflect.makeFuncStub", "reflect.methodValueCall": case "reflect.makeFuncStub", "reflect.methodValueCall":
arg0 := frame.sp arg0 := frame.sp + minFrameSize
if usesLR {
arg0 += ptrSize
}
fn := *(**[2]uintptr)(unsafe.Pointer(arg0)) fn := *(**[2]uintptr)(unsafe.Pointer(arg0))
if fn[0] != f.entry { if fn[0] != f.entry {
print("runtime: confused by ", funcname(f), "\n") print("runtime: confused by ", funcname(f), "\n")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment