]> Cypherpunks repositories - gostls13.git/commit
cmd/compile: mark DUFFZERO/DUFFCOPY as async unsafe
authorKeith Randall <khr@golang.org>
Tue, 11 Aug 2020 20:07:35 +0000 (13:07 -0700)
committerKeith Randall <khr@golang.org>
Sun, 16 Aug 2020 17:05:28 +0000 (17:05 +0000)
commit01f99b4e9540f34b44e13b25f6dd04b82ac952d9
treeec18a4ca73b57a0ab1c4b2b38d5e5150422eab45
parentc6a11f0dd279f374602794af60c7cde4585a1e6f
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>
src/cmd/compile/internal/ssa/gen/AMD64Ops.go
src/cmd/compile/internal/ssa/gen/ARM64Ops.go
src/cmd/compile/internal/ssa/opGen.go