mirror of
https://github.com/golang/go
synced 2024-09-15 22:20:06 +00:00
runtime: refactor ARM VDSO call setup to helper
We have a very complex process to make VDSO calls on ARM. Create a wrapper helper function which reduces duplication and allows for additional calls from other packages. vdsoCall has a few differences from the original code in walltime/nanotime: * It does not use R0-R3, as they are passed through as arguments to fn. * It does not save g if g.m.gsignal.stack.lo is zero. This may occur if it called at startup on g0 between assigning g0.m.gsignal and setting its stack. For #49182 Change-Id: I51aca514b4835b71142011341d2f09125334d30f Reviewed-on: https://go-review.googlesource.com/c/go/+/362795 Run-TryBot: Michael Pratt <mpratt@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
c7f870ebc4
commit
876d477b0e
|
@ -11,6 +11,8 @@ const (
|
|||
_HWCAP_VFPv3 = 1 << 13 // introduced in 2.6.30
|
||||
)
|
||||
|
||||
func vdsoCall()
|
||||
|
||||
func checkgoarm() {
|
||||
// On Android, /proc/self/auxv might be unreadable and hwcap won't
|
||||
// reflect the CPU capabilities. Assume that every Android arm device
|
||||
|
|
|
@ -262,73 +262,105 @@ TEXT runtime·mincore(SB),NOSPLIT,$0
|
|||
MOVW R0, ret+12(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·walltime(SB),NOSPLIT,$8-12
|
||||
// Call a VDSO function.
|
||||
//
|
||||
// R0-R3: arguments to VDSO function (C calling convention)
|
||||
// R4: uintptr function to call
|
||||
//
|
||||
// There is no return value.
|
||||
TEXT runtime·vdsoCall(SB),NOSPLIT,$8-0
|
||||
// R0-R3 may be arguments to fn, do not touch.
|
||||
// R4 is function to call.
|
||||
// R5-R9 are available as locals. They are unchanged by the C call
|
||||
// (callee-save).
|
||||
|
||||
// We don't know how much stack space the VDSO code will need,
|
||||
// so switch to g0.
|
||||
|
||||
// Save old SP. Use R13 instead of SP to avoid linker rewriting the offsets.
|
||||
MOVW R13, R4 // R4 is unchanged by C code.
|
||||
MOVW R13, R5
|
||||
|
||||
MOVW g_m(g), R5 // R5 is unchanged by C code.
|
||||
MOVW g_m(g), R6
|
||||
|
||||
// Set vdsoPC and vdsoSP for SIGPROF traceback.
|
||||
// Save the old values on stack and restore them on exit,
|
||||
// so this function is reentrant.
|
||||
MOVW m_vdsoPC(R5), R1
|
||||
MOVW m_vdsoSP(R5), R2
|
||||
MOVW R1, 4(R13)
|
||||
MOVW R2, 8(R13)
|
||||
MOVW m_vdsoPC(R6), R7
|
||||
MOVW m_vdsoSP(R6), R8
|
||||
MOVW R7, 4(R13)
|
||||
MOVW R8, 8(R13)
|
||||
|
||||
MOVW $ret-4(FP), R2 // caller's SP
|
||||
MOVW LR, m_vdsoPC(R5)
|
||||
MOVW R2, m_vdsoSP(R5)
|
||||
MOVW $sp-4(FP), R7 // caller's SP
|
||||
MOVW LR, m_vdsoPC(R6)
|
||||
MOVW R7, m_vdsoSP(R6)
|
||||
|
||||
MOVW m_curg(R5), R0
|
||||
MOVW m_curg(R6), R7
|
||||
|
||||
CMP g, R0 // Only switch if on curg.
|
||||
CMP g, R7 // Only switch if on curg.
|
||||
B.NE noswitch
|
||||
|
||||
MOVW m_g0(R5), R0
|
||||
MOVW (g_sched+gobuf_sp)(R0), R13 // Set SP to g0 stack
|
||||
MOVW m_g0(R6), R7
|
||||
MOVW (g_sched+gobuf_sp)(R7), R13 // Set SP to g0 stack
|
||||
|
||||
noswitch:
|
||||
SUB $24, R13 // Space for results
|
||||
BIC $0x7, R13 // Align for C code
|
||||
|
||||
MOVW $CLOCK_REALTIME, R0
|
||||
MOVW $8(R13), R1 // timespec
|
||||
MOVW runtime·vdsoClockgettimeSym(SB), R2
|
||||
CMP $0, R2
|
||||
B.EQ fallback
|
||||
|
||||
// Store g on gsignal's stack, so if we receive a signal
|
||||
// during VDSO code we can find the g.
|
||||
// If we don't have a signal stack, we won't receive signal,
|
||||
// so don't bother saving g.
|
||||
// When using cgo, we already saved g on TLS, also don't save
|
||||
// g here.
|
||||
// Also don't save g if we are already on the signal stack.
|
||||
// We won't get a nested signal.
|
||||
MOVB runtime·iscgo(SB), R6
|
||||
CMP $0, R6
|
||||
|
||||
// When using cgo, we already saved g on TLS, also don't save g here.
|
||||
MOVB runtime·iscgo(SB), R7
|
||||
CMP $0, R7
|
||||
BNE nosaveg
|
||||
MOVW m_gsignal(R5), R6 // g.m.gsignal
|
||||
CMP $0, R6
|
||||
// If we don't have a signal stack, we won't receive signal, so don't
|
||||
// bother saving g.
|
||||
MOVW m_gsignal(R6), R7 // g.m.gsignal
|
||||
CMP $0, R7
|
||||
BEQ nosaveg
|
||||
CMP g, R6
|
||||
// Don't save g if we are already on the signal stack, as we won't get
|
||||
// a nested signal.
|
||||
CMP g, R7
|
||||
BEQ nosaveg
|
||||
MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo
|
||||
MOVW g, (R6)
|
||||
// If we don't have a signal stack, we won't receive signal, so don't
|
||||
// bother saving g.
|
||||
MOVW (g_stack+stack_lo)(R7), R7 // g.m.gsignal.stack.lo
|
||||
CMP $0, R7
|
||||
BEQ nosaveg
|
||||
MOVW g, (R7)
|
||||
|
||||
BL (R2)
|
||||
BL (R4)
|
||||
|
||||
MOVW $0, R1
|
||||
MOVW R1, (R6) // clear g slot, R6 is unchanged by C code
|
||||
MOVW $0, R8
|
||||
MOVW R8, (R7) // clear g slot
|
||||
|
||||
JMP finish
|
||||
|
||||
nosaveg:
|
||||
BL (R2)
|
||||
BL (R4)
|
||||
|
||||
finish:
|
||||
MOVW R5, R13 // Restore real SP
|
||||
// Restore vdsoPC, vdsoSP
|
||||
// We don't worry about being signaled between the two stores.
|
||||
// If we are not in a signal handler, we'll restore vdsoSP to 0,
|
||||
// and no one will care about vdsoPC. If we are in a signal handler,
|
||||
// we cannot receive another signal.
|
||||
MOVW 8(R13), R7
|
||||
MOVW R7, m_vdsoSP(R6)
|
||||
MOVW 4(R13), R7
|
||||
MOVW R7, m_vdsoPC(R6)
|
||||
RET
|
||||
|
||||
TEXT runtime·walltime(SB),NOSPLIT,$12-12
|
||||
MOVW $CLOCK_REALTIME, R0
|
||||
MOVW $spec-12(SP), R1 // timespec
|
||||
|
||||
MOVW runtime·vdsoClockgettimeSym(SB), R4
|
||||
CMP $0, R4
|
||||
B.EQ fallback
|
||||
|
||||
BL runtime·vdsoCall(SB)
|
||||
|
||||
JMP finish
|
||||
|
||||
fallback:
|
||||
|
@ -336,19 +368,8 @@ fallback:
|
|||
SWI $0
|
||||
|
||||
finish:
|
||||
MOVW 8(R13), R0 // sec
|
||||
MOVW 12(R13), R2 // nsec
|
||||
|
||||
MOVW R4, R13 // Restore real SP
|
||||
// Restore vdsoPC, vdsoSP
|
||||
// We don't worry about being signaled between the two stores.
|
||||
// If we are not in a signal handler, we'll restore vdsoSP to 0,
|
||||
// and no one will care about vdsoPC. If we are in a signal handler,
|
||||
// we cannot receive another signal.
|
||||
MOVW 8(R13), R1
|
||||
MOVW R1, m_vdsoSP(R5)
|
||||
MOVW 4(R13), R1
|
||||
MOVW R1, m_vdsoPC(R5)
|
||||
MOVW sec-12(SP), R0 // sec
|
||||
MOVW nsec-8(SP), R2 // nsec
|
||||
|
||||
MOVW R0, sec_lo+0(FP)
|
||||
MOVW $0, R1
|
||||
|
@ -356,73 +377,17 @@ finish:
|
|||
MOVW R2, nsec+8(FP)
|
||||
RET
|
||||
|
||||
// int64 nanotime1(void)
|
||||
TEXT runtime·nanotime1(SB),NOSPLIT,$8-8
|
||||
// Switch to g0 stack. See comment above in runtime·walltime.
|
||||
|
||||
// Save old SP. Use R13 instead of SP to avoid linker rewriting the offsets.
|
||||
MOVW R13, R4 // R4 is unchanged by C code.
|
||||
|
||||
MOVW g_m(g), R5 // R5 is unchanged by C code.
|
||||
|
||||
// Set vdsoPC and vdsoSP for SIGPROF traceback.
|
||||
// Save the old values on stack and restore them on exit,
|
||||
// so this function is reentrant.
|
||||
MOVW m_vdsoPC(R5), R1
|
||||
MOVW m_vdsoSP(R5), R2
|
||||
MOVW R1, 4(R13)
|
||||
MOVW R2, 8(R13)
|
||||
|
||||
MOVW $ret-4(FP), R2 // caller's SP
|
||||
MOVW LR, m_vdsoPC(R5)
|
||||
MOVW R2, m_vdsoSP(R5)
|
||||
|
||||
MOVW m_curg(R5), R0
|
||||
|
||||
CMP g, R0 // Only switch if on curg.
|
||||
B.NE noswitch
|
||||
|
||||
MOVW m_g0(R5), R0
|
||||
MOVW (g_sched+gobuf_sp)(R0), R13 // Set SP to g0 stack
|
||||
|
||||
noswitch:
|
||||
SUB $24, R13 // Space for results
|
||||
BIC $0x7, R13 // Align for C code
|
||||
|
||||
// func nanotime1() int64
|
||||
TEXT runtime·nanotime1(SB),NOSPLIT,$12-8
|
||||
MOVW $CLOCK_MONOTONIC, R0
|
||||
MOVW $8(R13), R1 // timespec
|
||||
MOVW runtime·vdsoClockgettimeSym(SB), R2
|
||||
CMP $0, R2
|
||||
MOVW $spec-12(SP), R1 // timespec
|
||||
|
||||
MOVW runtime·vdsoClockgettimeSym(SB), R4
|
||||
CMP $0, R4
|
||||
B.EQ fallback
|
||||
|
||||
// Store g on gsignal's stack, so if we receive a signal
|
||||
// during VDSO code we can find the g.
|
||||
// If we don't have a signal stack, we won't receive signal,
|
||||
// so don't bother saving g.
|
||||
// When using cgo, we already saved g on TLS, also don't save
|
||||
// g here.
|
||||
// Also don't save g if we are already on the signal stack.
|
||||
// We won't get a nested signal.
|
||||
MOVB runtime·iscgo(SB), R6
|
||||
CMP $0, R6
|
||||
BNE nosaveg
|
||||
MOVW m_gsignal(R5), R6 // g.m.gsignal
|
||||
CMP $0, R6
|
||||
BEQ nosaveg
|
||||
CMP g, R6
|
||||
BEQ nosaveg
|
||||
MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo
|
||||
MOVW g, (R6)
|
||||
BL runtime·vdsoCall(SB)
|
||||
|
||||
BL (R2)
|
||||
|
||||
MOVW $0, R1
|
||||
MOVW R1, (R6) // clear g slot, R6 is unchanged by C code
|
||||
|
||||
JMP finish
|
||||
|
||||
nosaveg:
|
||||
BL (R2)
|
||||
JMP finish
|
||||
|
||||
fallback:
|
||||
|
@ -430,19 +395,8 @@ fallback:
|
|||
SWI $0
|
||||
|
||||
finish:
|
||||
MOVW 8(R13), R0 // sec
|
||||
MOVW 12(R13), R2 // nsec
|
||||
|
||||
MOVW R4, R13 // Restore real SP
|
||||
// Restore vdsoPC, vdsoSP
|
||||
// We don't worry about being signaled between the two stores.
|
||||
// If we are not in a signal handler, we'll restore vdsoSP to 0,
|
||||
// and no one will care about vdsoPC. If we are in a signal handler,
|
||||
// we cannot receive another signal.
|
||||
MOVW 8(R13), R4
|
||||
MOVW R4, m_vdsoSP(R5)
|
||||
MOVW 4(R13), R4
|
||||
MOVW R4, m_vdsoPC(R5)
|
||||
MOVW sec-12(SP), R0 // sec
|
||||
MOVW nsec-8(SP), R2 // nsec
|
||||
|
||||
MOVW $1000000000, R3
|
||||
MULLU R0, R3, (R1, R0)
|
||||
|
@ -451,6 +405,7 @@ finish:
|
|||
|
||||
MOVW R0, ret_lo+0(FP)
|
||||
MOVW R1, ret_hi+4(FP)
|
||||
|
||||
RET
|
||||
|
||||
// int32 futex(int32 *uaddr, int32 op, int32 val,
|
||||
|
|
Loading…
Reference in a new issue