Home | History | Annotate | Download | only in runtime
      1 // Copyright 2014 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 //
      5 // System calls and other sys.stuff for AMD64, SunOS
      6 // /usr/include/sys/syscall.h for syscall numbers.
      7 //
      8 
      9 #include "go_asm.h"
     10 #include "go_tls.h"
     11 #include "textflag.h"
     12 
     13 // This is needed by asm_amd64.s
     14 TEXT runtimesettls(SB),NOSPLIT,$8
     15 	RET
     16 
     17 // void libc_miniterrno(void *(*___errno)(void));
     18 //
     19 // Set the TLS errno pointer in M.
     20 //
     21 // Called using runtimeasmcgocall from os_solaris.c:/minit.
     22 // NOT USING GO CALLING CONVENTION.
     23 TEXT runtimeminiterrno(SB),NOSPLIT,$0
     24 	// asmcgocall will put first argument into DI.
     25 	CALL	DI	// SysV ABI so returns in AX
     26 	get_tls(CX)
     27 	MOVQ	g(CX), BX
     28 	MOVQ	g_m(BX), BX
     29 	MOVQ	AX,	m_perrno(BX)
     30 	RET
     31 
     32 // int64 runtimenanotime1(void);
     33 //
     34 // clock_gettime(3c) wrapper because Timespec is too large for
     35 // runtimenanotime stack.
     36 //
     37 // Called using runtimesysvicall6 from os_solaris.c:/nanotime.
     38 // NOT USING GO CALLING CONVENTION.
     39 TEXT runtimenanotime1(SB),NOSPLIT,$0
     40 	// need space for the timespec argument.
     41 	SUBQ	$64, SP	// 16 bytes will do, but who knows in the future?
     42 	MOVQ	$3, DI	// CLOCK_REALTIME from <sys/time_impl.h>
     43 	MOVQ	SP, SI
     44 	LEAQ	libc_clock_gettime(SB), AX
     45 	CALL	AX
     46 	MOVQ	(SP), AX	// tv_sec from struct timespec
     47 	IMULQ	$1000000000, AX	// multiply into nanoseconds
     48 	ADDQ	8(SP), AX	// tv_nsec, offset should be stable.
     49 	ADDQ	$64, SP
     50 	RET
     51 
     52 // pipe(3c) wrapper that returns fds in AX, DX.
     53 // NOT USING GO CALLING CONVENTION.
     54 TEXT runtimepipe1(SB),NOSPLIT,$0
     55 	SUBQ	$16, SP // 8 bytes will do, but stack has to be 16-byte alligned
     56 	MOVQ	SP, DI
     57 	LEAQ	libc_pipe(SB), AX
     58 	CALL	AX
     59 	MOVL	0(SP), AX
     60 	MOVL	4(SP), DX
     61 	ADDQ	$16, SP
     62 	RET
     63 
     64 // Call a library function with SysV calling conventions.
     65 // The called function can take a maximum of 6 INTEGER class arguments,
     66 // see
     67 //   Michael Matz, Jan Hubicka, Andreas Jaeger, and Mark Mitchell
     68 //   System V Application Binary Interface
     69 //   AMD64 Architecture Processor Supplement
     70 // section 3.2.3.
     71 //
     72 // Called by runtimeasmcgocall or runtimecgocall.
     73 // NOT USING GO CALLING CONVENTION.
     74 TEXT runtimeasmsysvicall6(SB),NOSPLIT,$0
     75 	// asmcgocall will put first argument into DI.
     76 	PUSHQ	DI			// save for later
     77 	MOVQ	libcall_fn(DI), AX
     78 	MOVQ	libcall_args(DI), R11
     79 	MOVQ	libcall_n(DI), R10
     80 
     81 	get_tls(CX)
     82 	MOVQ	g(CX), BX
     83 	MOVQ	g_m(BX), BX
     84 	MOVQ	m_perrno(BX), DX
     85 	CMPQ	DX, $0
     86 	JEQ	skiperrno1
     87 	MOVL	$0, 0(DX)
     88 
     89 skiperrno1:
     90 	CMPQ	R11, $0
     91 	JEQ	skipargs
     92 	// Load 6 args into correspondent registers.
     93 	MOVQ	0(R11), DI
     94 	MOVQ	8(R11), SI
     95 	MOVQ	16(R11), DX
     96 	MOVQ	24(R11), CX
     97 	MOVQ	32(R11), R8
     98 	MOVQ	40(R11), R9
     99 skipargs:
    100 
    101 	// Call SysV function
    102 	CALL	AX
    103 
    104 	// Return result
    105 	POPQ	DI
    106 	MOVQ	AX, libcall_r1(DI)
    107 	MOVQ	DX, libcall_r2(DI)
    108 
    109 	get_tls(CX)
    110 	MOVQ	g(CX), BX
    111 	MOVQ	g_m(BX), BX
    112 	MOVQ	m_perrno(BX), AX
    113 	CMPQ	AX, $0
    114 	JEQ	skiperrno2
    115 	MOVL	0(AX), AX
    116 	MOVQ	AX, libcall_err(DI)
    117 
    118 skiperrno2:
    119 	RET
    120 
    121 // uint32 tstart_sysvicall(M *newm);
    122 TEXT runtimetstart_sysvicall(SB),NOSPLIT,$0
    123 	// DI contains first arg newm
    124 	MOVQ	m_g0(DI), DX		// g
    125 
    126 	// Make TLS entries point at g and m.
    127 	get_tls(BX)
    128 	MOVQ	DX, g(BX)
    129 	MOVQ	DI, g_m(DX)
    130 
    131 	// Layout new m scheduler stack on os stack.
    132 	MOVQ	SP, AX
    133 	MOVQ	AX, (g_stack+stack_hi)(DX)
    134 	SUBQ	$(0x100000), AX		// stack size
    135 	MOVQ	AX, (g_stack+stack_lo)(DX)
    136 	ADDQ	$const__StackGuard, AX
    137 	MOVQ	AX, g_stackguard0(DX)
    138 	MOVQ	AX, g_stackguard1(DX)
    139 
    140 	// Someday the convention will be D is always cleared.
    141 	CLD
    142 
    143 	CALL	runtimestackcheck(SB)	// clobbers AX,CX
    144 	CALL	runtimemstart(SB)
    145 
    146 	XORL	AX, AX			// return 0 == success
    147 	MOVL	AX, ret+8(FP)
    148 	RET
    149 
    150 // Careful, this is called by __sighndlr, a libc function. We must preserve
    151 // registers as per AMD 64 ABI.
    152 TEXT runtimesigtramp(SB),NOSPLIT,$0
    153 	// Note that we are executing on altsigstack here, so we have
    154 	// more stack available than NOSPLIT would have us believe.
    155 	// To defeat the linker, we make our own stack frame with
    156 	// more space:
    157 	SUBQ    $184, SP
    158 
    159 	// save registers
    160 	MOVQ    BX, 32(SP)
    161 	MOVQ    BP, 40(SP)
    162 	MOVQ	R12, 48(SP)
    163 	MOVQ	R13, 56(SP)
    164 	MOVQ	R14, 64(SP)
    165 	MOVQ	R15, 72(SP)
    166 
    167 	get_tls(BX)
    168 	// check that g exists
    169 	MOVQ	g(BX), R10
    170 	CMPQ	R10, $0
    171 	JNE	allgood
    172 	MOVQ	DI, 0(SP)
    173 	MOVQ	$runtimebadsignal(SB), AX
    174 	CALL	AX
    175 	JMP	exit
    176 
    177 allgood:
    178 	// save g
    179 	MOVQ	R10, 80(SP)
    180 
    181 	// Save m->libcall and m->scratch. We need to do this because we
    182 	// might get interrupted by a signal in runtimeasmcgocall.
    183 
    184 	// save m->libcall
    185 	MOVQ	g_m(R10), BP
    186 	LEAQ	m_libcall(BP), R11
    187 	MOVQ	libcall_fn(R11), R10
    188 	MOVQ	R10, 88(SP)
    189 	MOVQ	libcall_args(R11), R10
    190 	MOVQ	R10, 96(SP)
    191 	MOVQ	libcall_n(R11), R10
    192 	MOVQ	R10, 104(SP)
    193 	MOVQ    libcall_r1(R11), R10
    194 	MOVQ    R10, 168(SP)
    195 	MOVQ    libcall_r2(R11), R10
    196 	MOVQ    R10, 176(SP)
    197 
    198 	// save m->scratch
    199 	LEAQ	m_scratch(BP), R11
    200 	MOVQ	0(R11), R10
    201 	MOVQ	R10, 112(SP)
    202 	MOVQ	8(R11), R10
    203 	MOVQ	R10, 120(SP)
    204 	MOVQ	16(R11), R10
    205 	MOVQ	R10, 128(SP)
    206 	MOVQ	24(R11), R10
    207 	MOVQ	R10, 136(SP)
    208 	MOVQ	32(R11), R10
    209 	MOVQ	R10, 144(SP)
    210 	MOVQ	40(R11), R10
    211 	MOVQ	R10, 152(SP)
    212 
    213 	// save errno, it might be EINTR; stuff we do here might reset it.
    214 	MOVQ	m_perrno(BP), R10
    215 	MOVL	0(R10), R10
    216 	MOVQ	R10, 160(SP)
    217 
    218 	MOVQ	g(BX), R10
    219 	// g = m->gsignal
    220 	MOVQ	m_gsignal(BP), BP
    221 	MOVQ	BP, g(BX)
    222 
    223 	// prepare call
    224 	MOVQ	DI, 0(SP)
    225 	MOVQ	SI, 8(SP)
    226 	MOVQ	DX, 16(SP)
    227 	MOVQ	R10, 24(SP)
    228 	CALL	runtimesighandler(SB)
    229 
    230 	get_tls(BX)
    231 	MOVQ	g(BX), BP
    232 	MOVQ	g_m(BP), BP
    233 	// restore libcall
    234 	LEAQ	m_libcall(BP), R11
    235 	MOVQ	88(SP), R10
    236 	MOVQ	R10, libcall_fn(R11)
    237 	MOVQ	96(SP), R10
    238 	MOVQ	R10, libcall_args(R11)
    239 	MOVQ	104(SP), R10
    240 	MOVQ	R10, libcall_n(R11)
    241 	MOVQ    168(SP), R10
    242 	MOVQ    R10, libcall_r1(R11)
    243 	MOVQ    176(SP), R10
    244 	MOVQ    R10, libcall_r2(R11)
    245 
    246 	// restore scratch
    247 	LEAQ	m_scratch(BP), R11
    248 	MOVQ	112(SP), R10
    249 	MOVQ	R10, 0(R11)
    250 	MOVQ	120(SP), R10
    251 	MOVQ	R10, 8(R11)
    252 	MOVQ	128(SP), R10
    253 	MOVQ	R10, 16(R11)
    254 	MOVQ	136(SP), R10
    255 	MOVQ	R10, 24(R11)
    256 	MOVQ	144(SP), R10
    257 	MOVQ	R10, 32(R11)
    258 	MOVQ	152(SP), R10
    259 	MOVQ	R10, 40(R11)
    260 
    261 	// restore errno
    262 	MOVQ	m_perrno(BP), R11
    263 	MOVQ	160(SP), R10
    264 	MOVL	R10, 0(R11)
    265 
    266 	// restore g
    267 	MOVQ	80(SP), R10
    268 	MOVQ	R10, g(BX)
    269 
    270 exit:
    271 	// restore registers
    272 	MOVQ	32(SP), BX
    273 	MOVQ	40(SP), BP
    274 	MOVQ	48(SP), R12
    275 	MOVQ	56(SP), R13
    276 	MOVQ	64(SP), R14
    277 	MOVQ	72(SP), R15
    278 
    279 	ADDQ    $184, SP
    280 	RET
    281 
    282 // Called from runtimeusleep (Go). Can be called on Go stack, on OS stack,
    283 // can also be called in cgo callback path without a g->m.
    284 TEXT runtimeusleep1(SB),NOSPLIT,$0
    285 	MOVL	usec+0(FP), DI
    286 	MOVQ	$runtimeusleep2(SB), AX // to hide from 6l
    287 
    288 	// Execute call on m->g0.
    289 	get_tls(R15)
    290 	CMPQ	R15, $0
    291 	JE	noswitch
    292 
    293 	MOVQ	g(R15), R13
    294 	CMPQ	R13, $0
    295 	JE	noswitch
    296 	MOVQ	g_m(R13), R13
    297 	CMPQ	R13, $0
    298 	JE	noswitch
    299 	// TODO(aram): do something about the cpu profiler here.
    300 
    301 	MOVQ	m_g0(R13), R14
    302 	CMPQ	g(R15), R14
    303 	JNE	switch
    304 	// executing on m->g0 already
    305 	CALL	AX
    306 	RET
    307 
    308 switch:
    309 	// Switch to m->g0 stack and back.
    310 	MOVQ	(g_sched+gobuf_sp)(R14), R14
    311 	MOVQ	SP, -8(R14)
    312 	LEAQ	-8(R14), SP
    313 	CALL	AX
    314 	MOVQ	0(SP), SP
    315 	RET
    316 
    317 noswitch:
    318 	// Not a Go-managed thread. Do not switch stack.
    319 	CALL	AX
    320 	RET
    321 
    322 // Runs on OS stack. duration (in s units) is in DI.
    323 TEXT runtimeusleep2(SB),NOSPLIT,$0
    324 	LEAQ	libc_usleep(SB), AX
    325 	CALL	AX
    326 	RET
    327 
    328 // Runs on OS stack, called from runtimeosyield.
    329 TEXT runtimeosyield1(SB),NOSPLIT,$0
    330 	LEAQ	libc_sched_yield(SB), AX
    331 	CALL	AX
    332 	RET
    333 
    334 // func now() (sec int64, nsec int32)
    335 TEXT timenow(SB),NOSPLIT,$8-12
    336 	CALL	runtimenanotime(SB)
    337 	MOVQ	0(SP), AX
    338 
    339 	// generated code for
    340 	//	func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
    341 	// adapted to reduce duplication
    342 	MOVQ	AX, CX
    343 	MOVQ	$1360296554856532783, AX
    344 	MULQ	CX
    345 	ADDQ	CX, DX
    346 	RCRQ	$1, DX
    347 	SHRQ	$29, DX
    348 	MOVQ	DX, sec+0(FP)
    349 	IMULQ	$1000000000, DX
    350 	SUBQ	DX, CX
    351 	MOVL	CX, nsec+8(FP)
    352 	RET
    353