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