mirror of
https://github.com/golang/go
synced 2024-11-26 06:27:58 -07:00
runtime: unify asmcgocall and systemstack traceback setup
Both asmcgocall and systemstack need to save the calling Go code's context for use by traceback, but they do it differently. Systemstack's appraoch is better, because it doesn't require a special case in traceback. So make them both use that. While we are here, the fake mstart caller in systemstack is no longer needed and can be removed. (traceback knows to stop in systemstack because of the writes to SP.) Also remove the fake mstarts in sys_windows_*.s. And while we are there, fix the control flow guard code in sys_windows_arm.s. The current code is using pointers to a stack frame that technically is gone once we hit the RET instruction. Clearly it's working OK, but better not to depend on data below SP being preserved, even for just a few instructions. Store the value we need in other registers instead. (This code is only used for pushing a sigpanic call, which does not actually return to the site of the fault and therefore doesn't need to preserve any of the registers.) This CL is part of a stack adding windows/arm64 support (#36439), intended to land in the Go 1.17 cycle. This CL is, however, not windows/arm64-specific. It is cleanup meant to make the port (and future ports) easier. Change-Id: Id1e3ef5e54f7ad786e4b87043f2626eba7c3bbd9 Reviewed-on: https://go-review.googlesource.com/c/go/+/288799 Trust: Russ Cox <rsc@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
229695a283
commit
01f05d8ff1
@ -182,7 +182,7 @@ func testCallbackCallers(t *testing.T) {
|
|||||||
"runtime.cgocallbackg1",
|
"runtime.cgocallbackg1",
|
||||||
"runtime.cgocallbackg",
|
"runtime.cgocallbackg",
|
||||||
"runtime.cgocallback",
|
"runtime.cgocallback",
|
||||||
"runtime.asmcgocall",
|
"runtime.systemstack_switch",
|
||||||
"runtime.cgocall",
|
"runtime.cgocall",
|
||||||
"test._Cfunc_callback",
|
"test._Cfunc_callback",
|
||||||
"test.nestedCall.func1",
|
"test.nestedCall.func1",
|
||||||
|
@ -352,18 +352,12 @@ TEXT runtime·systemstack(SB), NOSPLIT, $0-4
|
|||||||
// switch stacks
|
// switch stacks
|
||||||
// save our state in g->sched. Pretend to
|
// save our state in g->sched. Pretend to
|
||||||
// be systemstack_switch if the G stack is scanned.
|
// be systemstack_switch if the G stack is scanned.
|
||||||
MOVL $runtime·systemstack_switch(SB), (g_sched+gobuf_pc)(AX)
|
CALL gosave_systemstack_switch<>(SB)
|
||||||
MOVL SP, (g_sched+gobuf_sp)(AX)
|
|
||||||
MOVL AX, (g_sched+gobuf_g)(AX)
|
|
||||||
|
|
||||||
// switch to g0
|
// switch to g0
|
||||||
get_tls(CX)
|
get_tls(CX)
|
||||||
MOVL DX, g(CX)
|
MOVL DX, g(CX)
|
||||||
MOVL (g_sched+gobuf_sp)(DX), BX
|
MOVL (g_sched+gobuf_sp)(DX), BX
|
||||||
// make it look like mstart called systemstack on g0, to stop traceback
|
|
||||||
SUBL $4, BX
|
|
||||||
MOVL $runtime·mstart(SB), DX
|
|
||||||
MOVL DX, 0(BX)
|
|
||||||
MOVL BX, SP
|
MOVL BX, SP
|
||||||
|
|
||||||
// call target function
|
// call target function
|
||||||
@ -601,15 +595,18 @@ TEXT runtime·jmpdefer(SB), NOSPLIT, $0-8
|
|||||||
MOVL 0(DX), BX
|
MOVL 0(DX), BX
|
||||||
JMP BX // but first run the deferred function
|
JMP BX // but first run the deferred function
|
||||||
|
|
||||||
// Save state of caller into g->sched.
|
// Save state of caller into g->sched,
|
||||||
TEXT gosave<>(SB),NOSPLIT,$0
|
// but using fake PC from systemstack_switch.
|
||||||
|
// Must only be called from functions with no locals ($0)
|
||||||
|
// or else unwinding from systemstack_switch is incorrect.
|
||||||
|
TEXT gosave_systemstack_switch<>(SB),NOSPLIT,$0
|
||||||
PUSHL AX
|
PUSHL AX
|
||||||
PUSHL BX
|
PUSHL BX
|
||||||
get_tls(BX)
|
get_tls(BX)
|
||||||
MOVL g(BX), BX
|
MOVL g(BX), BX
|
||||||
LEAL arg+0(FP), AX
|
LEAL arg+0(FP), AX
|
||||||
MOVL AX, (g_sched+gobuf_sp)(BX)
|
MOVL AX, (g_sched+gobuf_sp)(BX)
|
||||||
MOVL -4(AX), AX
|
MOVL $runtime·systemstack_switch(SB), AX
|
||||||
MOVL AX, (g_sched+gobuf_pc)(BX)
|
MOVL AX, (g_sched+gobuf_pc)(BX)
|
||||||
MOVL $0, (g_sched+gobuf_ret)(BX)
|
MOVL $0, (g_sched+gobuf_ret)(BX)
|
||||||
// Assert ctxt is zero. See func save.
|
// Assert ctxt is zero. See func save.
|
||||||
@ -661,7 +658,7 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-12
|
|||||||
JEQ noswitch
|
JEQ noswitch
|
||||||
CMPL DI, m_gsignal(BP)
|
CMPL DI, m_gsignal(BP)
|
||||||
JEQ noswitch
|
JEQ noswitch
|
||||||
CALL gosave<>(SB)
|
CALL gosave_systemstack_switch<>(SB)
|
||||||
get_tls(CX)
|
get_tls(CX)
|
||||||
MOVL SI, g(CX)
|
MOVL SI, g(CX)
|
||||||
MOVL (g_sched+gobuf_sp)(SI), SP
|
MOVL (g_sched+gobuf_sp)(SI), SP
|
||||||
|
@ -338,20 +338,12 @@ TEXT runtime·systemstack(SB), NOSPLIT, $0-8
|
|||||||
// switch stacks
|
// switch stacks
|
||||||
// save our state in g->sched. Pretend to
|
// save our state in g->sched. Pretend to
|
||||||
// be systemstack_switch if the G stack is scanned.
|
// be systemstack_switch if the G stack is scanned.
|
||||||
MOVQ $runtime·systemstack_switch(SB), SI
|
CALL gosave_systemstack_switch<>(SB)
|
||||||
MOVQ SI, (g_sched+gobuf_pc)(AX)
|
|
||||||
MOVQ SP, (g_sched+gobuf_sp)(AX)
|
|
||||||
MOVQ AX, (g_sched+gobuf_g)(AX)
|
|
||||||
MOVQ BP, (g_sched+gobuf_bp)(AX)
|
|
||||||
|
|
||||||
// switch to g0
|
// switch to g0
|
||||||
MOVQ DX, g(CX)
|
MOVQ DX, g(CX)
|
||||||
MOVQ DX, R14 // set the g register
|
MOVQ DX, R14 // set the g register
|
||||||
MOVQ (g_sched+gobuf_sp)(DX), BX
|
MOVQ (g_sched+gobuf_sp)(DX), BX
|
||||||
// make it look like mstart called systemstack on g0, to stop traceback
|
|
||||||
SUBQ $8, BX
|
|
||||||
MOVQ $runtime·mstart(SB), DX
|
|
||||||
MOVQ DX, 0(BX)
|
|
||||||
MOVQ BX, SP
|
MOVQ BX, SP
|
||||||
|
|
||||||
// call target function
|
// call target function
|
||||||
@ -660,13 +652,17 @@ TEXT runtime·jmpdefer(SB), NOSPLIT, $0-16
|
|||||||
MOVQ 0(DX), BX
|
MOVQ 0(DX), BX
|
||||||
JMP BX // but first run the deferred function
|
JMP BX // but first run the deferred function
|
||||||
|
|
||||||
// Save state of caller into g->sched. Smashes R9.
|
// Save state of caller into g->sched,
|
||||||
TEXT gosave<>(SB),NOSPLIT,$0
|
// but using fake PC from systemstack_switch.
|
||||||
|
// Must only be called from functions with no locals ($0)
|
||||||
|
// or else unwinding from systemstack_switch is incorrect.
|
||||||
|
// Smashes R9.
|
||||||
|
TEXT gosave_systemstack_switch<>(SB),NOSPLIT,$0
|
||||||
#ifndef GOEXPERIMENT_REGABI
|
#ifndef GOEXPERIMENT_REGABI
|
||||||
get_tls(R14)
|
get_tls(R14)
|
||||||
MOVQ g(R14), R14
|
MOVQ g(R14), R14
|
||||||
#endif
|
#endif
|
||||||
MOVQ 0(SP), R9
|
MOVQ $runtime·systemstack_switch(SB), R9
|
||||||
MOVQ R9, (g_sched+gobuf_pc)(R14)
|
MOVQ R9, (g_sched+gobuf_pc)(R14)
|
||||||
LEAQ 8(SP), R9
|
LEAQ 8(SP), R9
|
||||||
MOVQ R9, (g_sched+gobuf_sp)(R14)
|
MOVQ R9, (g_sched+gobuf_sp)(R14)
|
||||||
@ -724,7 +720,7 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20
|
|||||||
|
|
||||||
// Switch to system stack.
|
// Switch to system stack.
|
||||||
MOVQ m_g0(R8), SI
|
MOVQ m_g0(R8), SI
|
||||||
CALL gosave<>(SB)
|
CALL gosave_systemstack_switch<>(SB)
|
||||||
MOVQ SI, g(CX)
|
MOVQ SI, g(CX)
|
||||||
MOVQ (g_sched+gobuf_sp)(SI), SP
|
MOVQ (g_sched+gobuf_sp)(SI), SP
|
||||||
|
|
||||||
|
@ -305,24 +305,14 @@ TEXT runtime·systemstack(SB),NOSPLIT,$0-4
|
|||||||
switch:
|
switch:
|
||||||
// save our state in g->sched. Pretend to
|
// save our state in g->sched. Pretend to
|
||||||
// be systemstack_switch if the G stack is scanned.
|
// be systemstack_switch if the G stack is scanned.
|
||||||
MOVW $runtime·systemstack_switch(SB), R3
|
BL gosave_systemstack_switch<>(SB)
|
||||||
ADD $4, R3, R3 // get past push {lr}
|
|
||||||
MOVW R3, (g_sched+gobuf_pc)(g)
|
|
||||||
MOVW R13, (g_sched+gobuf_sp)(g)
|
|
||||||
MOVW LR, (g_sched+gobuf_lr)(g)
|
|
||||||
MOVW g, (g_sched+gobuf_g)(g)
|
|
||||||
|
|
||||||
// switch to g0
|
// switch to g0
|
||||||
MOVW R0, R5
|
MOVW R0, R5
|
||||||
MOVW R2, R0
|
MOVW R2, R0
|
||||||
BL setg<>(SB)
|
BL setg<>(SB)
|
||||||
MOVW R5, R0
|
MOVW R5, R0
|
||||||
MOVW (g_sched+gobuf_sp)(R2), R3
|
MOVW (g_sched+gobuf_sp)(R2), R13
|
||||||
// make it look like mstart called systemstack on g0, to stop traceback
|
|
||||||
SUB $4, R3, R3
|
|
||||||
MOVW $runtime·mstart(SB), R4
|
|
||||||
MOVW R4, 0(R3)
|
|
||||||
MOVW R3, R13
|
|
||||||
|
|
||||||
// call target function
|
// call target function
|
||||||
MOVW R0, R7
|
MOVW R0, R7
|
||||||
@ -537,19 +527,25 @@ TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8
|
|||||||
MOVW 0(R7), R1
|
MOVW 0(R7), R1
|
||||||
B (R1)
|
B (R1)
|
||||||
|
|
||||||
// Save state of caller into g->sched. Smashes R11.
|
// Save state of caller into g->sched,
|
||||||
TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
|
// but using fake PC from systemstack_switch.
|
||||||
MOVW LR, (g_sched+gobuf_pc)(g)
|
// Must only be called from functions with no locals ($0)
|
||||||
|
// or else unwinding from systemstack_switch is incorrect.
|
||||||
|
// Smashes R11.
|
||||||
|
TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
|
||||||
|
MOVW $runtime·systemstack_switch(SB), R11
|
||||||
|
ADD $4, R11 // get past push {lr}
|
||||||
|
MOVW R11, (g_sched+gobuf_pc)(g)
|
||||||
MOVW R13, (g_sched+gobuf_sp)(g)
|
MOVW R13, (g_sched+gobuf_sp)(g)
|
||||||
|
MOVW g, (g_sched+gobuf_g)(g)
|
||||||
MOVW $0, R11
|
MOVW $0, R11
|
||||||
MOVW R11, (g_sched+gobuf_lr)(g)
|
MOVW R11, (g_sched+gobuf_lr)(g)
|
||||||
MOVW R11, (g_sched+gobuf_ret)(g)
|
MOVW R11, (g_sched+gobuf_ret)(g)
|
||||||
MOVW R11, (g_sched+gobuf_ctxt)(g)
|
|
||||||
// Assert ctxt is zero. See func save.
|
// Assert ctxt is zero. See func save.
|
||||||
MOVW (g_sched+gobuf_ctxt)(g), R11
|
MOVW (g_sched+gobuf_ctxt)(g), R11
|
||||||
CMP $0, R11
|
TST R11, R11
|
||||||
B.EQ 2(PC)
|
B.EQ 2(PC)
|
||||||
CALL runtime·badctxt(SB)
|
BL runtime·badctxt(SB)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
// func asmcgocall_no_g(fn, arg unsafe.Pointer)
|
// func asmcgocall_no_g(fn, arg unsafe.Pointer)
|
||||||
@ -590,7 +586,7 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-12
|
|||||||
MOVW m_g0(R8), R3
|
MOVW m_g0(R8), R3
|
||||||
CMP R3, g
|
CMP R3, g
|
||||||
BEQ nosave
|
BEQ nosave
|
||||||
BL gosave<>(SB)
|
BL gosave_systemstack_switch<>(SB)
|
||||||
MOVW R0, R5
|
MOVW R0, R5
|
||||||
MOVW R3, R0
|
MOVW R3, R0
|
||||||
BL setg<>(SB)
|
BL setg<>(SB)
|
||||||
|
@ -205,24 +205,12 @@ TEXT runtime·systemstack(SB), NOSPLIT, $0-8
|
|||||||
switch:
|
switch:
|
||||||
// save our state in g->sched. Pretend to
|
// save our state in g->sched. Pretend to
|
||||||
// be systemstack_switch if the G stack is scanned.
|
// be systemstack_switch if the G stack is scanned.
|
||||||
MOVD $runtime·systemstack_switch(SB), R6
|
BL gosave_systemstack_switch<>(SB)
|
||||||
ADD $8, R6 // get past prologue
|
|
||||||
MOVD R6, (g_sched+gobuf_pc)(g)
|
|
||||||
MOVD RSP, R0
|
|
||||||
MOVD R0, (g_sched+gobuf_sp)(g)
|
|
||||||
MOVD R29, (g_sched+gobuf_bp)(g)
|
|
||||||
MOVD $0, (g_sched+gobuf_lr)(g)
|
|
||||||
MOVD g, (g_sched+gobuf_g)(g)
|
|
||||||
|
|
||||||
// switch to g0
|
// switch to g0
|
||||||
MOVD R5, g
|
MOVD R5, g
|
||||||
BL runtime·save_g(SB)
|
BL runtime·save_g(SB)
|
||||||
MOVD (g_sched+gobuf_sp)(g), R3
|
MOVD (g_sched+gobuf_sp)(g), R3
|
||||||
// make it look like mstart called systemstack on g0, to stop traceback
|
|
||||||
SUB $16, R3
|
|
||||||
AND $~15, R3
|
|
||||||
MOVD $runtime·mstart(SB), R4
|
|
||||||
MOVD R4, 0(R3)
|
|
||||||
MOVD R3, RSP
|
MOVD R3, RSP
|
||||||
MOVD (g_sched+gobuf_bp)(g), R29
|
MOVD (g_sched+gobuf_bp)(g), R29
|
||||||
|
|
||||||
@ -859,14 +847,21 @@ TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16
|
|||||||
MOVD 0(R26), R3
|
MOVD 0(R26), R3
|
||||||
B (R3)
|
B (R3)
|
||||||
|
|
||||||
// Save state of caller into g->sched. Smashes R0.
|
// Save state of caller into g->sched,
|
||||||
TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
|
// but using fake PC from systemstack_switch.
|
||||||
MOVD LR, (g_sched+gobuf_pc)(g)
|
// Must only be called from functions with no locals ($0)
|
||||||
|
// or else unwinding from systemstack_switch is incorrect.
|
||||||
|
// Smashes R0.
|
||||||
|
TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
|
||||||
|
MOVD $runtime·systemstack_switch(SB), R0
|
||||||
|
ADD $8, R0 // get past prologue
|
||||||
|
MOVD R0, (g_sched+gobuf_pc)(g)
|
||||||
MOVD RSP, R0
|
MOVD RSP, R0
|
||||||
MOVD R0, (g_sched+gobuf_sp)(g)
|
MOVD R0, (g_sched+gobuf_sp)(g)
|
||||||
MOVD R29, (g_sched+gobuf_bp)(g)
|
MOVD R29, (g_sched+gobuf_bp)(g)
|
||||||
MOVD $0, (g_sched+gobuf_lr)(g)
|
MOVD $0, (g_sched+gobuf_lr)(g)
|
||||||
MOVD $0, (g_sched+gobuf_ret)(g)
|
MOVD $0, (g_sched+gobuf_ret)(g)
|
||||||
|
MOVD g, (g_sched+gobuf_g)(g)
|
||||||
// Assert ctxt is zero. See func save.
|
// Assert ctxt is zero. See func save.
|
||||||
MOVD (g_sched+gobuf_ctxt)(g), R0
|
MOVD (g_sched+gobuf_ctxt)(g), R0
|
||||||
CBZ R0, 2(PC)
|
CBZ R0, 2(PC)
|
||||||
@ -908,8 +903,8 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20
|
|||||||
BEQ nosave
|
BEQ nosave
|
||||||
|
|
||||||
// Switch to system stack.
|
// Switch to system stack.
|
||||||
MOVD R0, R9 // gosave<> and save_g might clobber R0
|
MOVD R0, R9 // gosave_systemstack_switch<> and save_g might clobber R0
|
||||||
BL gosave<>(SB)
|
BL gosave_systemstack_switch<>(SB)
|
||||||
MOVD R3, g
|
MOVD R3, g
|
||||||
BL runtime·save_g(SB)
|
BL runtime·save_g(SB)
|
||||||
MOVD (g_sched+gobuf_sp)(g), R0
|
MOVD (g_sched+gobuf_sp)(g), R0
|
||||||
|
@ -169,21 +169,12 @@ TEXT runtime·systemstack(SB), NOSPLIT, $0-8
|
|||||||
switch:
|
switch:
|
||||||
// save our state in g->sched. Pretend to
|
// save our state in g->sched. Pretend to
|
||||||
// be systemstack_switch if the G stack is scanned.
|
// be systemstack_switch if the G stack is scanned.
|
||||||
MOVV $runtime·systemstack_switch(SB), R4
|
JAL gosave_systemstack_switch<>(SB)
|
||||||
ADDV $8, R4 // get past prologue
|
|
||||||
MOVV R4, (g_sched+gobuf_pc)(g)
|
|
||||||
MOVV R29, (g_sched+gobuf_sp)(g)
|
|
||||||
MOVV R0, (g_sched+gobuf_lr)(g)
|
|
||||||
MOVV g, (g_sched+gobuf_g)(g)
|
|
||||||
|
|
||||||
// switch to g0
|
// switch to g0
|
||||||
MOVV R3, g
|
MOVV R3, g
|
||||||
JAL runtime·save_g(SB)
|
JAL runtime·save_g(SB)
|
||||||
MOVV (g_sched+gobuf_sp)(g), R1
|
MOVV (g_sched+gobuf_sp)(g), R1
|
||||||
// make it look like mstart called systemstack on g0, to stop traceback
|
|
||||||
ADDV $-8, R1
|
|
||||||
MOVV $runtime·mstart(SB), R2
|
|
||||||
MOVV R2, 0(R1)
|
|
||||||
MOVV R1, R29
|
MOVV R1, R29
|
||||||
|
|
||||||
// call target function
|
// call target function
|
||||||
@ -401,12 +392,19 @@ TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16
|
|||||||
MOVV 0(REGCTXT), R4
|
MOVV 0(REGCTXT), R4
|
||||||
JMP (R4)
|
JMP (R4)
|
||||||
|
|
||||||
// Save state of caller into g->sched. Smashes R1.
|
// Save state of caller into g->sched,
|
||||||
TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
|
// but using fake PC from systemstack_switch.
|
||||||
MOVV R31, (g_sched+gobuf_pc)(g)
|
// Must only be called from functions with no locals ($0)
|
||||||
|
// or else unwinding from systemstack_switch is incorrect.
|
||||||
|
// Smashes R1.
|
||||||
|
TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
|
||||||
|
MOVV $runtime·systemstack_switch(SB), R1
|
||||||
|
ADDV $8, R1 // get past prologue
|
||||||
|
MOVV R1, (g_sched+gobuf_pc)(g)
|
||||||
MOVV R29, (g_sched+gobuf_sp)(g)
|
MOVV R29, (g_sched+gobuf_sp)(g)
|
||||||
MOVV R0, (g_sched+gobuf_lr)(g)
|
MOVV R0, (g_sched+gobuf_lr)(g)
|
||||||
MOVV R0, (g_sched+gobuf_ret)(g)
|
MOVV R0, (g_sched+gobuf_ret)(g)
|
||||||
|
MOVV g, (g_sched+gobuf_g)(g)
|
||||||
// Assert ctxt is zero. See func save.
|
// Assert ctxt is zero. See func save.
|
||||||
MOVV (g_sched+gobuf_ctxt)(g), R1
|
MOVV (g_sched+gobuf_ctxt)(g), R1
|
||||||
BEQ R1, 2(PC)
|
BEQ R1, 2(PC)
|
||||||
@ -440,7 +438,7 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20
|
|||||||
MOVV m_g0(R5), R6
|
MOVV m_g0(R5), R6
|
||||||
BEQ R6, g, g0
|
BEQ R6, g, g0
|
||||||
|
|
||||||
JAL gosave<>(SB)
|
JAL gosave_systemstack_switch<>(SB)
|
||||||
MOVV R6, g
|
MOVV R6, g
|
||||||
JAL runtime·save_g(SB)
|
JAL runtime·save_g(SB)
|
||||||
MOVV (g_sched+gobuf_sp)(g), R29
|
MOVV (g_sched+gobuf_sp)(g), R29
|
||||||
|
@ -170,21 +170,12 @@ TEXT runtime·systemstack(SB),NOSPLIT,$0-4
|
|||||||
switch:
|
switch:
|
||||||
// save our state in g->sched. Pretend to
|
// save our state in g->sched. Pretend to
|
||||||
// be systemstack_switch if the G stack is scanned.
|
// be systemstack_switch if the G stack is scanned.
|
||||||
MOVW $runtime·systemstack_switch(SB), R4
|
JAL gosave_systemstack_switch<>(SB)
|
||||||
ADDU $8, R4 // get past prologue
|
|
||||||
MOVW R4, (g_sched+gobuf_pc)(g)
|
|
||||||
MOVW R29, (g_sched+gobuf_sp)(g)
|
|
||||||
MOVW R0, (g_sched+gobuf_lr)(g)
|
|
||||||
MOVW g, (g_sched+gobuf_g)(g)
|
|
||||||
|
|
||||||
// switch to g0
|
// switch to g0
|
||||||
MOVW R3, g
|
MOVW R3, g
|
||||||
JAL runtime·save_g(SB)
|
JAL runtime·save_g(SB)
|
||||||
MOVW (g_sched+gobuf_sp)(g), R1
|
MOVW (g_sched+gobuf_sp)(g), R1
|
||||||
// make it look like mstart called systemstack on g0, to stop traceback
|
|
||||||
ADDU $-4, R1
|
|
||||||
MOVW $runtime·mstart(SB), R2
|
|
||||||
MOVW R2, 0(R1)
|
|
||||||
MOVW R1, R29
|
MOVW R1, R29
|
||||||
|
|
||||||
// call target function
|
// call target function
|
||||||
@ -401,12 +392,19 @@ TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8
|
|||||||
MOVW 0(REGCTXT), R4
|
MOVW 0(REGCTXT), R4
|
||||||
JMP (R4)
|
JMP (R4)
|
||||||
|
|
||||||
// Save state of caller into g->sched. Smashes R1.
|
// Save state of caller into g->sched,
|
||||||
TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
|
// but using fake PC from systemstack_switch.
|
||||||
MOVW R31, (g_sched+gobuf_pc)(g)
|
// Must only be called from functions with no locals ($0)
|
||||||
|
// or else unwinding from systemstack_switch is incorrect.
|
||||||
|
// Smashes R1.
|
||||||
|
TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
|
||||||
|
MOVW $runtime·systemstack_switch(SB), R1
|
||||||
|
ADDU $8, R1 // get past prologue
|
||||||
|
MOVW R1, (g_sched+gobuf_pc)(g)
|
||||||
MOVW R29, (g_sched+gobuf_sp)(g)
|
MOVW R29, (g_sched+gobuf_sp)(g)
|
||||||
MOVW R0, (g_sched+gobuf_lr)(g)
|
MOVW R0, (g_sched+gobuf_lr)(g)
|
||||||
MOVW R0, (g_sched+gobuf_ret)(g)
|
MOVW R0, (g_sched+gobuf_ret)(g)
|
||||||
|
MOVW g, (g_sched+gobuf_g)(g)
|
||||||
// Assert ctxt is zero. See func save.
|
// Assert ctxt is zero. See func save.
|
||||||
MOVW (g_sched+gobuf_ctxt)(g), R1
|
MOVW (g_sched+gobuf_ctxt)(g), R1
|
||||||
BEQ R1, 2(PC)
|
BEQ R1, 2(PC)
|
||||||
@ -431,7 +429,7 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-12
|
|||||||
MOVW m_g0(R5), R6
|
MOVW m_g0(R5), R6
|
||||||
BEQ R6, g, g0
|
BEQ R6, g, g0
|
||||||
|
|
||||||
JAL gosave<>(SB)
|
JAL gosave_systemstack_switch<>(SB)
|
||||||
MOVW R6, g
|
MOVW R6, g
|
||||||
JAL runtime·save_g(SB)
|
JAL runtime·save_g(SB)
|
||||||
MOVW (g_sched+gobuf_sp)(g), R29
|
MOVW (g_sched+gobuf_sp)(g), R29
|
||||||
|
@ -229,22 +229,12 @@ TEXT runtime·systemstack(SB), NOSPLIT, $0-8
|
|||||||
switch:
|
switch:
|
||||||
// save our state in g->sched. Pretend to
|
// save our state in g->sched. Pretend to
|
||||||
// be systemstack_switch if the G stack is scanned.
|
// be systemstack_switch if the G stack is scanned.
|
||||||
MOVD $runtime·systemstack_switch(SB), R6
|
BL gosave_systemstack_switch<>(SB)
|
||||||
ADD $16, R6 // get past prologue (including r2-setting instructions when they're there)
|
|
||||||
MOVD R6, (g_sched+gobuf_pc)(g)
|
|
||||||
MOVD R1, (g_sched+gobuf_sp)(g)
|
|
||||||
MOVD R0, (g_sched+gobuf_lr)(g)
|
|
||||||
MOVD g, (g_sched+gobuf_g)(g)
|
|
||||||
|
|
||||||
// switch to g0
|
// switch to g0
|
||||||
MOVD R5, g
|
MOVD R5, g
|
||||||
BL runtime·save_g(SB)
|
BL runtime·save_g(SB)
|
||||||
MOVD (g_sched+gobuf_sp)(g), R3
|
MOVD (g_sched+gobuf_sp)(g), R1
|
||||||
// make it look like mstart called systemstack on g0, to stop traceback
|
|
||||||
SUB $FIXED_FRAME, R3
|
|
||||||
MOVD $runtime·mstart(SB), R4
|
|
||||||
MOVD R4, 0(R3)
|
|
||||||
MOVD R3, R1
|
|
||||||
|
|
||||||
// call target function
|
// call target function
|
||||||
MOVD 0(R11), R12 // code pointer
|
MOVD 0(R11), R12 // code pointer
|
||||||
@ -534,13 +524,19 @@ TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16
|
|||||||
MOVD R12, CTR
|
MOVD R12, CTR
|
||||||
BR (CTR)
|
BR (CTR)
|
||||||
|
|
||||||
// Save state of caller into g->sched. Smashes R31.
|
// Save state of caller into g->sched,
|
||||||
TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
|
// but using fake PC from systemstack_switch.
|
||||||
MOVD LR, R31
|
// Must only be called from functions with no locals ($0)
|
||||||
|
// or else unwinding from systemstack_switch is incorrect.
|
||||||
|
// Smashes R31.
|
||||||
|
TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
|
||||||
|
MOVD $runtime·systemstack_switch(SB), R31
|
||||||
|
ADD $16, R31 // get past prologue (including r2-setting instructions when they're there)
|
||||||
MOVD R31, (g_sched+gobuf_pc)(g)
|
MOVD R31, (g_sched+gobuf_pc)(g)
|
||||||
MOVD R1, (g_sched+gobuf_sp)(g)
|
MOVD R1, (g_sched+gobuf_sp)(g)
|
||||||
MOVD R0, (g_sched+gobuf_lr)(g)
|
MOVD R0, (g_sched+gobuf_lr)(g)
|
||||||
MOVD R0, (g_sched+gobuf_ret)(g)
|
MOVD R0, (g_sched+gobuf_ret)(g)
|
||||||
|
MOVD g, (g_sched+gobuf_g)(g)
|
||||||
// Assert ctxt is zero. See func save.
|
// Assert ctxt is zero. See func save.
|
||||||
MOVD (g_sched+gobuf_ctxt)(g), R31
|
MOVD (g_sched+gobuf_ctxt)(g), R31
|
||||||
CMP R0, R31
|
CMP R0, R31
|
||||||
@ -577,7 +573,7 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20
|
|||||||
MOVD m_g0(R8), R6
|
MOVD m_g0(R8), R6
|
||||||
CMP R6, g
|
CMP R6, g
|
||||||
BEQ g0
|
BEQ g0
|
||||||
BL gosave<>(SB)
|
BL gosave_systemstack_switch<>(SB)
|
||||||
MOVD R6, g
|
MOVD R6, g
|
||||||
BL runtime·save_g(SB)
|
BL runtime·save_g(SB)
|
||||||
MOVD (g_sched+gobuf_sp)(g), R1
|
MOVD (g_sched+gobuf_sp)(g), R1
|
||||||
|
@ -114,21 +114,12 @@ TEXT runtime·systemstack(SB), NOSPLIT, $0-8
|
|||||||
switch:
|
switch:
|
||||||
// save our state in g->sched. Pretend to
|
// save our state in g->sched. Pretend to
|
||||||
// be systemstack_switch if the G stack is scanned.
|
// be systemstack_switch if the G stack is scanned.
|
||||||
MOV $runtime·systemstack_switch(SB), T2
|
CALL gosave_systemstack_switch<>(SB)
|
||||||
ADD $8, T2 // get past prologue
|
|
||||||
MOV T2, (g_sched+gobuf_pc)(g)
|
|
||||||
MOV X2, (g_sched+gobuf_sp)(g)
|
|
||||||
MOV ZERO, (g_sched+gobuf_lr)(g)
|
|
||||||
MOV g, (g_sched+gobuf_g)(g)
|
|
||||||
|
|
||||||
// switch to g0
|
// switch to g0
|
||||||
MOV T1, g
|
MOV T1, g
|
||||||
CALL runtime·save_g(SB)
|
CALL runtime·save_g(SB)
|
||||||
MOV (g_sched+gobuf_sp)(g), T0
|
MOV (g_sched+gobuf_sp)(g), T0
|
||||||
// make it look like mstart called systemstack on g0, to stop traceback
|
|
||||||
ADD $-8, T0
|
|
||||||
MOV $runtime·mstart(SB), T1
|
|
||||||
MOV T1, 0(T0)
|
|
||||||
MOV T0, X2
|
MOV T0, X2
|
||||||
|
|
||||||
// call target function
|
// call target function
|
||||||
@ -297,12 +288,19 @@ TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8
|
|||||||
JALR RA, T1
|
JALR RA, T1
|
||||||
JMP runtime·badmcall2(SB)
|
JMP runtime·badmcall2(SB)
|
||||||
|
|
||||||
// Save state of caller into g->sched. Smashes X31.
|
// Save state of caller into g->sched,
|
||||||
TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
|
// but using fake PC from systemstack_switch.
|
||||||
MOV X1, (g_sched+gobuf_pc)(g)
|
// Must only be called from functions with no locals ($0)
|
||||||
|
// or else unwinding from systemstack_switch is incorrect.
|
||||||
|
// Smashes X31.
|
||||||
|
TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
|
||||||
|
MOV $runtime·systemstack_switch(SB), X31
|
||||||
|
ADD $8, X31 // get past prologue
|
||||||
|
MOV X31, (g_sched+gobuf_pc)(g)
|
||||||
MOV X2, (g_sched+gobuf_sp)(g)
|
MOV X2, (g_sched+gobuf_sp)(g)
|
||||||
MOV ZERO, (g_sched+gobuf_lr)(g)
|
MOV ZERO, (g_sched+gobuf_lr)(g)
|
||||||
MOV ZERO, (g_sched+gobuf_ret)(g)
|
MOV ZERO, (g_sched+gobuf_ret)(g)
|
||||||
|
MOV g, (g_sched+gobuf_g)(g)
|
||||||
// Assert ctxt is zero. See func save.
|
// Assert ctxt is zero. See func save.
|
||||||
MOV (g_sched+gobuf_ctxt)(g), X31
|
MOV (g_sched+gobuf_ctxt)(g), X31
|
||||||
BEQ ZERO, X31, 2(PC)
|
BEQ ZERO, X31, 2(PC)
|
||||||
@ -327,7 +325,7 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20
|
|||||||
MOV m_g0(X6), X7
|
MOV m_g0(X6), X7
|
||||||
BEQ X7, g, g0
|
BEQ X7, g, g0
|
||||||
|
|
||||||
CALL gosave<>(SB)
|
CALL gosave_systemstack_switch<>(SB)
|
||||||
MOV X7, g
|
MOV X7, g
|
||||||
CALL runtime·save_g(SB)
|
CALL runtime·save_g(SB)
|
||||||
MOV (g_sched+gobuf_sp)(g), X2
|
MOV (g_sched+gobuf_sp)(g), X2
|
||||||
|
@ -256,22 +256,12 @@ TEXT runtime·systemstack(SB), NOSPLIT, $0-8
|
|||||||
switch:
|
switch:
|
||||||
// save our state in g->sched. Pretend to
|
// save our state in g->sched. Pretend to
|
||||||
// be systemstack_switch if the G stack is scanned.
|
// be systemstack_switch if the G stack is scanned.
|
||||||
MOVD $runtime·systemstack_switch(SB), R6
|
BL gosave_systemstack_switch<>(SB)
|
||||||
ADD $16, R6 // get past prologue
|
|
||||||
MOVD R6, (g_sched+gobuf_pc)(g)
|
|
||||||
MOVD R15, (g_sched+gobuf_sp)(g)
|
|
||||||
MOVD $0, (g_sched+gobuf_lr)(g)
|
|
||||||
MOVD g, (g_sched+gobuf_g)(g)
|
|
||||||
|
|
||||||
// switch to g0
|
// switch to g0
|
||||||
MOVD R5, g
|
MOVD R5, g
|
||||||
BL runtime·save_g(SB)
|
BL runtime·save_g(SB)
|
||||||
MOVD (g_sched+gobuf_sp)(g), R3
|
MOVD (g_sched+gobuf_sp)(g), R15
|
||||||
// make it look like mstart called systemstack on g0, to stop traceback
|
|
||||||
SUB $8, R3
|
|
||||||
MOVD $runtime·mstart(SB), R4
|
|
||||||
MOVD R4, 0(R3)
|
|
||||||
MOVD R3, R15
|
|
||||||
|
|
||||||
// call target function
|
// call target function
|
||||||
MOVD 0(R12), R3 // code pointer
|
MOVD 0(R12), R3 // code pointer
|
||||||
@ -498,12 +488,19 @@ TEXT runtime·jmpdefer(SB),NOSPLIT|NOFRAME,$0-16
|
|||||||
MOVD 0(R12), R3
|
MOVD 0(R12), R3
|
||||||
BR (R3)
|
BR (R3)
|
||||||
|
|
||||||
// Save state of caller into g->sched. Smashes R1.
|
// Save state of caller into g->sched,
|
||||||
TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
|
// but using fake PC from systemstack_switch.
|
||||||
MOVD LR, (g_sched+gobuf_pc)(g)
|
// Must only be called from functions with no locals ($0)
|
||||||
|
// or else unwinding from systemstack_switch is incorrect.
|
||||||
|
// Smashes R1.
|
||||||
|
TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
|
||||||
|
MOVD $runtime·systemstack_switch(SB), R1
|
||||||
|
ADD $16, R1 // get past prologue
|
||||||
|
MOVD R1, (g_sched+gobuf_pc)(g)
|
||||||
MOVD R15, (g_sched+gobuf_sp)(g)
|
MOVD R15, (g_sched+gobuf_sp)(g)
|
||||||
MOVD $0, (g_sched+gobuf_lr)(g)
|
MOVD $0, (g_sched+gobuf_lr)(g)
|
||||||
MOVD $0, (g_sched+gobuf_ret)(g)
|
MOVD $0, (g_sched+gobuf_ret)(g)
|
||||||
|
MOVD g, (g_sched+gobuf_g)(g)
|
||||||
// Assert ctxt is zero. See func save.
|
// Assert ctxt is zero. See func save.
|
||||||
MOVD (g_sched+gobuf_ctxt)(g), R1
|
MOVD (g_sched+gobuf_ctxt)(g), R1
|
||||||
CMPBEQ R1, $0, 2(PC)
|
CMPBEQ R1, $0, 2(PC)
|
||||||
@ -529,7 +526,7 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20
|
|||||||
MOVD g_m(g), R6
|
MOVD g_m(g), R6
|
||||||
MOVD m_g0(R6), R6
|
MOVD m_g0(R6), R6
|
||||||
CMPBEQ R6, g, g0
|
CMPBEQ R6, g, g0
|
||||||
BL gosave<>(SB)
|
BL gosave_systemstack_switch<>(SB)
|
||||||
MOVD R6, g
|
MOVD R6, g
|
||||||
BL runtime·save_g(SB)
|
BL runtime·save_g(SB)
|
||||||
MOVD (g_sched+gobuf_sp)(g), R15
|
MOVD (g_sched+gobuf_sp)(g), R15
|
||||||
|
@ -94,7 +94,7 @@ TEXT sigtramp<>(SB),NOSPLIT,$0-0
|
|||||||
JNE 2(PC)
|
JNE 2(PC)
|
||||||
CALL runtime·badsignal2(SB)
|
CALL runtime·badsignal2(SB)
|
||||||
|
|
||||||
// save g and SP in case of stack switch
|
// save g in case of stack switch
|
||||||
MOVL DX, 32(SP) // g
|
MOVL DX, 32(SP) // g
|
||||||
MOVL SP, 36(SP)
|
MOVL SP, 36(SP)
|
||||||
|
|
||||||
@ -108,13 +108,9 @@ TEXT sigtramp<>(SB),NOSPLIT,$0-0
|
|||||||
get_tls(BP)
|
get_tls(BP)
|
||||||
MOVL BX, g(BP)
|
MOVL BX, g(BP)
|
||||||
MOVL (g_sched+gobuf_sp)(BX), DI
|
MOVL (g_sched+gobuf_sp)(BX), DI
|
||||||
// make it look like mstart called us on g0, to stop traceback
|
// make room for sighandler arguments
|
||||||
SUBL $4, DI
|
|
||||||
MOVL $runtime·mstart(SB), 0(DI)
|
|
||||||
// traceback will think that we've done SUBL
|
|
||||||
// on this stack, so subtract them here to match.
|
|
||||||
// (we need room for sighandler arguments anyway).
|
|
||||||
// and re-save old SP for restoring later.
|
// and re-save old SP for restoring later.
|
||||||
|
// (note that the 36(DI) here must match the 36(SP) above.)
|
||||||
SUBL $40, DI
|
SUBL $40, DI
|
||||||
MOVL SP, 36(DI)
|
MOVL SP, 36(DI)
|
||||||
MOVL DI, SP
|
MOVL DI, SP
|
||||||
@ -132,7 +128,7 @@ g0:
|
|||||||
// switch back to original stack and g
|
// switch back to original stack and g
|
||||||
// no-op if we never left.
|
// no-op if we never left.
|
||||||
MOVL 36(SP), SP
|
MOVL 36(SP), SP
|
||||||
MOVL 32(SP), DX
|
MOVL 32(SP), DX // note: different SP
|
||||||
get_tls(BP)
|
get_tls(BP)
|
||||||
MOVL DX, g(BP)
|
MOVL DX, g(BP)
|
||||||
|
|
||||||
|
@ -151,16 +151,10 @@ TEXT sigtramp<>(SB),NOSPLIT|NOFRAME,$0-0
|
|||||||
get_tls(BP)
|
get_tls(BP)
|
||||||
MOVQ BX, g(BP)
|
MOVQ BX, g(BP)
|
||||||
MOVQ (g_sched+gobuf_sp)(BX), DI
|
MOVQ (g_sched+gobuf_sp)(BX), DI
|
||||||
// make it look like mstart called us on g0, to stop traceback
|
// make room for sighandler arguments
|
||||||
SUBQ $8, DI
|
|
||||||
MOVQ $runtime·mstart(SB), SI
|
|
||||||
MOVQ SI, 0(DI)
|
|
||||||
// traceback will think that we've done PUSHFQ and SUBQ
|
|
||||||
// on this stack, so subtract them here to match.
|
|
||||||
// (we need room for sighandler arguments anyway).
|
|
||||||
// and re-save old SP for restoring later.
|
// and re-save old SP for restoring later.
|
||||||
SUBQ $(112+8), DI
|
// (note that the 104(DI) here must match the 104(SP) above.)
|
||||||
// save g, save old stack pointer.
|
SUBQ $120, DI
|
||||||
MOVQ SP, 104(DI)
|
MOVQ SP, 104(DI)
|
||||||
MOVQ DI, SP
|
MOVQ DI, SP
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include "go_tls.h"
|
#include "go_tls.h"
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// Note: For system ABI, R0-R3 are args, R4-R11 are callee-save.
|
||||||
|
|
||||||
// void runtime·asmstdcall(void *c);
|
// void runtime·asmstdcall(void *c);
|
||||||
TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0
|
TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0
|
||||||
MOVM.DB.W [R4, R5, R14], (R13) // push {r4, r5, lr}
|
MOVM.DB.W [R4, R5, R14], (R13) // push {r4, r5, lr}
|
||||||
@ -139,11 +141,10 @@ TEXT sigtramp<>(SB),NOSPLIT|NOFRAME,$0
|
|||||||
MOVW (g_sched+gobuf_sp)(g), R3 // R3 = g->gobuf.sp
|
MOVW (g_sched+gobuf_sp)(g), R3 // R3 = g->gobuf.sp
|
||||||
BL runtime·save_g(SB)
|
BL runtime·save_g(SB)
|
||||||
|
|
||||||
// traceback will think that we've done PUSH and SUB
|
// make room for sighandler arguments
|
||||||
// on this stack, so subtract them here to match.
|
|
||||||
// (we need room for sighandler arguments anyway).
|
|
||||||
// and re-save old SP for restoring later.
|
// and re-save old SP for restoring later.
|
||||||
SUB $(40+8+20), R3
|
// (note that the 24(R3) here must match the 24(R13) above.)
|
||||||
|
SUB $40, R3
|
||||||
MOVW R13, 24(R3) // save old stack pointer
|
MOVW R13, 24(R3) // save old stack pointer
|
||||||
MOVW R3, R13 // switch stack
|
MOVW R3, R13 // switch stack
|
||||||
|
|
||||||
@ -151,22 +152,14 @@ g0:
|
|||||||
MOVW 0(R6), R2 // R2 = ExceptionPointers->ExceptionRecord
|
MOVW 0(R6), R2 // R2 = ExceptionPointers->ExceptionRecord
|
||||||
MOVW 4(R6), R3 // R3 = ExceptionPointers->ContextRecord
|
MOVW 4(R6), R3 // R3 = ExceptionPointers->ContextRecord
|
||||||
|
|
||||||
// make it look like mstart called us on g0, to stop traceback
|
MOVW $0, R4
|
||||||
MOVW $runtime·mstart(SB), R4
|
MOVW R4, 0(R13) // No saved link register.
|
||||||
|
|
||||||
MOVW R4, 0(R13) // Save link register for traceback
|
|
||||||
MOVW R2, 4(R13) // Move arg0 (ExceptionRecord) into position
|
MOVW R2, 4(R13) // Move arg0 (ExceptionRecord) into position
|
||||||
MOVW R3, 8(R13) // Move arg1 (ContextRecord) into position
|
MOVW R3, 8(R13) // Move arg1 (ContextRecord) into position
|
||||||
MOVW R5, 12(R13) // Move arg2 (original g) into position
|
MOVW R5, 12(R13) // Move arg2 (original g) into position
|
||||||
BL (R7) // Call the go routine
|
BL (R7) // Call the go routine
|
||||||
MOVW 16(R13), R4 // Fetch return value from stack
|
MOVW 16(R13), R4 // Fetch return value from stack
|
||||||
|
|
||||||
// Compute the value of the g0 stack pointer after deallocating
|
|
||||||
// this frame, then allocating 8 bytes. We may need to store
|
|
||||||
// the resume SP and PC on the g0 stack to work around
|
|
||||||
// control flow guard when we resume from the exception.
|
|
||||||
ADD $(40+20), R13, R12
|
|
||||||
|
|
||||||
// switch back to original stack and g
|
// switch back to original stack and g
|
||||||
MOVW 24(R13), R13
|
MOVW 24(R13), R13
|
||||||
MOVW 20(R13), g
|
MOVW 20(R13), g
|
||||||
@ -192,33 +185,36 @@ done:
|
|||||||
// If returntramp has already been set up by a previous exception
|
// If returntramp has already been set up by a previous exception
|
||||||
// handler, don't clobber the stored SP and PC on the stack.
|
// handler, don't clobber the stored SP and PC on the stack.
|
||||||
MOVW 4(R3), R3 // PEXCEPTION_POINTERS->Context
|
MOVW 4(R3), R3 // PEXCEPTION_POINTERS->Context
|
||||||
MOVW 0x40(R3), R2 // load PC from context record
|
MOVW context_pc(R3), R2 // load PC from context record
|
||||||
MOVW $returntramp<>(SB), R1
|
MOVW $returntramp<>(SB), R1
|
||||||
CMP R1, R2
|
CMP R1, R2
|
||||||
B.EQ return // do not clobber saved SP/PC
|
B.EQ return // do not clobber saved SP/PC
|
||||||
|
|
||||||
// Save resume SP and PC on g0 stack
|
// Save resume SP and PC into R0, R1.
|
||||||
MOVW 0x38(R3), R2 // load SP from context record
|
MOVW context_spr(R3), R2
|
||||||
MOVW R2, 0(R12) // Store resume SP on g0 stack
|
MOVW R2, context_r0(R3)
|
||||||
MOVW 0x40(R3), R2 // load PC from context record
|
MOVW context_pc(R3), R2
|
||||||
MOVW R2, 4(R12) // Store resume PC on g0 stack
|
MOVW R2, context_r1(R3)
|
||||||
|
|
||||||
// Set up context record to return to returntramp on g0 stack
|
// Set up context record to return to returntramp on g0 stack
|
||||||
MOVW R12, 0x38(R3) // save g0 stack pointer
|
MOVW R12, context_spr(R3)
|
||||||
// in context record
|
MOVW $returntramp<>(SB), R2
|
||||||
MOVW $returntramp<>(SB), R2 // save resume address
|
MOVW R2, context_pc(R3)
|
||||||
MOVW R2, 0x40(R3) // in context record
|
|
||||||
|
|
||||||
return:
|
return:
|
||||||
B (R14) // return
|
B (R14) // return
|
||||||
|
|
||||||
//
|
|
||||||
// Trampoline to resume execution from exception handler.
|
// Trampoline to resume execution from exception handler.
|
||||||
// This is part of the control flow guard workaround.
|
// This is part of the control flow guard workaround.
|
||||||
// It switches stacks and jumps to the continuation address.
|
// It switches stacks and jumps to the continuation address.
|
||||||
//
|
// R0 and R1 are set above at the end of sigtramp<>
|
||||||
|
// in the context that starts executing at returntramp<>.
|
||||||
TEXT returntramp<>(SB),NOSPLIT|NOFRAME,$0
|
TEXT returntramp<>(SB),NOSPLIT|NOFRAME,$0
|
||||||
MOVM.IA (R13), [R13, R15] // ldm sp, [sp, pc]
|
// Important: do not smash LR,
|
||||||
|
// which is set to a live value when handling
|
||||||
|
// a signal by pushing a call to sigpanic onto the stack.
|
||||||
|
MOVW R0, R13
|
||||||
|
B (R1)
|
||||||
|
|
||||||
TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0
|
TEXT runtime·exceptiontramp(SB),NOSPLIT|NOFRAME,$0
|
||||||
MOVW $runtime·exceptionhandler(SB), R1
|
MOVW $runtime·exceptionhandler(SB), R1
|
||||||
|
Loading…
Reference in New Issue
Block a user