1
0
mirror of https://github.com/golang/go synced 2024-09-29 23:14:29 -06:00

cmd/compile: mark DUFFZERO/DUFFCOPY as async unsafe

These operations are async unsafe on architectures that use
frame pointers.

The reason is they rely on data being safe when stored below the stack
pointer. They do:

  45da69:       48 89 6c 24 f0          mov    %rbp,-0x10(%rsp)
  45da6e:       48 8d 6c 24 f0          lea    -0x10(%rsp),%rbp
  45da73:       e8 7d d0 ff ff          callq  45aaf5 <runtime.duffzero+0x115>
  45da78:       48 8b 6d 00             mov    0x0(%rbp),%rbp

This dance ensures that inside duffzero, it looks like there is a
proper frame pointer set up, so that stack walkbacks work correctly if
the kernel samples during duffzero.

However, this instruction sequence depends on data not being clobbered
even though it is below the stack pointer.

If there is an async interrupt at any of those last 3 instructions,
and the interrupt decides to insert a call to asyncPreempt, then the
saved frame pointer on the stack gets clobbered. The last instruction
above then restores junk to the frame pointer.

To prevent this, mark these instructions as async unsafe.

(The body of duffzero is already async unsafe, as it is in package runtime.)

Change-Id: I5562e82f9f5bd2fb543dcf2b6b9133d87ff83032
Reviewed-on: https://go-review.googlesource.com/c/go/+/248261
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Martin Möhrmann <moehrmann@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Keith Randall 2020-08-11 13:07:35 -07:00
parent c6a11f0dd2
commit 01f99b4e95
3 changed files with 8 additions and 0 deletions

View File

@ -748,6 +748,7 @@ func init() {
clobbers: buildReg("DI"),
},
faultOnNilArg0: true,
unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
},
{name: "MOVOconst", reg: regInfo{nil, 0, []regMask{fp}}, typ: "Int128", aux: "Int128", rematerializeable: true},
@ -786,6 +787,7 @@ func init() {
clobberFlags: true,
faultOnNilArg0: true,
faultOnNilArg1: true,
unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
},
// arg0 = destination pointer

View File

@ -507,6 +507,7 @@ func init() {
clobbers: buildReg("R20 R30"),
},
faultOnNilArg0: true,
unsafePoint: true, // FP maintenance around DUFFZERO can be clobbered by interrupts
},
// large zeroing
@ -547,6 +548,7 @@ func init() {
},
faultOnNilArg0: true,
faultOnNilArg1: true,
unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
},
// large move

View File

@ -13119,6 +13119,7 @@ var opcodeTable = [...]opInfo{
auxType: auxInt64,
argLen: 3,
faultOnNilArg0: true,
unsafePoint: true,
reg: regInfo{
inputs: []inputInfo{
{0, 128}, // DI
@ -13196,6 +13197,7 @@ var opcodeTable = [...]opInfo{
clobberFlags: true,
faultOnNilArg0: true,
faultOnNilArg1: true,
unsafePoint: true,
reg: regInfo{
inputs: []inputInfo{
{0, 128}, // DI
@ -20734,6 +20736,7 @@ var opcodeTable = [...]opInfo{
auxType: auxInt64,
argLen: 2,
faultOnNilArg0: true,
unsafePoint: true,
reg: regInfo{
inputs: []inputInfo{
{0, 1048576}, // R20
@ -20760,6 +20763,7 @@ var opcodeTable = [...]opInfo{
argLen: 3,
faultOnNilArg0: true,
faultOnNilArg1: true,
unsafePoint: true,
reg: regInfo{
inputs: []inputInfo{
{0, 2097152}, // R21