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 runtimeexit(SB),NOSPLIT,$4
     14 	MOVL code+0(FP), AX
     15 	MOVL AX, 0(SP)
     16 	NACL_SYSCALL(SYS_exit)
     17 	JMP 0(PC)
     18 
     19 // func exitThread(wait *uint32)
     20 TEXT runtimeexitThread(SB),NOSPLIT,$4-4
     21 	MOVL wait+0(FP), AX
     22 	// SYS_thread_exit will clear *wait when the stack is free.
     23 	MOVL AX, 0(SP)
     24 	NACL_SYSCALL(SYS_thread_exit)
     25 	JMP 0(PC)
     26 
     27 TEXT runtimeopen(SB),NOSPLIT,$12
     28 	MOVL name+0(FP), AX
     29 	MOVL AX, 0(SP)
     30 	MOVL mode+4(FP), AX
     31 	MOVL AX, 4(SP)
     32 	MOVL perm+8(FP), AX
     33 	MOVL AX, 8(SP)
     34 	NACL_SYSCALL(SYS_open)
     35 	MOVL AX, ret+12(FP)
     36 	RET
     37 
     38 TEXT runtimeclosefd(SB),NOSPLIT,$4
     39 	MOVL fd+0(FP), AX
     40 	MOVL AX, 0(SP)
     41 	NACL_SYSCALL(SYS_close)
     42 	MOVL AX, ret+4(FP)
     43 	RET
     44 
     45 TEXT runtimeread(SB),NOSPLIT,$12
     46 	MOVL fd+0(FP), AX
     47 	MOVL AX, 0(SP)
     48 	MOVL p+4(FP), AX
     49 	MOVL AX, 4(SP)
     50 	MOVL n+8(FP), AX
     51 	MOVL AX, 8(SP)
     52 	NACL_SYSCALL(SYS_read)
     53 	MOVL AX, ret+12(FP)
     54 	RET
     55 
     56 TEXT syscallnaclWrite(SB), NOSPLIT, $16-16
     57 	MOVL arg1+0(FP), DI
     58 	MOVL arg2+4(FP), SI
     59 	MOVL arg3+8(FP), DX
     60 	MOVL DI, 0(SP)
     61 	MOVL SI, 4(SP)
     62 	MOVL DX, 8(SP)
     63 	CALL runtimewrite(SB)
     64 	MOVL AX, ret+16(FP)
     65 	RET
     66 
     67 TEXT runtimewrite(SB),NOSPLIT,$12
     68 	MOVL fd+0(FP), AX
     69 	MOVL AX, 0(SP)
     70 	MOVL p+4(FP), AX
     71 	MOVL AX, 4(SP)
     72 	MOVL n+8(FP), AX
     73 	MOVL AX, 8(SP)
     74 	NACL_SYSCALL(SYS_write)
     75 	MOVL AX, ret+12(FP)
     76 	RET
     77 
     78 TEXT runtimenacl_exception_stack(SB),NOSPLIT,$8
     79 	MOVL p+0(FP), AX
     80 	MOVL AX, 0(SP)
     81 	MOVL size+4(FP), AX
     82 	MOVL AX, 4(SP)
     83 	NACL_SYSCALL(SYS_exception_stack)
     84 	MOVL AX, ret+8(FP)
     85 	RET
     86 
     87 TEXT runtimenacl_exception_handler(SB),NOSPLIT,$8
     88 	MOVL fn+0(FP), AX
     89 	MOVL AX, 0(SP)
     90 	MOVL arg+4(FP), AX
     91 	MOVL AX, 4(SP)
     92 	NACL_SYSCALL(SYS_exception_handler)
     93 	MOVL AX, ret+8(FP)
     94 	RET
     95 
     96 TEXT runtimenacl_sem_create(SB),NOSPLIT,$4
     97 	MOVL flag+0(FP), AX
     98 	MOVL AX, 0(SP)
     99 	NACL_SYSCALL(SYS_sem_create)
    100 	MOVL AX, ret+4(FP)
    101 	RET
    102 
    103 TEXT runtimenacl_sem_wait(SB),NOSPLIT,$4
    104 	MOVL sem+0(FP), AX
    105 	MOVL AX, 0(SP)
    106 	NACL_SYSCALL(SYS_sem_wait)
    107 	MOVL AX, ret+4(FP)
    108 	RET
    109 
    110 TEXT runtimenacl_sem_post(SB),NOSPLIT,$4
    111 	MOVL sem+0(FP), AX
    112 	MOVL AX, 0(SP)
    113 	NACL_SYSCALL(SYS_sem_post)
    114 	MOVL AX, ret+4(FP)
    115 	RET
    116 
    117 TEXT runtimenacl_mutex_create(SB),NOSPLIT,$4
    118 	MOVL flag+0(FP), AX
    119 	MOVL AX, 0(SP)
    120 	NACL_SYSCALL(SYS_mutex_create)
    121 	MOVL AX, ret+4(FP)
    122 	RET
    123 
    124 TEXT runtimenacl_mutex_lock(SB),NOSPLIT,$4
    125 	MOVL mutex+0(FP), AX
    126 	MOVL AX, 0(SP)
    127 	NACL_SYSCALL(SYS_mutex_lock)
    128 	MOVL AX, ret+4(FP)
    129 	RET
    130 
    131 TEXT runtimenacl_mutex_trylock(SB),NOSPLIT,$4
    132 	MOVL mutex+0(FP), AX
    133 	MOVL AX, 0(SP)
    134 	NACL_SYSCALL(SYS_mutex_trylock)
    135 	MOVL AX, ret+4(FP)
    136 	RET
    137 
    138 TEXT runtimenacl_mutex_unlock(SB),NOSPLIT,$4
    139 	MOVL mutex+0(FP), AX
    140 	MOVL AX, 0(SP)
    141 	NACL_SYSCALL(SYS_mutex_unlock)
    142 	MOVL AX, ret+4(FP)
    143 	RET
    144 
    145 TEXT runtimenacl_cond_create(SB),NOSPLIT,$4
    146 	MOVL flag+0(FP), AX
    147 	MOVL AX, 0(SP)
    148 	NACL_SYSCALL(SYS_cond_create)
    149 	MOVL AX, ret+4(FP)
    150 	RET
    151 
    152 TEXT runtimenacl_cond_wait(SB),NOSPLIT,$8
    153 	MOVL cond+0(FP), AX
    154 	MOVL AX, 0(SP)
    155 	MOVL n+4(FP), AX
    156 	MOVL AX, 4(SP)
    157 	NACL_SYSCALL(SYS_cond_wait)
    158 	MOVL AX, ret+8(FP)
    159 	RET
    160 
    161 TEXT runtimenacl_cond_signal(SB),NOSPLIT,$4
    162 	MOVL cond+0(FP), AX
    163 	MOVL AX, 0(SP)
    164 	NACL_SYSCALL(SYS_cond_signal)
    165 	MOVL AX, ret+4(FP)
    166 	RET
    167 
    168 TEXT runtimenacl_cond_broadcast(SB),NOSPLIT,$4
    169 	MOVL cond+0(FP), AX
    170 	MOVL AX, 0(SP)
    171 	NACL_SYSCALL(SYS_cond_broadcast)
    172 	MOVL AX, ret+4(FP)
    173 	RET
    174 
    175 TEXT runtimenacl_cond_timed_wait_abs(SB),NOSPLIT,$12
    176 	MOVL cond+0(FP), AX
    177 	MOVL AX, 0(SP)
    178 	MOVL lock+4(FP), AX
    179 	MOVL AX, 4(SP)
    180 	MOVL ts+8(FP), AX
    181 	MOVL AX, 8(SP)
    182 	NACL_SYSCALL(SYS_cond_timed_wait_abs)
    183 	MOVL AX, ret+12(FP)
    184 	RET
    185 
    186 TEXT runtimenacl_thread_create(SB),NOSPLIT,$16
    187 	MOVL fn+0(FP), AX
    188 	MOVL AX, 0(SP)
    189 	MOVL stk+4(FP), AX
    190 	MOVL AX, 4(SP)
    191 	MOVL tls+8(FP), AX
    192 	MOVL AX, 8(SP)
    193 	MOVL xx+12(FP), AX
    194 	MOVL AX, 12(SP)
    195 	NACL_SYSCALL(SYS_thread_create)
    196 	MOVL AX, ret+16(FP)
    197 	RET
    198 
    199 TEXT runtimemstart_nacl(SB),NOSPLIT,$0
    200 	JMP runtimemstart(SB)
    201 
    202 TEXT runtimenacl_nanosleep(SB),NOSPLIT,$8
    203 	MOVL ts+0(FP), AX
    204 	MOVL AX, 0(SP)
    205 	MOVL extra+4(FP), AX
    206 	MOVL AX, 4(SP)
    207 	NACL_SYSCALL(SYS_nanosleep)
    208 	MOVL AX, ret+8(FP)
    209 	RET
    210 
    211 TEXT runtimeosyield(SB),NOSPLIT,$0
    212 	NACL_SYSCALL(SYS_sched_yield)
    213 	RET
    214 
    215 TEXT runtimemmap(SB),NOSPLIT,$32
    216 	MOVL	addr+0(FP), AX
    217 	MOVL	AX, 0(SP)
    218 	MOVL	n+4(FP), AX
    219 	MOVL	AX, 4(SP)
    220 	MOVL	prot+8(FP), AX
    221 	MOVL	AX, 8(SP)
    222 	MOVL	flags+12(FP), AX
    223 	MOVL	AX, 12(SP)
    224 	MOVL	fd+16(FP), AX
    225 	MOVL	AX, 16(SP)
    226 	MOVL	off+20(FP), AX
    227 	MOVL	AX, 24(SP)
    228 	MOVL	$0, 28(SP)
    229 	LEAL	24(SP), AX
    230 	MOVL	AX, 20(SP)
    231 	NACL_SYSCALL(SYS_mmap)
    232 	CMPL	AX, $-4095
    233 	JNA	ok
    234 	NEGL	AX
    235 	MOVL	$0, p+24(FP)
    236 	MOVL	AX, err+28(FP)
    237 	RET
    238 ok:
    239 	MOVL	AX, p+24(FP)
    240 	MOVL	$0, err+28(FP)
    241 	RET
    242 
    243 TEXT runtimewalltime(SB),NOSPLIT,$20
    244 	MOVL $0, 0(SP) // real time clock
    245 	LEAL 8(SP), AX
    246 	MOVL AX, 4(SP) // timespec
    247 	NACL_SYSCALL(SYS_clock_gettime)
    248 	MOVL 8(SP), AX // low 32 sec
    249 	MOVL 12(SP), CX // high 32 sec
    250 	MOVL 16(SP), BX // nsec
    251 
    252 	// sec is in AX, nsec in BX
    253 	MOVL	AX, sec_lo+0(FP)
    254 	MOVL	CX, sec_hi+4(FP)
    255 	MOVL	BX, nsec+8(FP)
    256 	RET
    257 
    258 TEXT syscallnow(SB),NOSPLIT,$0
    259 	JMP runtimewalltime(SB)
    260 
    261 TEXT runtimenacl_clock_gettime(SB),NOSPLIT,$8
    262 	MOVL arg1+0(FP), AX
    263 	MOVL AX, 0(SP)
    264 	MOVL arg2+4(FP), AX
    265 	MOVL AX, 4(SP)
    266 	NACL_SYSCALL(SYS_clock_gettime)
    267 	MOVL AX, ret+8(FP)
    268 	RET
    269 
    270 TEXT runtimenanotime(SB),NOSPLIT,$20
    271 	MOVL $0, 0(SP) // real time clock
    272 	LEAL 8(SP), AX
    273 	MOVL AX, 4(SP) // timespec
    274 	NACL_SYSCALL(SYS_clock_gettime)
    275 	MOVL 8(SP), AX // low 32 sec
    276 	MOVL 16(SP), BX // nsec
    277 
    278 	// sec is in AX, nsec in BX
    279 	// convert to DX:AX nsec
    280 	MOVL	$1000000000, CX
    281 	MULL	CX
    282 	ADDL	BX, AX
    283 	ADCL	$0, DX
    284 
    285 	MOVL	AX, ret_lo+0(FP)
    286 	MOVL	DX, ret_hi+4(FP)
    287 	RET
    288 
    289 TEXT runtimesetldt(SB),NOSPLIT,$8
    290 	MOVL	addr+4(FP), BX // aka base
    291 	ADDL	$0x8, BX
    292 	MOVL	BX, 0(SP)
    293 	NACL_SYSCALL(SYS_tls_init)
    294 	RET
    295 
    296 TEXT runtimesigtramp(SB),NOSPLIT,$0
    297 	get_tls(CX)
    298 
    299 	// check that g exists
    300 	MOVL	g(CX), DI
    301 	CMPL	DI, $0
    302 	JNE	6(PC)
    303 	MOVL	$11, BX
    304 	MOVL	$0, 0(SP)
    305 	MOVL	$runtimebadsignal(SB), AX
    306 	CALL	AX
    307 	JMP 	ret
    308 
    309 	// save g
    310 	MOVL	DI, 20(SP)
    311 
    312 	// g = m->gsignal
    313 	MOVL	g_m(DI), BX
    314 	MOVL	m_gsignal(BX), BX
    315 	MOVL	BX, g(CX)
    316 
    317 	// copy arguments for sighandler
    318 	MOVL	$11, 0(SP) // signal
    319 	MOVL	$0, 4(SP) // siginfo
    320 	LEAL	ctxt+4(FP), AX
    321 	MOVL	AX, 8(SP) // context
    322 	MOVL	DI, 12(SP) // g
    323 
    324 	CALL	runtimesighandler(SB)
    325 
    326 	// restore g
    327 	get_tls(CX)
    328 	MOVL	20(SP), BX
    329 	MOVL	BX, g(CX)
    330 
    331 ret:
    332 	// Enable exceptions again.
    333 	NACL_SYSCALL(SYS_exception_clear_flag)
    334 
    335 	// NaCl has abdicated its traditional operating system responsibility
    336 	// and declined to implement 'sigreturn'. Instead the only way to return
    337 	// to the execution of our program is to restore the registers ourselves.
    338 	// Unfortunately, that is impossible to do with strict fidelity, because
    339 	// there is no way to do the final update of PC that ends the sequence
    340 	// without either (1) jumping to a register, in which case the register ends
    341 	// holding the PC value instead of its intended value or (2) storing the PC
    342 	// on the stack and using RET, which imposes the requirement that SP is
    343 	// valid and that is okay to smash the word below it. The second would
    344 	// normally be the lesser of the two evils, except that on NaCl, the linker
    345 	// must rewrite RET into "POP reg; AND $~31, reg; JMP reg", so either way
    346 	// we are going to lose a register as a result of the incoming signal.
    347 	// Similarly, there is no way to restore EFLAGS; the usual way is to use
    348 	// POPFL, but NaCl rejects that instruction. We could inspect the bits and
    349 	// execute a sequence of instructions designed to recreate those flag
    350 	// settings, but that's a lot of work.
    351 	//
    352 	// Thankfully, Go's signal handlers never try to return directly to the
    353 	// executing code, so all the registers and EFLAGS are dead and can be
    354 	// smashed. The only registers that matter are the ones that are setting
    355 	// up for the simulated call that the signal handler has created.
    356 	// Today those registers are just PC and SP, but in case additional registers
    357 	// are relevant in the future (for example DX is the Go func context register)
    358 	// we restore as many registers as possible.
    359 	//
    360 	// We smash BP, because that's what the linker smashes during RET.
    361 	//
    362 	LEAL	ctxt+4(FP), BP
    363 	ADDL	$64, BP
    364 	MOVL	0(BP), AX
    365 	MOVL	4(BP), CX
    366 	MOVL	8(BP), DX
    367 	MOVL	12(BP), BX
    368 	MOVL	16(BP), SP
    369 	// 20(BP) is saved BP, never to be seen again
    370 	MOVL	24(BP), SI
    371 	MOVL	28(BP), DI
    372 	// 36(BP) is saved EFLAGS, never to be seen again
    373 	MOVL	32(BP), BP // saved PC
    374 	JMP	BP
    375 
    376 // func getRandomData([]byte)
    377 TEXT runtimegetRandomData(SB),NOSPLIT,$8-12
    378 	MOVL arg_base+0(FP), AX
    379 	MOVL AX, 0(SP)
    380 	MOVL arg_len+4(FP), AX
    381 	MOVL AX, 4(SP)
    382 	NACL_SYSCALL(SYS_get_random_bytes)
    383 	RET
    384