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