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