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 m->libcall and m->scratch. We need to do this because we
    187 	// might get interrupted by a signal in runtimeasmcgocall.
    188 
    189 	// save m->libcall
    190 	MOVQ	g_m(R10), BP
    191 	LEAQ	m_libcall(BP), R11
    192 	MOVQ	libcall_fn(R11), R10
    193 	MOVQ	R10, 88(SP)
    194 	MOVQ	libcall_args(R11), R10
    195 	MOVQ	R10, 96(SP)
    196 	MOVQ	libcall_n(R11), R10
    197 	MOVQ	R10, 104(SP)
    198 	MOVQ    libcall_r1(R11), R10
    199 	MOVQ    R10, 168(SP)
    200 	MOVQ    libcall_r2(R11), R10
    201 	MOVQ    R10, 176(SP)
    202 
    203 	// save m->scratch
    204 	LEAQ	(m_mOS+mOS_scratch)(BP), R11
    205 	MOVQ	0(R11), R10
    206 	MOVQ	R10, 112(SP)
    207 	MOVQ	8(R11), R10
    208 	MOVQ	R10, 120(SP)
    209 	MOVQ	16(R11), R10
    210 	MOVQ	R10, 128(SP)
    211 	MOVQ	24(R11), R10
    212 	MOVQ	R10, 136(SP)
    213 	MOVQ	32(R11), R10
    214 	MOVQ	R10, 144(SP)
    215 	MOVQ	40(R11), R10
    216 	MOVQ	R10, 152(SP)
    217 
    218 	// save errno, it might be EINTR; stuff we do here might reset it.
    219 	MOVQ	(m_mOS+mOS_perrno)(BP), R10
    220 	MOVL	0(R10), R10
    221 	MOVQ	R10, 160(SP)
    222 
    223 	// prepare call
    224 	MOVQ	DI, 0(SP)
    225 	MOVQ	SI, 8(SP)
    226 	MOVQ	DX, 16(SP)
    227 	CALL	runtimesigtrampgo(SB)
    228 
    229 	get_tls(BX)
    230 	MOVQ	g(BX), BP
    231 	MOVQ	g_m(BP), BP
    232 	// restore libcall
    233 	LEAQ	m_libcall(BP), R11
    234 	MOVQ	88(SP), R10
    235 	MOVQ	R10, libcall_fn(R11)
    236 	MOVQ	96(SP), R10
    237 	MOVQ	R10, libcall_args(R11)
    238 	MOVQ	104(SP), R10
    239 	MOVQ	R10, libcall_n(R11)
    240 	MOVQ    168(SP), R10
    241 	MOVQ    R10, libcall_r1(R11)
    242 	MOVQ    176(SP), R10
    243 	MOVQ    R10, libcall_r2(R11)
    244 
    245 	// restore scratch
    246 	LEAQ	(m_mOS+mOS_scratch)(BP), R11
    247 	MOVQ	112(SP), R10
    248 	MOVQ	R10, 0(R11)
    249 	MOVQ	120(SP), R10
    250 	MOVQ	R10, 8(R11)
    251 	MOVQ	128(SP), R10
    252 	MOVQ	R10, 16(R11)
    253 	MOVQ	136(SP), R10
    254 	MOVQ	R10, 24(R11)
    255 	MOVQ	144(SP), R10
    256 	MOVQ	R10, 32(R11)
    257 	MOVQ	152(SP), R10
    258 	MOVQ	R10, 40(R11)
    259 
    260 	// restore errno
    261 	MOVQ	(m_mOS+mOS_perrno)(BP), R11
    262 	MOVQ	160(SP), R10
    263 	MOVL	R10, 0(R11)
    264 
    265 exit:
    266 	// restore registers
    267 	MOVQ	32(SP), BX
    268 	MOVQ	40(SP), BP
    269 	MOVQ	48(SP), R12
    270 	MOVQ	56(SP), R13
    271 	MOVQ	64(SP), R14
    272 	MOVQ	72(SP), R15
    273 
    274 	ADDQ    $184, SP
    275 	RET
    276 
    277 TEXT runtimesigfwd(SB),NOSPLIT,$0-32
    278 	MOVQ	fn+0(FP),    AX
    279 	MOVL	sig+8(FP),   DI
    280 	MOVQ	info+16(FP), SI
    281 	MOVQ	ctx+24(FP),  DX
    282 	PUSHQ	BP
    283 	MOVQ	SP, BP
    284 	ANDQ	$~15, SP     // alignment for x86_64 ABI
    285 	CALL	AX
    286 	MOVQ	BP, SP
    287 	POPQ	BP
    288 	RET
    289 
    290 // Called from runtimeusleep (Go). Can be called on Go stack, on OS stack,
    291 // can also be called in cgo callback path without a g->m.
    292 TEXT runtimeusleep1(SB),NOSPLIT,$0
    293 	MOVL	usec+0(FP), DI
    294 	MOVQ	$runtimeusleep2(SB), AX // to hide from 6l
    295 
    296 	// Execute call on m->g0.
    297 	get_tls(R15)
    298 	CMPQ	R15, $0
    299 	JE	noswitch
    300 
    301 	MOVQ	g(R15), R13
    302 	CMPQ	R13, $0
    303 	JE	noswitch
    304 	MOVQ	g_m(R13), R13
    305 	CMPQ	R13, $0
    306 	JE	noswitch
    307 	// TODO(aram): do something about the cpu profiler here.
    308 
    309 	MOVQ	m_g0(R13), R14
    310 	CMPQ	g(R15), R14
    311 	JNE	switch
    312 	// executing on m->g0 already
    313 	CALL	AX
    314 	RET
    315 
    316 switch:
    317 	// Switch to m->g0 stack and back.
    318 	MOVQ	(g_sched+gobuf_sp)(R14), R14
    319 	MOVQ	SP, -8(R14)
    320 	LEAQ	-8(R14), SP
    321 	CALL	AX
    322 	MOVQ	0(SP), SP
    323 	RET
    324 
    325 noswitch:
    326 	// Not a Go-managed thread. Do not switch stack.
    327 	CALL	AX
    328 	RET
    329 
    330 // Runs on OS stack. duration (in s units) is in DI.
    331 TEXT runtimeusleep2(SB),NOSPLIT,$0
    332 	LEAQ	libc_usleep(SB), AX
    333 	CALL	AX
    334 	RET
    335 
    336 // Runs on OS stack, called from runtimeosyield.
    337 TEXT runtimeosyield1(SB),NOSPLIT,$0
    338 	LEAQ	libc_sched_yield(SB), AX
    339 	CALL	AX
    340 	RET
    341 
    342 // func walltime() (sec int64, nsec int32)
    343 TEXT runtimewalltime(SB),NOSPLIT,$8-12
    344 	CALL	runtimenanotime(SB)
    345 	MOVQ	0(SP), AX
    346 
    347 	// generated code for
    348 	//	func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
    349 	// adapted to reduce duplication
    350 	MOVQ	AX, CX
    351 	MOVQ	$1360296554856532783, AX
    352 	MULQ	CX
    353 	ADDQ	CX, DX
    354 	RCRQ	$1, DX
    355 	SHRQ	$29, DX
    356 	MOVQ	DX, sec+0(FP)
    357 	IMULQ	$1000000000, DX
    358 	SUBQ	DX, CX
    359 	MOVL	CX, nsec+8(FP)
    360 	RET
    361