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 	MOVL	AX, ret+24(FP)
    231 	RET
    232 
    233 TEXT timenow(SB),NOSPLIT,$20
    234 	MOVL $0, 0(SP) // real time clock
    235 	LEAL 8(SP), AX
    236 	MOVL AX, 4(SP) // timespec
    237 	NACL_SYSCALL(SYS_clock_gettime)
    238 	MOVL 8(SP), AX // low 32 sec
    239 	MOVL 12(SP), CX // high 32 sec
    240 	MOVL 16(SP), BX // nsec
    241 
    242 	// sec is in AX, nsec in BX
    243 	MOVL	AX, sec+0(FP)
    244 	MOVL	CX, sec+4(FP)
    245 	MOVL	BX, nsec+8(FP)
    246 	RET
    247 
    248 TEXT syscallnow(SB),NOSPLIT,$0
    249 	JMP timenow(SB)
    250 
    251 TEXT runtimenacl_clock_gettime(SB),NOSPLIT,$8
    252 	MOVL arg1+0(FP), AX
    253 	MOVL AX, 0(SP)
    254 	MOVL arg2+4(FP), AX
    255 	MOVL AX, 4(SP)
    256 	NACL_SYSCALL(SYS_clock_gettime)
    257 	MOVL AX, ret+8(FP)
    258 	RET
    259 
    260 TEXT runtimenanotime(SB),NOSPLIT,$20
    261 	MOVL $0, 0(SP) // real time clock
    262 	LEAL 8(SP), AX
    263 	MOVL AX, 4(SP) // timespec
    264 	NACL_SYSCALL(SYS_clock_gettime)
    265 	MOVL 8(SP), AX // low 32 sec
    266 	MOVL 16(SP), BX // nsec
    267 
    268 	// sec is in AX, nsec in BX
    269 	// convert to DX:AX nsec
    270 	MOVL	$1000000000, CX
    271 	MULL	CX
    272 	ADDL	BX, AX
    273 	ADCL	$0, DX
    274 
    275 	MOVL	AX, ret_lo+0(FP)
    276 	MOVL	DX, ret_hi+4(FP)
    277 	RET
    278 
    279 TEXT runtimesetldt(SB),NOSPLIT,$8
    280 	MOVL	addr+4(FP), BX // aka base
    281 	ADDL	$0x8, BX
    282 	MOVL	BX, 0(SP)
    283 	NACL_SYSCALL(SYS_tls_init)
    284 	RET
    285 
    286 TEXT runtimesigtramp(SB),NOSPLIT,$0
    287 	get_tls(CX)
    288 
    289 	// check that g exists
    290 	MOVL	g(CX), DI
    291 	CMPL	DI, $0
    292 	JNE	6(PC)
    293 	MOVL	$11, BX
    294 	MOVL	$0, 0(SP)
    295 	MOVL	$runtimebadsignal(SB), AX
    296 	CALL	AX
    297 	JMP 	ret
    298 
    299 	// save g
    300 	MOVL	DI, 20(SP)
    301 
    302 	// g = m->gsignal
    303 	MOVL	g_m(DI), BX
    304 	MOVL	m_gsignal(BX), BX
    305 	MOVL	BX, g(CX)
    306 
    307 	// copy arguments for sighandler
    308 	MOVL	$11, 0(SP) // signal
    309 	MOVL	$0, 4(SP) // siginfo
    310 	LEAL	ctxt+4(FP), AX
    311 	MOVL	AX, 8(SP) // context
    312 	MOVL	DI, 12(SP) // g
    313 
    314 	CALL	runtimesighandler(SB)
    315 
    316 	// restore g
    317 	get_tls(CX)
    318 	MOVL	20(SP), BX
    319 	MOVL	BX, g(CX)
    320 
    321 ret:
    322 	// Enable exceptions again.
    323 	NACL_SYSCALL(SYS_exception_clear_flag)
    324 
    325 	// NaCl has abdicated its traditional operating system responsibility
    326 	// and declined to implement 'sigreturn'. Instead the only way to return
    327 	// to the execution of our program is to restore the registers ourselves.
    328 	// Unfortunately, that is impossible to do with strict fidelity, because
    329 	// there is no way to do the final update of PC that ends the sequence
    330 	// without either (1) jumping to a register, in which case the register ends
    331 	// holding the PC value instead of its intended value or (2) storing the PC
    332 	// on the stack and using RET, which imposes the requirement that SP is
    333 	// valid and that is okay to smash the word below it. The second would
    334 	// normally be the lesser of the two evils, except that on NaCl, the linker
    335 	// must rewrite RET into "POP reg; AND $~31, reg; JMP reg", so either way
    336 	// we are going to lose a register as a result of the incoming signal.
    337 	// Similarly, there is no way to restore EFLAGS; the usual way is to use
    338 	// POPFL, but NaCl rejects that instruction. We could inspect the bits and
    339 	// execute a sequence of instructions designed to recreate those flag
    340 	// settings, but that's a lot of work.
    341 	//
    342 	// Thankfully, Go's signal handlers never try to return directly to the
    343 	// executing code, so all the registers and EFLAGS are dead and can be
    344 	// smashed. The only registers that matter are the ones that are setting
    345 	// up for the simulated call that the signal handler has created.
    346 	// Today those registers are just PC and SP, but in case additional registers
    347 	// are relevant in the future (for example DX is the Go func context register)
    348 	// we restore as many registers as possible.
    349 	//
    350 	// We smash BP, because that's what the linker smashes during RET.
    351 	//
    352 	LEAL	ctxt+4(FP), BP
    353 	ADDL	$64, BP
    354 	MOVL	0(BP), AX
    355 	MOVL	4(BP), CX
    356 	MOVL	8(BP), DX
    357 	MOVL	12(BP), BX
    358 	MOVL	16(BP), SP
    359 	// 20(BP) is saved BP, never to be seen again
    360 	MOVL	24(BP), SI
    361 	MOVL	28(BP), DI
    362 	// 36(BP) is saved EFLAGS, never to be seen again
    363 	MOVL	32(BP), BP // saved PC
    364 	JMP	BP
    365 
    366 // func getRandomData([]byte)
    367 TEXT runtimegetRandomData(SB),NOSPLIT,$8-12
    368 	MOVL buf+0(FP), AX
    369 	MOVL AX, 0(SP)
    370 	MOVL len+4(FP), AX
    371 	MOVL AX, 4(SP)
    372 	NACL_SYSCALL(SYS_get_random_bytes)
    373 	RET
    374