RET
// func walltime() (sec int64, nsec int32)
-TEXT runtime·walltime(SB), NOSPLIT, $16
+TEXT runtime·walltime(SB), NOSPLIT, $0-12
+ // We don't know how much stack space the VDSO code will need,
+ // so switch to g0.
+
+ MOVL SP, BP // Save old SP; BP unchanged by C code.
+
+ get_tls(CX)
+ MOVL g(CX), AX
+ MOVL g_m(AX), CX
+ MOVL m_curg(CX), DX
+
+ CMPL AX, DX // Only switch if on curg.
+ JNE noswitch
+
+ MOVL m_g0(CX), DX
+ MOVL (g_sched+gobuf_sp)(DX), SP // Set SP to g0 stack
+
+noswitch:
+ SUBL $16, SP // Space for results
+ ANDL $~15, SP // Align for C code
+
// Stack layout, depending on call path:
// x(SP) vDSO INVOKE_SYSCALL
// 12 ts.tv_nsec ts.tv_nsec
// 8 ts.tv_sec ts.tv_sec
// 4 &ts -
// 0 CLOCK_<id> -
- //
- // If we take the vDSO path, we're calling a function with gcc calling convention.
- // We're guaranteed 128 bytes on entry. We've taken 16, and the call uses another 4,
- // leaving 108 for __vdso_clock_gettime to use.
+
MOVL runtime·__vdso_clock_gettime_sym(SB), AX
CMPL AX, $0
JEQ fallback
MOVL 8(SP), AX // sec
MOVL 12(SP), BX // nsec
+ MOVL BP, SP // Restore real SP
+
// sec is in AX, nsec in BX
MOVL AX, sec_lo+0(FP)
MOVL $0, sec_hi+4(FP)
// int64 nanotime(void) so really
// void nanotime(int64 *nsec)
-TEXT runtime·nanotime(SB), NOSPLIT, $16
- // See comments above in walltime() about stack space usage and layout.
+TEXT runtime·nanotime(SB), NOSPLIT, $0-8
+ // Switch to g0 stack. See comment above in runtime·walltime.
+
+ MOVL SP, BP // Save old SP; BP unchanged by C code.
+
+ get_tls(CX)
+ MOVL g(CX), AX
+ MOVL g_m(AX), CX
+ MOVL m_curg(CX), DX
+
+ CMPL AX, DX // Only switch if on curg.
+ JNE noswitch
+
+ MOVL m_g0(CX), DX
+ MOVL (g_sched+gobuf_sp)(DX), SP // Set SP to g0 stack
+
+noswitch:
+ SUBL $16, SP // Space for results
+ ANDL $~15, SP // Align for C code
+
MOVL runtime·__vdso_clock_gettime_sym(SB), AX
CMPL AX, $0
JEQ fallback
MOVL 8(SP), AX // sec
MOVL 12(SP), BX // nsec
+ MOVL BP, SP // Restore real SP
+
// sec is in AX, nsec in BX
// convert to DX:AX nsec
MOVL $1000000000, CX
RET
// func walltime() (sec int64, nsec int32)
-TEXT runtime·walltime(SB),NOSPLIT,$16
- // Be careful. We're calling a function with gcc calling convention here.
- // We're guaranteed 128 bytes on entry, and we've taken 16, and the
- // call uses another 8.
- // That leaves 104 for the gettime code to use. Hope that's enough!
+TEXT runtime·walltime(SB),NOSPLIT,$0-12
+ // We don't know how much stack space the VDSO code will need,
+ // so switch to g0.
+ // In particular, a kernel configured with CONFIG_OPTIMIZE_INLINING=n
+ // and hardening can use a full page of stack space in gettime_sym
+ // due to stack probes inserted to avoid stack/heap collisions.
+ // See issue #20427.
+
+ MOVQ SP, BP // Save old SP; BP unchanged by C code.
+
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), CX
+ MOVQ m_curg(CX), DX
+
+ CMPQ AX, DX // Only switch if on curg.
+ JNE noswitch
+
+ MOVQ m_g0(CX), DX
+ MOVQ (g_sched+gobuf_sp)(DX), SP // Set SP to g0 stack
+
+noswitch:
+ SUBQ $16, SP // Space for results
+ ANDQ $~15, SP // Align for C code
+
MOVQ runtime·__vdso_clock_gettime_sym(SB), AX
CMPQ AX, $0
JEQ fallback
CALL AX
MOVQ 0(SP), AX // sec
MOVQ 8(SP), DX // nsec
+ MOVQ BP, SP // Restore real SP
MOVQ AX, sec+0(FP)
MOVL DX, nsec+8(FP)
RET
MOVQ 0(SP), AX // sec
MOVL 8(SP), DX // usec
IMULQ $1000, DX
+ MOVQ BP, SP // Restore real SP
MOVQ AX, sec+0(FP)
MOVL DX, nsec+8(FP)
RET
-TEXT runtime·nanotime(SB),NOSPLIT,$16
- // Duplicate time.now here to avoid using up precious stack space.
- // See comment above in time.now.
+TEXT runtime·nanotime(SB),NOSPLIT,$0-8
+ // Switch to g0 stack. See comment above in runtime·walltime.
+
+ MOVQ SP, BP // Save old SP; BX unchanged by C code.
+
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), CX
+ MOVQ m_curg(CX), DX
+
+ CMPQ AX, DX // Only switch if on curg.
+ JNE noswitch
+
+ MOVQ m_g0(CX), DX
+ MOVQ (g_sched+gobuf_sp)(DX), SP // Set SP to g0 stack
+
+noswitch:
+ SUBQ $16, SP // Space for results
+ ANDQ $~15, SP // Align for C code
+
MOVQ runtime·__vdso_clock_gettime_sym(SB), AX
CMPQ AX, $0
JEQ fallback
CALL AX
MOVQ 0(SP), AX // sec
MOVQ 8(SP), DX // nsec
+ MOVQ BP, SP // Restore real SP
// sec is in AX, nsec in DX
// return nsec in AX
IMULQ $1000000000, AX
CALL AX
MOVQ 0(SP), AX // sec
MOVL 8(SP), DX // usec
+ MOVQ BP, SP // Restore real SP
IMULQ $1000, DX
// sec is in AX, nsec in DX
// return nsec in AX