aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mkpreempt.go
diff options
context:
space:
mode:
authorCherry Zhang <cherryyz@google.com>2019-10-29 20:42:00 -0400
committerCherry Zhang <cherryyz@google.com>2019-11-07 20:45:45 +0000
commit933bf75edaf4e762f65e6738d5a9d71b6438b50f (patch)
tree130ee0037103ce98ee545cc7f19ede9fedad25e1 /src/runtime/mkpreempt.go
parent4751db93ef23c87c0fa2f06433555b7084f339bd (diff)
downloadgo-933bf75edaf4e762f65e6738d5a9d71b6438b50f.tar.gz
go-933bf75edaf4e762f65e6738d5a9d71b6438b50f.zip
runtime: add async preemption support on S390X
This CL adds support of call injection and async preemption on S390X. Like ARM64, we need to clobber one register (REGTMP) for returning from the injected call. Previous CLs have marked code sequences that use REGTMP async-nonpreemtible. Change-Id: I78adbc5fd70ca245da390f6266623385b45c9dfc Reviewed-on: https://go-review.googlesource.com/c/go/+/204106 Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/runtime/mkpreempt.go')
-rw-r--r--src/runtime/mkpreempt.go35
1 files changed, 34 insertions, 1 deletions
diff --git a/src/runtime/mkpreempt.go b/src/runtime/mkpreempt.go
index 76637e8a01..2f022971fd 100644
--- a/src/runtime/mkpreempt.go
+++ b/src/runtime/mkpreempt.go
@@ -83,7 +83,7 @@ var arches = map[string]func(){
"mips64x": notImplemented,
"mipsx": notImplemented,
"ppc64x": notImplemented,
- "s390x": notImplemented,
+ "s390x": genS390X,
"wasm": genWasm,
}
var beLe = map[string]bool{"mips64x": true, "mipsx": true, "ppc64x": true}
@@ -356,6 +356,39 @@ func genARM64() {
p("JMP (R27)")
}
+func genS390X() {
+ // Add integer registers R0-R12
+ // R13 (g), R14 (LR), R15 (SP) are special, and not saved here.
+ // Saving R10 (REGTMP) is not necessary, but it is saved anyway.
+ var l = layout{sp: "R15", stack: 16} // add slot to save PC of interrupted instruction and flags
+ l.addSpecial(
+ "STMG R0, R12, %d(R15)",
+ "LMG %d(R15), R0, R12",
+ 13*8)
+ // Add floating point registers F0-F31.
+ for i := 0; i <= 15; i++ {
+ reg := fmt.Sprintf("F%d", i)
+ l.add("FMOVD", reg, 8)
+ }
+
+ // allocate frame, save PC of interrupted instruction (in LR) and flags (condition code)
+ p("IPM R10") // save flags upfront, as ADD will clobber flags
+ p("MOVD R14, -%d(R15)", l.stack)
+ p("ADD $-%d, R15", l.stack)
+ p("MOVW R10, 8(R15)") // save flags
+
+ l.save()
+ p("CALL ·asyncPreempt2(SB)")
+ l.restore()
+
+ p("MOVD %d(R15), R14", l.stack) // sigctxt.pushCall has pushed LR (at interrupt) on stack, restore it
+ p("ADD $%d, R15", l.stack+8) // pop frame (including the space pushed by sigctxt.pushCall)
+ p("MOVWZ -%d(R15), R10", l.stack) // load flags to REGTMP
+ p("TMLH R10, $(3<<12)") // restore flags
+ p("MOVD -%d(R15), R10", l.stack+8) // load PC to REGTMP
+ p("JMP (R10)")
+}
+
func genWasm() {
p("// No async preemption on wasm")
p("UNDEF")