Home | History | Annotate | Download | only in runtime
      1 // Copyright 2013 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 #include "go_asm.h"
      6 #include "go_tls.h"
      7 #include "textflag.h"
      8 #include "syscall_nacl.h"
      9 
     10 #define NACL_SYSCALL(code) \
     11 	MOVL $(0x10000 + ((code)<<5)), AX; CALL AX
     12 
     13 TEXT runtimesettls(SB),NOSPLIT,$0
     14 	MOVL	DI, TLS // really BP
     15 	RET
     16 
     17 TEXT runtimeexit(SB),NOSPLIT,$0
     18 	MOVL code+0(FP), DI
     19 	NACL_SYSCALL(SYS_exit)
     20 	RET
     21 
     22 // func exitThread(wait *uint32)
     23 TEXT runtimeexitThread(SB),NOSPLIT,$0-4
     24 	MOVL wait+0(FP), DI
     25 	// SYS_thread_exit will clear *wait when the stack is free.
     26 	NACL_SYSCALL(SYS_thread_exit)
     27 	JMP 0(PC)
     28 
     29 TEXT runtimeopen(SB),NOSPLIT,$0
     30 	MOVL name+0(FP), DI
     31 	MOVL mode+4(FP), SI
     32 	MOVL perm+8(FP), DX
     33 	NACL_SYSCALL(SYS_open)
     34 	MOVL AX, ret+16(FP)
     35 	RET
     36 
     37 TEXT runtimeclosefd(SB),NOSPLIT,$0
     38 	MOVL fd+0(FP), DI
     39 	NACL_SYSCALL(SYS_close)
     40 	MOVL AX, ret+8(FP)
     41 	RET
     42 
     43 TEXT runtimeread(SB),NOSPLIT,$0
     44 	MOVL fd+0(FP), DI
     45 	MOVL p+4(FP), SI
     46 	MOVL n+8(FP), DX
     47 	NACL_SYSCALL(SYS_read)
     48 	MOVL AX, ret+16(FP)
     49 	RET
     50 
     51 TEXT syscallnaclWrite(SB), NOSPLIT, $24-20
     52 	MOVL arg1+0(FP), DI
     53 	MOVL arg2+4(FP), SI
     54 	MOVL arg3+8(FP), DX
     55 	MOVL DI, 0(SP)
     56 	MOVL SI, 4(SP)
     57 	MOVL DX, 8(SP)
     58 	CALL runtimewrite(SB)
     59 	MOVL 16(SP), AX
     60 	MOVL AX, ret+16(FP)
     61 	RET
     62 
     63 TEXT runtimewrite(SB),NOSPLIT,$16-20
     64 	// If using fake time and writing to stdout or stderr,
     65 	// emit playback header before actual data.
     66 	MOVQ runtimefaketime(SB), AX
     67 	CMPQ AX, $0
     68 	JEQ write
     69 	MOVL fd+0(FP), DI
     70 	CMPL DI, $1
     71 	JEQ playback
     72 	CMPL DI, $2
     73 	JEQ playback
     74 
     75 write:
     76 	// Ordinary write.
     77 	MOVL fd+0(FP), DI
     78 	MOVL p+4(FP), SI
     79 	MOVL n+8(FP), DX
     80 	NACL_SYSCALL(SYS_write)
     81 	MOVL	AX, ret+16(FP)
     82 	RET
     83 
     84 	// Write with playback header.
     85 	// First, lock to avoid interleaving writes.
     86 playback:
     87 	MOVL $1, BX
     88 	XCHGL	runtimewritelock(SB), BX
     89 	CMPL BX, $0
     90 	JNE playback
     91 
     92 	// Playback header: 0 0 P B <8-byte time> <4-byte data length>
     93 	MOVL $(('B'<<24) | ('P'<<16)), 0(SP)
     94 	BSWAPQ AX
     95 	MOVQ AX, 4(SP)
     96 	MOVL n+8(FP), DX
     97 	BSWAPL DX
     98 	MOVL DX, 12(SP)
     99 	MOVL fd+0(FP), DI
    100 	MOVL SP, SI
    101 	MOVL $16, DX
    102 	NACL_SYSCALL(SYS_write)
    103 
    104 	// Write actual data.
    105 	MOVL fd+0(FP), DI
    106 	MOVL p+4(FP), SI
    107 	MOVL n+8(FP), DX
    108 	NACL_SYSCALL(SYS_write)
    109 
    110 	// Unlock.
    111 	MOVL	$0, runtimewritelock(SB)
    112 
    113 	MOVL	AX, ret+16(FP)
    114 	RET
    115 
    116 TEXT runtimenacl_exception_stack(SB),NOSPLIT,$0
    117 	MOVL p+0(FP), DI
    118 	MOVL size+4(FP), SI
    119 	NACL_SYSCALL(SYS_exception_stack)
    120 	MOVL AX, ret+8(FP)
    121 	RET
    122 
    123 TEXT runtimenacl_exception_handler(SB),NOSPLIT,$0
    124 	MOVL fn+0(FP), DI
    125 	MOVL arg+4(FP), SI
    126 	NACL_SYSCALL(SYS_exception_handler)
    127 	MOVL AX, ret+8(FP)
    128 	RET
    129 
    130 TEXT runtimenacl_sem_create(SB),NOSPLIT,$0
    131 	MOVL flag+0(FP), DI
    132 	NACL_SYSCALL(SYS_sem_create)
    133 	MOVL AX, ret+8(FP)
    134 	RET
    135 
    136 TEXT runtimenacl_sem_wait(SB),NOSPLIT,$0
    137 	MOVL sem+0(FP), DI
    138 	NACL_SYSCALL(SYS_sem_wait)
    139 	MOVL AX, ret+8(FP)
    140 	RET
    141 
    142 TEXT runtimenacl_sem_post(SB),NOSPLIT,$0
    143 	MOVL sem+0(FP), DI
    144 	NACL_SYSCALL(SYS_sem_post)
    145 	MOVL AX, ret+8(FP)
    146 	RET
    147 
    148 TEXT runtimenacl_mutex_create(SB),NOSPLIT,$0
    149 	MOVL flag+0(FP), DI
    150 	NACL_SYSCALL(SYS_mutex_create)
    151 	MOVL AX, ret+8(FP)
    152 	RET
    153 
    154 TEXT runtimenacl_mutex_lock(SB),NOSPLIT,$0
    155 	MOVL mutex+0(FP), DI
    156 	NACL_SYSCALL(SYS_mutex_lock)
    157 	MOVL AX, ret+8(FP)
    158 	RET
    159 
    160 TEXT runtimenacl_mutex_trylock(SB),NOSPLIT,$0
    161 	MOVL mutex+0(FP), DI
    162 	NACL_SYSCALL(SYS_mutex_trylock)
    163 	MOVL AX, ret+8(FP)
    164 	RET
    165 
    166 TEXT runtimenacl_mutex_unlock(SB),NOSPLIT,$0
    167 	MOVL mutex+0(FP), DI
    168 	NACL_SYSCALL(SYS_mutex_unlock)
    169 	MOVL AX, ret+8(FP)
    170 	RET
    171 
    172 TEXT runtimenacl_cond_create(SB),NOSPLIT,$0
    173 	MOVL flag+0(FP), DI
    174 	NACL_SYSCALL(SYS_cond_create)
    175 	MOVL AX, ret+8(FP)
    176 	RET
    177 
    178 TEXT runtimenacl_cond_wait(SB),NOSPLIT,$0
    179 	MOVL cond+0(FP), DI
    180 	MOVL n+4(FP), SI
    181 	NACL_SYSCALL(SYS_cond_wait)
    182 	MOVL AX, ret+8(FP)
    183 	RET
    184 
    185 TEXT runtimenacl_cond_signal(SB),NOSPLIT,$0
    186 	MOVL cond+0(FP), DI
    187 	NACL_SYSCALL(SYS_cond_signal)
    188 	MOVL AX, ret+8(FP)
    189 	RET
    190 
    191 TEXT runtimenacl_cond_broadcast(SB),NOSPLIT,$0
    192 	MOVL cond+0(FP), DI
    193 	NACL_SYSCALL(SYS_cond_broadcast)
    194 	MOVL AX, ret+8(FP)
    195 	RET
    196 
    197 TEXT runtimenacl_cond_timed_wait_abs(SB),NOSPLIT,$0
    198 	MOVL cond+0(FP), DI
    199 	MOVL lock+4(FP), SI
    200 	MOVL ts+8(FP), DX
    201 	NACL_SYSCALL(SYS_cond_timed_wait_abs)
    202 	MOVL AX, ret+16(FP)
    203 	RET
    204 
    205 TEXT runtimenacl_thread_create(SB),NOSPLIT,$0
    206 	MOVL fn+0(FP), DI
    207 	MOVL stk+4(FP), SI
    208 	MOVL tls+8(FP), DX
    209 	MOVL xx+12(FP), CX
    210 	NACL_SYSCALL(SYS_thread_create)
    211 	MOVL AX, ret+16(FP)
    212 	RET
    213 
    214 TEXT runtimemstart_nacl(SB),NOSPLIT,$0
    215 	NACL_SYSCALL(SYS_tls_get)
    216 	SUBL	$8, AX
    217 	MOVL	AX, TLS
    218 	JMP runtimemstart(SB)
    219 
    220 TEXT runtimenacl_nanosleep(SB),NOSPLIT,$0
    221 	MOVL ts+0(FP), DI
    222 	MOVL extra+4(FP), SI
    223 	NACL_SYSCALL(SYS_nanosleep)
    224 	MOVL AX, ret+8(FP)
    225 	RET
    226 
    227 TEXT runtimeosyield(SB),NOSPLIT,$0
    228 	NACL_SYSCALL(SYS_sched_yield)
    229 	RET
    230 
    231 TEXT runtimemmap(SB),NOSPLIT,$8
    232 	MOVL addr+0(FP), DI
    233 	MOVL n+4(FP), SI
    234 	MOVL prot+8(FP), DX
    235 	MOVL flags+12(FP), CX
    236 	MOVL fd+16(FP), R8
    237 	MOVL off+20(FP), AX
    238 	MOVQ AX, 0(SP)
    239 	MOVL SP, R9
    240 	NACL_SYSCALL(SYS_mmap)
    241 	CMPL AX, $-4095
    242 	JNA ok
    243 	NEGL AX
    244 	MOVL	$0, p+24(FP)
    245 	MOVL	AX, err+28(FP)
    246 	RET
    247 ok:
    248 	MOVL	AX, p+24(FP)
    249 	MOVL	$0, err+28(FP)
    250 	RET
    251 
    252 TEXT runtimewalltime(SB),NOSPLIT,$16
    253 	MOVQ runtimefaketime(SB), AX
    254 	CMPQ AX, $0
    255 	JEQ realtime
    256 	MOVQ $0, DX
    257 	MOVQ $1000000000, CX
    258 	DIVQ CX
    259 	MOVQ AX, sec+0(FP)
    260 	MOVL DX, nsec+8(FP)
    261 	RET
    262 realtime:
    263 	MOVL $0, DI // real time clock
    264 	LEAL 0(SP), AX
    265 	MOVL AX, SI // timespec
    266 	NACL_SYSCALL(SYS_clock_gettime)
    267 	MOVL 0(SP), AX // low 32 sec
    268 	MOVL 4(SP), CX // high 32 sec
    269 	MOVL 8(SP), BX // nsec
    270 
    271 	// sec is in AX, nsec in BX
    272 	MOVL	AX, sec_lo+0(FP)
    273 	MOVL	CX, sec_hi+4(FP)
    274 	MOVL	BX, nsec+8(FP)
    275 	RET
    276 
    277 TEXT syscallnow(SB),NOSPLIT,$0
    278 	JMP runtimewalltime(SB)
    279 
    280 TEXT runtimenacl_clock_gettime(SB),NOSPLIT,$0
    281 	MOVL arg1+0(FP), DI
    282 	MOVL arg2+4(FP), SI
    283 	NACL_SYSCALL(SYS_clock_gettime)
    284 	MOVL AX, ret+8(FP)
    285 	RET
    286 
    287 TEXT runtimenanotime(SB),NOSPLIT,$16
    288 	MOVQ runtimefaketime(SB), AX
    289 	CMPQ AX, $0
    290 	JEQ 3(PC)
    291 	MOVQ	AX, ret+0(FP)
    292 	RET
    293 	MOVL $0, DI // real time clock
    294 	LEAL 0(SP), AX
    295 	MOVL AX, SI // timespec
    296 	NACL_SYSCALL(SYS_clock_gettime)
    297 	MOVQ 0(SP), AX // sec
    298 	MOVL 8(SP), DX // nsec
    299 
    300 	// sec is in AX, nsec in DX
    301 	// return nsec in AX
    302 	IMULQ	$1000000000, AX
    303 	ADDQ	DX, AX
    304 	MOVQ	AX, ret+0(FP)
    305 	RET
    306 
    307 TEXT runtimesigtramp(SB),NOSPLIT,$80
    308 	// restore TLS register at time of execution,
    309 	// in case it's been smashed.
    310 	// the TLS register is really BP, but for consistency
    311 	// with non-NaCl systems it is referred to here as TLS.
    312 	// NOTE: Cannot use SYS_tls_get here (like we do in mstart_nacl),
    313 	// because the main thread never calls tls_set.
    314 	LEAL ctxt+0(FP), AX
    315 	MOVL (16*4+5*8)(AX), AX
    316 	MOVL	AX, TLS
    317 
    318 	// check that g exists
    319 	get_tls(CX)
    320 	MOVL	g(CX), DI
    321 
    322 	CMPL	DI, $0
    323 	JEQ	nog
    324 
    325 	// save g
    326 	MOVL	DI, 20(SP)
    327 
    328 	// g = m->gsignal
    329 	MOVL	g_m(DI), BX
    330 	MOVL	m_gsignal(BX), BX
    331 	MOVL	BX, g(CX)
    332 
    333 //JMP debughandler
    334 
    335 	// copy arguments for sighandler
    336 	MOVL	$11, 0(SP) // signal
    337 	MOVL	$0, 4(SP) // siginfo
    338 	LEAL	ctxt+0(FP), AX
    339 	MOVL	AX, 8(SP) // context
    340 	MOVL	DI, 12(SP) // g
    341 
    342 	CALL	runtimesighandler(SB)
    343 
    344 	// restore g
    345 	get_tls(CX)
    346 	MOVL	20(SP), BX
    347 	MOVL	BX, g(CX)
    348 
    349 	// Enable exceptions again.
    350 	NACL_SYSCALL(SYS_exception_clear_flag)
    351 
    352 	// Restore registers as best we can. Impossible to do perfectly.
    353 	// See comment in sys_nacl_386.s for extended rationale.
    354 	LEAL	ctxt+0(FP), SI
    355 	ADDL	$64, SI
    356 	MOVQ	0(SI), AX
    357 	MOVQ	8(SI), CX
    358 	MOVQ	16(SI), DX
    359 	MOVQ	24(SI), BX
    360 	MOVL	32(SI), SP	// MOVL for SP sandboxing
    361 	// 40(SI) is saved BP aka TLS, already restored above
    362 	// 48(SI) is saved SI, never to be seen again
    363 	MOVQ	56(SI), DI
    364 	MOVQ	64(SI), R8
    365 	MOVQ	72(SI), R9
    366 	MOVQ	80(SI), R10
    367 	MOVQ	88(SI), R11
    368 	MOVQ	96(SI), R12
    369 	MOVQ	104(SI), R13
    370 	MOVQ	112(SI), R14
    371 	// 120(SI) is R15, which is owned by Native Client and must not be modified
    372 	MOVQ	128(SI), SI // saved PC
    373 	// 136(SI) is saved EFLAGS, never to be seen again
    374 	JMP	SI
    375 
    376 //debughandler:
    377 	//// print basic information
    378 	//LEAL	ctxt+0(FP), DI
    379 	//MOVL	$runtimesigtrampf(SB), AX
    380 	//MOVL	AX, 0(SP)
    381 	//MOVQ	(16*4+16*8)(DI), BX // rip
    382 	//MOVQ	BX, 8(SP)
    383 	//MOVQ	(16*4+0*8)(DI), BX // rax
    384 	//MOVQ	BX, 16(SP)
    385 	//MOVQ	(16*4+1*8)(DI), BX // rcx
    386 	//MOVQ	BX, 24(SP)
    387 	//MOVQ	(16*4+2*8)(DI), BX // rdx
    388 	//MOVQ	BX, 32(SP)
    389 	//MOVQ	(16*4+3*8)(DI), BX // rbx
    390 	//MOVQ	BX, 40(SP)
    391 	//MOVQ	(16*4+7*8)(DI), BX // rdi
    392 	//MOVQ	BX, 48(SP)
    393 	//MOVQ	(16*4+15*8)(DI), BX // r15
    394 	//MOVQ	BX, 56(SP)
    395 	//MOVQ	(16*4+4*8)(DI), BX // rsp
    396 	//MOVQ	0(BX), BX
    397 	//MOVQ	BX, 64(SP)
    398 	//CALL	runtimeprintf(SB)
    399 	//
    400 	//LEAL	ctxt+0(FP), DI
    401 	//MOVQ	(16*4+16*8)(DI), BX // rip
    402 	//MOVL	BX, 0(SP)
    403 	//MOVQ	(16*4+4*8)(DI), BX // rsp
    404 	//MOVL	BX, 4(SP)
    405 	//MOVL	$0, 8(SP)	// lr
    406 	//get_tls(CX)
    407 	//MOVL	g(CX), BX
    408 	//MOVL	BX, 12(SP)	// gp
    409 	//CALL	runtimetraceback(SB)
    410 
    411 notls:
    412 	MOVL	0, AX
    413 	RET
    414 
    415 nog:
    416 	MOVL	0, AX
    417 	RET
    418 
    419 // cannot do real signal handling yet, because gsignal has not been allocated.
    420 MOVL $1, DI; NACL_SYSCALL(SYS_exit)
    421 
    422 // func getRandomData([]byte)
    423 TEXT runtimegetRandomData(SB),NOSPLIT,$0-12
    424 	MOVL arg_base+0(FP), DI
    425 	MOVL arg_len+4(FP), SI
    426 	NACL_SYSCALL(SYS_get_random_bytes)
    427 	RET
    428 
    429 TEXT runtimenacl_sysinfo(SB),NOSPLIT,$16
    430 /*
    431 	MOVL	di+0(FP), DI
    432 	LEAL	12(DI), BX
    433 	MOVL	8(DI), AX
    434 	ADDL	4(DI), AX
    435 	ADDL	$2, AX
    436 	LEAL	(BX)(AX*4), BX
    437 	MOVL	BX, runtimenacl_irt_query(SB)
    438 auxloop:
    439 	MOVL	0(BX), DX
    440 	CMPL	DX, $0
    441 	JNE	2(PC)
    442 	RET
    443 	CMPL	DX, $32
    444 	JEQ	auxfound
    445 	ADDL	$8, BX
    446 	JMP	auxloop
    447 auxfound:
    448 	MOVL	4(BX), BX
    449 	MOVL	BX, runtimenacl_irt_query(SB)
    450 
    451 	LEAL	runtimenacl_irt_basic_v0_1_str(SB), DI
    452 	LEAL	runtimenacl_irt_basic_v0_1(SB), SI
    453 	MOVL	runtimenacl_irt_basic_v0_1_size(SB), DX
    454 	MOVL	runtimenacl_irt_query(SB), BX
    455 	CALL	BX
    456 
    457 	LEAL	runtimenacl_irt_memory_v0_3_str(SB), DI
    458 	LEAL	runtimenacl_irt_memory_v0_3(SB), SI
    459 	MOVL	runtimenacl_irt_memory_v0_3_size(SB), DX
    460 	MOVL	runtimenacl_irt_query(SB), BX
    461 	CALL	BX
    462 
    463 	LEAL	runtimenacl_irt_thread_v0_1_str(SB), DI
    464 	LEAL	runtimenacl_irt_thread_v0_1(SB), SI
    465 	MOVL	runtimenacl_irt_thread_v0_1_size(SB), DX
    466 	MOVL	runtimenacl_irt_query(SB), BX
    467 	CALL	BX
    468 
    469 	// TODO: Once we have a NaCl SDK with futex syscall support,
    470 	// try switching to futex syscalls and here load the
    471 	// nacl-irt-futex-0.1 table.
    472 */
    473 	RET
    474