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_mOS+mOS_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 aligned
     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 	CMPQ	BX, $0
     84 	JEQ	skiperrno1
     85 	MOVQ	g_m(BX), BX
     86 	MOVQ	(m_mOS+mOS_perrno)(BX), DX
     87 	CMPQ	DX, $0
     88 	JEQ	skiperrno1
     89 	MOVL	$0, 0(DX)
     90 
     91 skiperrno1:
     92 	CMPQ	R11, $0
     93 	JEQ	skipargs
     94 	// Load 6 args into correspondent registers.
     95 	MOVQ	0(R11), DI
     96 	MOVQ	8(R11), SI
     97 	MOVQ	16(R11), DX
     98 	MOVQ	24(R11), CX
     99 	MOVQ	32(R11), R8
    100 	MOVQ	40(R11), R9
    101 skipargs:
    102 
    103 	// Call SysV function
    104 	CALL	AX
    105 
    106 	// Return result
    107 	POPQ	DI
    108 	MOVQ	AX, libcall_r1(DI)
    109 	MOVQ	DX, libcall_r2(DI)
    110 
    111 	get_tls(CX)
    112 	MOVQ	g(CX), BX
    113 	CMPQ	BX, $0
    114 	JEQ	skiperrno2
    115 	MOVQ	g_m(BX), BX
    116 	MOVQ	(m_mOS+mOS_perrno)(BX), AX
    117 	CMPQ	AX, $0
    118 	JEQ	skiperrno2
    119 	MOVL	0(AX), AX
    120 	MOVQ	AX, libcall_err(DI)
    121 
    122 skiperrno2:
    123 	RET
    124 
    125 // uint32 tstart_sysvicall(M *newm);
    126 TEXT runtimetstart_sysvicall(SB),NOSPLIT,$0
    127 	// DI contains first arg newm
    128 	MOVQ	m_g0(DI), DX		// g
    129 
    130 	// Make TLS entries point at g and m.
    131 	get_tls(BX)
    132 	MOVQ	DX, g(BX)
    133 	MOVQ	DI, g_m(DX)
    134 
    135 	// Layout new m scheduler stack on os stack.
    136 	MOVQ	SP, AX
    137 	MOVQ	AX, (g_stack+stack_hi)(DX)
    138 	SUBQ	$(0x100000), AX		// stack size
    139 	MOVQ	AX, (g_stack+stack_lo)(DX)
    140 	ADDQ	$const__StackGuard, AX
    141 	MOVQ	AX, g_stackguard0(DX)
    142 	MOVQ	AX, g_stackguard1(DX)
    143 
    144 	// Someday the convention will be D is always cleared.
    145 	CLD
    146 
    147 	CALL	runtimestackcheck(SB)	// clobbers AX,CX
    148 	CALL	runtimemstart(SB)
    149 
    150 	XORL	AX, AX			// return 0 == success
    151 	MOVL	AX, ret+8(FP)
    152 	RET
    153 
    154 // Careful, this is called by __sighndlr, a libc function. We must preserve
    155 // registers as per AMD 64 ABI.
    156 TEXT runtimesigtramp(SB),NOSPLIT,$0
    157 	// Note that we are executing on altsigstack here, so we have
    158 	// more stack available than NOSPLIT would have us believe.
    159 	// To defeat the linker, we make our own stack frame with
    160 	// more space:
    161 	SUBQ    $184, SP
    162 
    163 	// save registers
    164 	MOVQ    BX, 32(SP)
    165 	MOVQ    BP, 40(SP)
    166 	MOVQ	R12, 48(SP)
    167 	MOVQ	R13, 56(SP)
    168 	MOVQ	R14, 64(SP)
    169 	MOVQ	R15, 72(SP)
    170 
    171 	get_tls(BX)
    172 	// check that g exists
    173 	MOVQ	g(BX), R10
    174 	CMPQ	R10, $0
    175 	JNE	allgood
    176 	MOVQ	SI, 80(SP)
    177 	MOVQ	DX, 88(SP)
    178 	LEAQ	80(SP), AX
    179 	MOVQ	DI, 0(SP)
    180 	MOVQ	AX, 8(SP)
    181 	MOVQ	$runtimebadsignal(SB), AX
    182 	CALL	AX
    183 	JMP	exit
    184 
    185 allgood:
    186 	// save g
    187 	MOVQ	R10, 80(SP)
    188 
    189 	// Save m->libcall and m->scratch. We need to do this because we
    190 	// might get interrupted by a signal in runtimeasmcgocall.
    191 
    192 	// save m->libcall
    193 	MOVQ	g_m(R10), BP
    194 	LEAQ	m_libcall(BP), R11
    195 	MOVQ	libcall_fn(R11), R10
    196 	MOVQ	R10, 88(SP)
    197 	MOVQ	libcall_args(R11), R10
    198 	MOVQ	R10, 96(SP)
    199 	MOVQ	libcall_n(R11), R10
    200 	MOVQ	R10, 104(SP)
    201 	MOVQ    libcall_r1(R11), R10
    202 	MOVQ    R10, 168(SP)
    203 	MOVQ    libcall_r2(R11), R10
    204 	MOVQ    R10, 176(SP)
    205 
    206 	// save m->scratch
    207 	LEAQ	(m_mOS+mOS_scratch)(BP), R11
    208 	MOVQ	0(R11), R10
    209 	MOVQ	R10, 112(SP)
    210 	MOVQ	8(R11), R10
    211 	MOVQ	R10, 120(SP)
    212 	MOVQ	16(R11), R10
    213 	MOVQ	R10, 128(SP)
    214 	MOVQ	24(R11), R10
    215 	MOVQ	R10, 136(SP)
    216 	MOVQ	32(R11), R10
    217 	MOVQ	R10, 144(SP)
    218 	MOVQ	40(R11), R10
    219 	MOVQ	R10, 152(SP)
    220 
    221 	// save errno, it might be EINTR; stuff we do here might reset it.
    222 	MOVQ	(m_mOS+mOS_perrno)(BP), R10
    223 	MOVL	0(R10), R10
    224 	MOVQ	R10, 160(SP)
    225 
    226 	MOVQ	g(BX), R10
    227 	// g = m->gsignal
    228 	MOVQ	m_gsignal(BP), BP
    229 	MOVQ	BP, g(BX)
    230 
    231 	// TODO: If current SP is not in gsignal.stack, then adjust.
    232 
    233 	// prepare call
    234 	MOVQ	DI, 0(SP)
    235 	MOVQ	SI, 8(SP)
    236 	MOVQ	DX, 16(SP)
    237 	MOVQ	R10, 24(SP)
    238 	CALL	runtimesighandler(SB)
    239 
    240 	get_tls(BX)
    241 	MOVQ	g(BX), BP
    242 	MOVQ	g_m(BP), BP
    243 	// restore libcall
    244 	LEAQ	m_libcall(BP), R11
    245 	MOVQ	88(SP), R10
    246 	MOVQ	R10, libcall_fn(R11)
    247 	MOVQ	96(SP), R10
    248 	MOVQ	R10, libcall_args(R11)
    249 	MOVQ	104(SP), R10
    250 	MOVQ	R10, libcall_n(R11)
    251 	MOVQ    168(SP), R10
    252 	MOVQ    R10, libcall_r1(R11)
    253 	MOVQ    176(SP), R10
    254 	MOVQ    R10, libcall_r2(R11)
    255 
    256 	// restore scratch
    257 	LEAQ	(m_mOS+mOS_scratch)(BP), R11
    258 	MOVQ	112(SP), R10
    259 	MOVQ	R10, 0(R11)
    260 	MOVQ	120(SP), R10
    261 	MOVQ	R10, 8(R11)
    262 	MOVQ	128(SP), R10
    263 	MOVQ	R10, 16(R11)
    264 	MOVQ	136(SP), R10
    265 	MOVQ	R10, 24(R11)
    266 	MOVQ	144(SP), R10
    267 	MOVQ	R10, 32(R11)
    268 	MOVQ	152(SP), R10
    269 	MOVQ	R10, 40(R11)
    270 
    271 	// restore errno
    272 	MOVQ	(m_mOS+mOS_perrno)(BP), R11
    273 	MOVQ	160(SP), R10
    274 	MOVL	R10, 0(R11)
    275 
    276 	// restore g
    277 	MOVQ	80(SP), R10
    278 	MOVQ	R10, g(BX)
    279 
    280 exit:
    281 	// restore registers
    282 	MOVQ	32(SP), BX
    283 	MOVQ	40(SP), BP
    284 	MOVQ	48(SP), R12
    285 	MOVQ	56(SP), R13
    286 	MOVQ	64(SP), R14
    287 	MOVQ	72(SP), R15
    288 
    289 	ADDQ    $184, SP
    290 	RET
    291 
    292 TEXT runtimesigfwd(SB),NOSPLIT,$0-32
    293 	MOVQ	fn+0(FP),    AX
    294 	MOVL	sig+8(FP),   DI
    295 	MOVQ	info+16(FP), SI
    296 	MOVQ	ctx+24(FP),  DX
    297 	PUSHQ	BP
    298 	MOVQ	SP, BP
    299 	ANDQ	$~15, SP     // alignment for x86_64 ABI
    300 	CALL	AX
    301 	MOVQ	BP, SP
    302 	POPQ	BP
    303 	RET
    304 
    305 // Called from runtimeusleep (Go). Can be called on Go stack, on OS stack,
    306 // can also be called in cgo callback path without a g->m.
    307 TEXT runtimeusleep1(SB),NOSPLIT,$0
    308 	MOVL	usec+0(FP), DI
    309 	MOVQ	$runtimeusleep2(SB), AX // to hide from 6l
    310 
    311 	// Execute call on m->g0.
    312 	get_tls(R15)
    313 	CMPQ	R15, $0
    314 	JE	noswitch
    315 
    316 	MOVQ	g(R15), R13
    317 	CMPQ	R13, $0
    318 	JE	noswitch
    319 	MOVQ	g_m(R13), R13
    320 	CMPQ	R13, $0
    321 	JE	noswitch
    322 	// TODO(aram): do something about the cpu profiler here.
    323 
    324 	MOVQ	m_g0(R13), R14
    325 	CMPQ	g(R15), R14
    326 	JNE	switch
    327 	// executing on m->g0 already
    328 	CALL	AX
    329 	RET
    330 
    331 switch:
    332 	// Switch to m->g0 stack and back.
    333 	MOVQ	(g_sched+gobuf_sp)(R14), R14
    334 	MOVQ	SP, -8(R14)
    335 	LEAQ	-8(R14), SP
    336 	CALL	AX
    337 	MOVQ	0(SP), SP
    338 	RET
    339 
    340 noswitch:
    341 	// Not a Go-managed thread. Do not switch stack.
    342 	CALL	AX
    343 	RET
    344 
    345 // Runs on OS stack. duration (in s units) is in DI.
    346 TEXT runtimeusleep2(SB),NOSPLIT,$0
    347 	LEAQ	libc_usleep(SB), AX
    348 	CALL	AX
    349 	RET
    350 
    351 // Runs on OS stack, called from runtimeosyield.
    352 TEXT runtimeosyield1(SB),NOSPLIT,$0
    353 	LEAQ	libc_sched_yield(SB), AX
    354 	CALL	AX
    355 	RET
    356 
    357 // func now() (sec int64, nsec int32)
    358 TEXT timenow(SB),NOSPLIT,$8-12
    359 	CALL	runtimenanotime(SB)
    360 	MOVQ	0(SP), AX
    361 
    362 	// generated code for
    363 	//	func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
    364 	// adapted to reduce duplication
    365 	MOVQ	AX, CX
    366 	MOVQ	$1360296554856532783, AX
    367 	MULQ	CX
    368 	ADDQ	CX, DX
    369 	RCRQ	$1, DX
    370 	SHRQ	$29, DX
    371 	MOVQ	DX, sec+0(FP)
    372 	IMULQ	$1000000000, DX
    373 	SUBQ	DX, CX
    374 	MOVL	CX, nsec+8(FP)
    375 	RET
    376