github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/runtime/sys_nacl_386.s (about) 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 // NaCl system calls are mediated through an "outer sandbox." System calls are 6 // internally implemented by branching to a stub in the system call table 7 // located at address 0x10000+32*number. 8 // 9 // However, the system call interface isn't part of the public NaCl API, and it 10 // is subject to change. The officially supported interface is the NaCl IRT 11 // (for "integrated runtime"), which must be manually linked. If the IRT is 12 // available, a lookup function is passed via the Elf aux vector, for fetching 13 // the function pointers corresponding to each of the IRT functions. 14 // 15 // For now, we support both mechanisms. If the IRT is available, we use it. 16 // Otherwise, we invoke the raw system calls directly. The two interfaces are 17 // similar; the IRT is really just a thin wrapper around the system calls, 18 // changing the signature somewhat. For example, the raw system calls use 19 // return values to pass back results in some cases. 20 // 21 // // Raw syscall. 22 // int fd = NACL_SYSCALL(SYS_open)(pathname, oflag, mode); 23 // if (fd < 0) { ...error... } 24 // 25 // In contrast, the IRT uses return values only for error codes. Results are 26 // returned through result parameters. 27 // 28 // // IRT syscall. 29 // int fd; 30 // int code = (*irt_filename[IRT_FILENAME_OPEN])(pathname, oflag, mode, &fd); 31 // if (code != 0) { ...error... } 32 // 33 // Whether raw or IRT, the system call that is invoked runs in the same address 34 // space as the caller, using the caller's stack. Since the stack requirements 35 // for the syscall aren't known, the wrappers here switch from the goroutine 36 // stack to the main thread stack, invoke the system call, then switch back to 37 // the original stack. The basic form of these wrappers is as follows. 38 // 39 // switch to main thread stack 40 // if !irt_is_enabled 41 // invoke raw syscall 42 // else 43 // invoke IRT syscall 44 // switch back to original stack 45 // 46 // One of the reasons for supporting raw syscalls is for the Go playground. At 47 // some point, we may want to consider requiring the IRT for the playground, 48 // removing support for raw syscalls. 49 50 #include "zasm_GOOS_GOARCH.h" 51 #include "textflag.h" 52 #include "syscall_nacl.h" 53 #include "irt_nacl.h" 54 55 #define NACL_SYSCALL(code) \ 56 MOVL $(0x10000 + ((code)<<5)), AX; CALL AX 57 58 // Swap stacks so that the caller runs on the main m->g0 stack. 59 // On return, SP is the main m->g0 stack, BP holds the original stack frame, and 60 // the current stack contains contains the original SP at 0(SP). 61 TEXT runtime·nacl_swapstack(SB),NOSPLIT,$0 62 LEAL 4(SP), BP 63 64 get_tls(CX) 65 CMPL CX, $0 66 JE nss_return // Not a Go-managed thread. Do not switch stack. 67 68 MOVL g(CX), DI 69 MOVL g_m(DI), DI 70 MOVL m_g0(DI), SI 71 CMPL g(CX), SI 72 JE nss_return // Executing on m->g0 already. 73 74 // Switch to m->g0 stack. 75 MOVL (g_sched+gobuf_sp)(SI), SI 76 LEAL -4(SI), SP 77 78 nss_return: 79 MOVL -4(BP), AX 80 MOVL BP, (SP) 81 ADDL $4, BP 82 JMP AX 83 84 // Restore the original stack. Must not modify AX. 85 TEXT runtime·nacl_restorestack(SB),NOSPLIT,$0 86 MOVL (SP), BX 87 MOVL 4(SP), SP 88 JMP BX 89 90 // Begin a NaCl IRT call. Execute call on the main m->g0 stack. 91 // On return, SP is the main m->g0 stack, BP holds the original stack frame, and 92 // the current stack contains the original SP at 0(SP). Call runtime·entersyscall 93 // only if the stack is switched and the current P is set. 94 TEXT runtime·nacl_entersyscall(SB),NOSPLIT,$0-0 95 MOVL $0, AX // AX is set to true only if runtime·entersyscall was called. 96 MOVL SP, BP 97 98 get_tls(CX) 99 TESTL CX, CX 100 JZ nen_return // Not a Go-managed thread. Do not switch stack. 101 102 MOVL g(CX), DI 103 MOVL g_m(DI), DI 104 MOVL m_g0(DI), SI 105 CMPL g(CX), SI 106 JE nen_return // Executing on m->g0 already. 107 108 MOVL m_p(DI), DX 109 TESTL DX, DX 110 JZ nen_swapstack // Not a goroutine. 111 112 CALL runtime·entersyscall(SB) 113 MOVL $1, AX 114 MOVL SP, BP 115 get_tls(CX) 116 MOVL g(CX), DI 117 MOVL g_m(DI), DI 118 MOVL m_g0(DI), SI 119 120 nen_swapstack: 121 // Switch to m->g0 stack. 122 MOVL (g_sched+gobuf_sp)(SI), SI 123 LEAL -4(SI), SP 124 125 nen_return: 126 SUBL $8, SP 127 MOVL (BP), CX 128 MOVL BP, (SP) 129 MOVL AX, 4(SP) 130 ADDL $8, BP 131 JMP CX 132 133 // Finish a NaCl IRT call. Restores the stack, and calls runtime·exitsyscall, 134 // but only if runtime·entersyscall was called on entry. Must not modify AX. 135 TEXT runtime·nacl_exitsyscall(SB),NOSPLIT,$0-0 136 MOVL 8(SP), BX 137 TESTL BX, BX 138 JZ nex_return 139 MOVL (SP), BX 140 MOVL 4(SP), SP 141 MOVL BX, (SP) 142 CALL runtime·nacl_wrap_exitsyscall(SB) 143 RET 144 nex_return: 145 MOVL (SP), BX 146 MOVL 4(SP), SP 147 MOVL BX, (SP) 148 RET 149 150 TEXT runtime·nacl_wrap_exitsyscall(SB),NOSPLIT,$4 151 MOVL AX, (SP) 152 CALL runtime·exitsyscall(SB) 153 MOVL (SP), AX 154 RET 155 156 TEXT runtime·exit(SB),NOSPLIT,$0 157 CALL runtime·nacl_swapstack(SB) 158 SUBL $4, SP 159 MOVL 0(BP), AX 160 MOVL AX, 0(SP) 161 CMPL runtime·nacl_irt_is_enabled(SB), $0 162 JNE exit_irt 163 NACL_SYSCALL(SYS_exit) 164 MOVL $0x13, 0x13 // crash 165 exit_irt: 166 MOVL runtime·nacl_irt_basic_v0_1+(IRT_BASIC_EXIT*4)(SB), AX 167 CALL AX 168 MOVL $0x14, 0x14 // crash 169 170 TEXT runtime·exit1(SB),NOSPLIT,$0 171 CALL runtime·nacl_swapstack(SB) 172 SUBL $4, SP 173 MOVL 0(BP), AX 174 MOVL AX, 0(SP) 175 CMPL runtime·nacl_irt_is_enabled(SB), $0 176 JNE exit1_irt 177 NACL_SYSCALL(SYS_thread_exit) 178 MOVL $0x15, 0x15 // crash 179 exit1_irt: 180 MOVL runtime·nacl_irt_thread_v0_1+(IRT_THREAD_EXIT*4)(SB), AX 181 CALL AX 182 MOVL $0x16, 0x16 // crash 183 184 TEXT runtime·open(SB),NOSPLIT,$0 185 CALL runtime·nacl_entersyscall(SB) 186 CMPL runtime·nacl_irt_is_enabled(SB), $0 187 JNE open_irt 188 SUBL $12, SP 189 MOVL 0(BP), AX // pathname 190 MOVL AX, 0(SP) 191 MOVL 4(BP), AX // oflag 192 MOVL AX, 4(SP) 193 MOVL 8(BP), AX // cmode 194 MOVL AX, 8(SP) 195 NACL_SYSCALL(SYS_open) 196 ADDL $12, SP 197 CALL runtime·nacl_exitsyscall(SB) 198 MOVL AX, ret+12(FP) 199 RET 200 open_irt: 201 SUBL $20, SP 202 MOVL 0(BP), AX // pathname 203 MOVL AX, 0(SP) 204 MOVL 4(BP), AX // oflag 205 MOVL AX, 4(SP) 206 MOVL 8(BP), AX // cmode 207 MOVL AX, 8(SP) 208 LEAL 16(SP), AX // &fd 209 MOVL AX, 12(SP) 210 MOVL runtime·nacl_irt_filename_v0_1+(IRT_FILENAME_OPEN*4)(SB), AX 211 CALL AX 212 NEGL AX 213 JNZ open_done 214 MOVL 16(SP), AX 215 open_done: 216 ADDL $20, SP 217 CALL runtime·nacl_exitsyscall(SB) 218 MOVL AX, ret+12(FP) 219 RET 220 221 TEXT runtime·close(SB),NOSPLIT,$0 222 CALL runtime·nacl_entersyscall(SB) 223 SUBL $4, SP 224 MOVL 0(BP), AX 225 MOVL AX, 0(SP) 226 CMPL runtime·nacl_irt_is_enabled(SB), $0 227 JNE close_irt 228 NACL_SYSCALL(SYS_close) 229 JMP close_done 230 close_irt: 231 MOVL runtime·nacl_irt_fdio_v0_1+(IRT_FDIO_CLOSE*4)(SB), AX 232 CALL AX 233 NEGL AX 234 close_done: 235 ADDL $4, SP 236 CALL runtime·nacl_exitsyscall(SB) 237 MOVL AX, ret+4(FP) 238 RET 239 240 TEXT runtime·read(SB),NOSPLIT,$0 241 CALL runtime·nacl_entersyscall(SB) 242 CMPL runtime·nacl_irt_is_enabled(SB), $0 243 JNE read_irt 244 SUBL $12, SP 245 MOVL 0(BP), AX // fd 246 MOVL AX, 0(SP) 247 MOVL 4(BP), AX // buf 248 MOVL AX, 4(SP) 249 MOVL 8(BP), AX // count 250 MOVL AX, 8(SP) 251 NACL_SYSCALL(SYS_read) 252 ADDL $12, SP 253 CALL runtime·nacl_exitsyscall(SB) 254 MOVL AX, ret+12(FP) 255 RET 256 read_irt: 257 SUBL $20, SP 258 MOVL 0(BP), AX // fd 259 MOVL AX, 0(SP) 260 MOVL 4(BP), AX // buf 261 MOVL AX, 4(SP) 262 MOVL 8(BP), AX // count 263 MOVL AX, 8(SP) 264 LEAL 16(SP), AX // nread 265 MOVL AX, 12(SP) 266 MOVL runtime·nacl_irt_fdio_v0_1+(IRT_FDIO_READ*4)(SB), AX 267 CALL AX 268 NEGL AX 269 JNZ read_done 270 MOVL 16(SP), AX 271 read_done: 272 ADDL $20, SP 273 CALL runtime·nacl_exitsyscall(SB) 274 MOVL AX, ret+12(FP) 275 RET 276 277 TEXT syscall·naclWrite(SB), NOSPLIT, $16-16 278 MOVL arg1+0(FP), DI 279 MOVL arg2+4(FP), SI 280 MOVL arg3+8(FP), DX 281 MOVL DI, 0(SP) 282 MOVL SI, 4(SP) 283 MOVL DX, 8(SP) 284 CALL runtime·write(SB) 285 MOVL AX, ret+16(FP) 286 RET 287 288 TEXT runtime·write(SB),NOSPLIT,$0 289 CALL runtime·nacl_entersyscall(SB) 290 CMPL runtime·nacl_irt_is_enabled(SB), $0 291 JNE write_irt 292 SUBL $12, SP 293 MOVL 0(BP), AX // fd 294 MOVL AX, 0(SP) 295 MOVL 4(BP), AX // buf 296 MOVL AX, 4(SP) 297 MOVL 8(BP), AX // count 298 MOVL AX, 8(SP) 299 NACL_SYSCALL(SYS_write) 300 ADDL $12, SP 301 CALL runtime·nacl_exitsyscall(SB) 302 MOVL AX, ret+12(FP) 303 RET 304 write_irt: 305 SUBL $20, SP 306 MOVL 0(BP), AX // fd 307 MOVL AX, 0(SP) 308 MOVL 4(BP), AX // buf 309 MOVL AX, 4(SP) 310 MOVL 8(BP), AX // count 311 MOVL AX, 8(SP) 312 LEAL 16(SP), AX // nwrite 313 MOVL AX, 12(SP) 314 MOVL runtime·nacl_irt_fdio_v0_1+(IRT_FDIO_WRITE*4)(SB), AX 315 CALL AX 316 NEGL AX 317 JNZ write_done 318 MOVL 16(SP), AX 319 write_done: 320 ADDL $20, SP 321 CALL runtime·nacl_exitsyscall(SB) 322 MOVL AX, ret+12(FP) 323 RET 324 325 TEXT runtime·nacl_exception_stack(SB),NOSPLIT,$0 326 CALL runtime·nacl_swapstack(SB) 327 SUBL $8, SP 328 MOVL 0(BP), AX // stack 329 MOVL AX, 0(SP) 330 MOVL 4(BP), AX // size 331 MOVL AX, 4(SP) 332 CMPL runtime·nacl_irt_is_enabled(SB), $0 333 JNE nacl_exception_stack_irt 334 NACL_SYSCALL(SYS_exception_stack) 335 JMP nacl_exception_stack_done 336 nacl_exception_stack_irt: 337 MOVL runtime·nacl_irt_exception_handling_v0_1+(IRT_EXCEPTION_STACK*4)(SB), AX 338 CALL AX 339 NEGL AX 340 nacl_exception_stack_done: 341 ADDL $8, SP 342 CALL runtime·nacl_restorestack(SB) 343 MOVL AX, ret+8(FP) 344 RET 345 346 TEXT runtime·nacl_exception_handler(SB),NOSPLIT,$0 347 CALL runtime·nacl_swapstack(SB) 348 SUBL $8, SP 349 MOVL 0(BP), AX // handler 350 MOVL AX, 0(SP) 351 MOVL 4(BP), AX // *old_handler 352 MOVL AX, 4(SP) 353 CMPL runtime·nacl_irt_is_enabled(SB), $0 354 JNE nacl_exception_handler_irt 355 NACL_SYSCALL(SYS_exception_handler) 356 JMP nacl_exception_handler_done 357 nacl_exception_handler_irt: 358 MOVL runtime·nacl_irt_exception_handling_v0_1+(IRT_EXCEPTION_HANDLER*4)(SB), AX 359 CALL AX 360 NEGL AX 361 nacl_exception_handler_done: 362 ADDL $8, SP 363 CALL runtime·nacl_restorestack(SB) 364 MOVL AX, ret+8(FP) 365 RET 366 367 TEXT runtime·nacl_sem_create(SB),NOSPLIT,$0 368 CALL runtime·nacl_entersyscall(SB) 369 CMPL runtime·nacl_irt_is_enabled(SB), $0 370 JNE sem_create_irt 371 SUBL $4, SP 372 MOVL 0(BP), AX // value 373 MOVL AX, 0(SP) 374 NACL_SYSCALL(SYS_sem_create) 375 ADDL $4, SP 376 CALL runtime·nacl_exitsyscall(SB) 377 MOVL AX, ret+4(FP) 378 RET 379 sem_create_irt: 380 SUBL $12, SP 381 LEAL 8(SP), AX // *sem_handle 382 MOVL AX, 0(SP) 383 MOVL 4(BP), AX // value 384 MOVL AX, 4(SP) 385 MOVL runtime·nacl_irt_sem_v0_1+(IRT_SEM_CREATE*4)(SB), AX 386 CALL AX 387 NEGL AX 388 JNZ sem_create_done 389 MOVL 8(SP), AX 390 sem_create_done: 391 ADDL $12, SP 392 CALL runtime·nacl_exitsyscall(SB) 393 MOVL AX, ret+4(FP) 394 RET 395 396 TEXT runtime·nacl_sem_wait(SB),NOSPLIT,$0 397 CALL runtime·nacl_entersyscall(SB) 398 SUBL $4, SP 399 MOVL 0(BP), AX // sem_handle 400 MOVL AX, 0(SP) 401 CMPL runtime·nacl_irt_is_enabled(SB), $0 402 JNE sem_wait_irt 403 NACL_SYSCALL(SYS_sem_wait) 404 JMP sem_wait_done 405 sem_wait_irt: 406 MOVL runtime·nacl_irt_sem_v0_1+(IRT_SEM_WAIT*4)(SB), AX 407 CALL AX 408 NEGL AX 409 sem_wait_done: 410 ADDL $4, SP 411 CALL runtime·nacl_exitsyscall(SB) 412 MOVL AX, ret+4(FP) 413 RET 414 415 TEXT runtime·nacl_sem_post(SB),NOSPLIT,$0 416 CALL runtime·nacl_entersyscall(SB) 417 SUBL $4, SP 418 MOVL 0(BP), AX // sem_handle 419 MOVL AX, 0(SP) 420 CMPL runtime·nacl_irt_is_enabled(SB), $0 421 JNE sem_post_irt 422 NACL_SYSCALL(SYS_sem_post) 423 JMP sem_post_done 424 sem_post_irt: 425 MOVL runtime·nacl_irt_sem_v0_1+(IRT_SEM_POST*4)(SB), AX 426 CALL AX 427 NEGL AX 428 sem_post_done: 429 ADDL $4, SP 430 CALL runtime·nacl_exitsyscall(SB) 431 MOVL AX, ret+4(FP) 432 RET 433 434 TEXT runtime·nacl_mutex_create(SB),NOSPLIT,$0 435 CALL runtime·nacl_entersyscall(SB) 436 CMPL runtime·nacl_irt_is_enabled(SB), $0 437 JNE mutex_create_irt 438 SUBL $4, SP 439 MOVL 0(BP), AX // flag 440 MOVL AX, (SP) 441 NACL_SYSCALL(SYS_mutex_create) 442 ADDL $4, SP 443 CALL runtime·nacl_exitsyscall(SB) 444 MOVL AX, ret+4(FP) 445 RET 446 mutex_create_irt: 447 SUBL $8, SP 448 LEAL 4(SP), AX // *mutex_handle 449 MOVL AX, 0(SP) 450 MOVL runtime·nacl_irt_mutex_v0_1+(IRT_MUTEX_CREATE*4)(SB), AX 451 CALL AX 452 NEGL AX 453 JNZ mutex_create_done 454 MOVL 4(SP), AX 455 mutex_create_done: 456 ADDL $8, SP 457 CALL runtime·nacl_exitsyscall(SB) 458 MOVL AX, ret+4(FP) 459 RET 460 461 TEXT runtime·nacl_mutex_lock(SB),NOSPLIT,$0 462 CALL runtime·nacl_entersyscall(SB) 463 SUBL $4, SP 464 MOVL 0(BP), AX // mutex_handle 465 MOVL AX, 0(SP) 466 CMPL runtime·nacl_irt_is_enabled(SB), $0 467 JNE mutex_lock_irt 468 NACL_SYSCALL(SYS_mutex_lock) 469 JMP mutex_lock_done 470 mutex_lock_irt: 471 MOVL runtime·nacl_irt_mutex_v0_1+(IRT_MUTEX_LOCK*4)(SB), AX 472 CALL AX 473 NEGL AX 474 mutex_lock_done: 475 ADDL $4, SP 476 CALL runtime·nacl_exitsyscall(SB) 477 MOVL AX, ret+4(FP) 478 RET 479 480 TEXT runtime·nacl_mutex_trylock(SB),NOSPLIT,$0 481 CALL runtime·nacl_entersyscall(SB) 482 SUBL $4, SP 483 MOVL 0(BP), AX // mutex_handle 484 MOVL AX, 0(SP) 485 CMPL runtime·nacl_irt_is_enabled(SB), $0 486 JNE mutex_trylock_irt 487 NACL_SYSCALL(SYS_mutex_trylock) 488 JMP mutex_trylock_done 489 mutex_trylock_irt: 490 MOVL runtime·nacl_irt_mutex_v0_1+(IRT_MUTEX_TRYLOCK*4)(SB), AX 491 CALL AX 492 NEGL AX 493 mutex_trylock_done: 494 ADDL $4, SP 495 CALL runtime·nacl_exitsyscall(SB) 496 MOVL AX, ret+4(FP) 497 RET 498 499 TEXT runtime·nacl_mutex_unlock(SB),NOSPLIT,$0 500 CALL runtime·nacl_entersyscall(SB) 501 SUBL $4, SP 502 MOVL 0(BP), AX // mutex_handle 503 MOVL AX, 0(SP) 504 CMPL runtime·nacl_irt_is_enabled(SB), $0 505 JNE mutex_unlock_irt 506 NACL_SYSCALL(SYS_mutex_unlock) 507 JMP mutex_unlock_done 508 mutex_unlock_irt: 509 MOVL runtime·nacl_irt_mutex_v0_1+(IRT_MUTEX_UNLOCK*4)(SB), AX 510 CALL AX 511 NEGL AX 512 mutex_unlock_done: 513 ADDL $4, SP 514 CALL runtime·nacl_exitsyscall(SB) 515 MOVL AX, ret+4(FP) 516 RET 517 518 TEXT runtime·nacl_cond_create(SB),NOSPLIT,$0 519 CALL runtime·nacl_entersyscall(SB) 520 CMPL runtime·nacl_irt_is_enabled(SB), $0 521 JNE cond_create_irt 522 SUBL $4, SP 523 MOVL 0(BP), AX // flag 524 MOVL AX, (SP) 525 NACL_SYSCALL(SYS_cond_create) 526 ADDL $4, SP 527 CALL runtime·nacl_exitsyscall(SB) 528 MOVL AX, ret+4(FP) 529 RET 530 cond_create_irt: 531 SUBL $8, SP 532 LEAL 4(SP), AX // *cond_handle 533 MOVL AX, 0(SP) 534 MOVL runtime·nacl_irt_cond_v0_1+(IRT_COND_CREATE*4)(SB), AX 535 CALL AX 536 NEGL AX 537 JNZ cond_create_done 538 MOVL 4(SP), AX 539 cond_create_done: 540 ADDL $8, SP 541 CALL runtime·nacl_exitsyscall(SB) 542 MOVL AX, ret+4(FP) 543 RET 544 545 TEXT runtime·nacl_cond_wait(SB),NOSPLIT,$0 546 CALL runtime·nacl_entersyscall(SB) 547 SUBL $8, SP 548 MOVL 0(BP), AX // cond_handle 549 MOVL AX, 0(SP) 550 MOVL 4(BP), AX // mutex_handle 551 MOVL AX, 4(SP) 552 CMPL runtime·nacl_irt_is_enabled(SB), $0 553 JNE cond_wait_irt 554 NACL_SYSCALL(SYS_cond_wait) 555 JMP cond_wait_done 556 cond_wait_irt: 557 MOVL runtime·nacl_irt_cond_v0_1+(IRT_COND_WAIT*4)(SB), AX 558 CALL AX 559 NEGL AX 560 cond_wait_done: 561 ADDL $8, SP 562 CALL runtime·nacl_exitsyscall(SB) 563 MOVL AX, ret+8(FP) 564 RET 565 566 TEXT runtime·nacl_cond_signal(SB),NOSPLIT,$0 567 CALL runtime·nacl_entersyscall(SB) 568 SUBL $4, SP 569 MOVL 0(BP), AX // cond_handle 570 MOVL AX, 0(SP) 571 CMPL runtime·nacl_irt_is_enabled(SB), $0 572 JNE cond_signal_irt 573 NACL_SYSCALL(SYS_cond_signal) 574 JMP cond_signal_done 575 cond_signal_irt: 576 MOVL runtime·nacl_irt_cond_v0_1+(IRT_COND_SIGNAL*4)(SB), AX 577 CALL AX 578 NEGL AX 579 cond_signal_done: 580 ADDL $4, SP 581 CALL runtime·nacl_exitsyscall(SB) 582 MOVL AX, ret+4(FP) 583 RET 584 585 TEXT runtime·nacl_cond_broadcast(SB),NOSPLIT,$0 586 CALL runtime·nacl_entersyscall(SB) 587 SUBL $4, SP 588 MOVL 0(BP), AX // cond_handle 589 MOVL AX, 0(SP) 590 CMPL runtime·nacl_irt_is_enabled(SB), $0 591 JNE cond_broadcast_irt 592 NACL_SYSCALL(SYS_cond_broadcast) 593 JMP cond_broadcast_done 594 cond_broadcast_irt: 595 MOVL runtime·nacl_irt_cond_v0_1+(IRT_COND_BROADCAST*4)(SB), AX 596 CALL AX 597 NEGL AX 598 cond_broadcast_done: 599 ADDL $4, SP 600 CALL runtime·nacl_exitsyscall(SB) 601 MOVL AX, ret+4(FP) 602 RET 603 604 TEXT runtime·nacl_cond_timed_wait_abs(SB),NOSPLIT,$0 605 CALL runtime·nacl_entersyscall(SB) 606 SUBL $12, SP 607 MOVL 0(BP), AX // cond_handle 608 MOVL AX, 0(SP) 609 MOVL 4(BP), AX // mutex_handle 610 MOVL AX, 4(SP) 611 MOVL 8(BP), AX // abstime 612 MOVL AX, 8(SP) 613 CMPL runtime·nacl_irt_is_enabled(SB), $0 614 JNE cond_timed_wait_abs_irt 615 NACL_SYSCALL(SYS_cond_timed_wait_abs) 616 JMP cond_timed_wait_abs_done 617 cond_timed_wait_abs_irt: 618 MOVL runtime·nacl_irt_cond_v0_1+(IRT_COND_TIMED_WAIT_ABS*4)(SB), AX 619 CALL AX 620 NEGL AX 621 cond_timed_wait_abs_done: 622 ADDL $12, SP 623 CALL runtime·nacl_exitsyscall(SB) 624 MOVL AX, ret+12(FP) 625 RET 626 627 TEXT runtime·nacl_thread_create(SB),NOSPLIT,$0 628 CALL runtime·nacl_entersyscall(SB) 629 CMPL runtime·nacl_irt_is_enabled(SB), $0 630 JNE thread_create_irt 631 SUBL $16, SP 632 MOVL 0(BP), AX // start_func 633 MOVL AX, 0(SP) 634 MOVL 4(BP), AX // stack 635 MOVL AX, 4(SP) 636 MOVL 8(BP), AX // tls 637 MOVL AX, 8(SP) 638 MOVL 12(BP), AX // tp 639 MOVL AX, 12(SP) 640 NACL_SYSCALL(SYS_thread_create) 641 ADDL $16, SP 642 CALL runtime·nacl_exitsyscall(SB) 643 MOVL AX, ret+16(FP) 644 RET 645 thread_create_irt: 646 SUBL $12, SP 647 MOVL 0(BP), AX // start_func 648 MOVL AX, 0(SP) 649 MOVL 4(BP), AX // stack 650 MOVL AX, 4(SP) 651 MOVL 8(BP), AX // thread_ptr 652 MOVL AX, 8(SP) 653 MOVL runtime·nacl_irt_thread_v0_1+(IRT_THREAD_CREATE*4)(SB), AX 654 CALL AX 655 NEGL AX 656 ADDL $12, SP 657 CALL runtime·nacl_exitsyscall(SB) 658 MOVL AX, ret+16(FP) 659 RET 660 661 TEXT runtime·mstart_nacl(SB),NOSPLIT,$0 662 JMP runtime·mstart(SB) 663 664 TEXT runtime·nacl_nanosleep(SB),NOSPLIT,$0 665 CALL runtime·nacl_entersyscall(SB) 666 SUBL $8, SP 667 MOVL 0(BP), AX // req 668 MOVL AX, 0(SP) 669 MOVL 4(BP), AX // rem 670 MOVL AX, 4(SP) 671 CMPL runtime·nacl_irt_is_enabled(SB), $0 672 JNE nanosleep_irt 673 NACL_SYSCALL(SYS_nanosleep) 674 JMP nanosleep_done 675 nanosleep_irt: 676 MOVL runtime·nacl_irt_basic_v0_1+(IRT_BASIC_NANOSLEEP*4)(SB), AX 677 CALL AX 678 NEGL AX 679 nanosleep_done: 680 ADDL $8, SP 681 CALL runtime·nacl_exitsyscall(SB) 682 MOVL AX, ret+8(FP) 683 RET 684 685 TEXT runtime·osyield(SB),NOSPLIT,$0 686 CALL runtime·nacl_entersyscall(SB) 687 CMPL runtime·nacl_irt_is_enabled(SB), $0 688 JNE osyield_irt 689 NACL_SYSCALL(SYS_sched_yield) 690 JMP osyield_done 691 osyield_irt: 692 MOVL runtime·nacl_irt_basic_v0_1+(IRT_BASIC_SCHED_YIELD*4)(SB), AX 693 CALL AX 694 osyield_done: 695 CALL runtime·nacl_exitsyscall(SB) 696 RET 697 698 TEXT runtime·mmap(SB),NOSPLIT,$0 699 CALL runtime·nacl_entersyscall(SB) 700 SUBL $32, SP 701 CMPL runtime·nacl_irt_is_enabled(SB), $0 702 JNE mmap_irt 703 MOVL 0(BP), AX // addr 704 MOVL AX, 0(SP) 705 MOVL 4(BP), AX // len 706 MOVL AX, 4(SP) 707 MOVL 8(BP), AX // prot 708 MOVL AX, 8(SP) 709 MOVL 12(BP), AX // flags 710 MOVL AX, 12(SP) 711 MOVL 16(BP), AX // fd 712 MOVL AX, 16(SP) 713 MOVL 20(BP), AX // off 714 MOVL AX, 24(SP) 715 MOVL $0, 28(SP) // sign-extend 716 LEAL 24(SP), AX // &off 717 MOVL AX, 20(SP) 718 NACL_SYSCALL(SYS_mmap) 719 JMP mmap_done 720 mmap_irt: 721 MOVL 0(BP), AX // addr 722 MOVL AX, 28(SP) 723 LEAL 28(SP), AX // &addr 724 MOVL AX, 0(SP) 725 MOVL 4(BP), AX // len 726 MOVL AX, 4(SP) 727 MOVL 8(BP), AX // prot 728 MOVL AX, 8(SP) 729 MOVL 12(BP), AX // flags 730 MOVL AX, 12(SP) 731 MOVL 16(BP), AX // fd 732 MOVL AX, 16(SP) 733 MOVL 20(BP), AX // off 734 MOVL AX, 20(SP) 735 MOVL $0, 24(SP) // sign-extend 736 MOVL runtime·nacl_irt_memory_v0_3+(IRT_MEMORY_MMAP*4)(SB), AX 737 CALL AX 738 NEGL AX 739 JNZ mmap_done 740 MOVL 28(SP), AX 741 mmap_done: 742 ADDL $32, SP 743 CALL runtime·nacl_exitsyscall(SB) 744 MOVL AX, ret+24(FP) 745 RET 746 747 TEXT time·now(SB),NOSPLIT,$0 748 CALL runtime·nacl_swapstack(SB) 749 SUBL $24, SP 750 MOVL BP, 20(SP) 751 MOVL $0, 0(SP) // real time clock 752 LEAL 8(SP), AX 753 MOVL AX, 4(SP) // timespec 754 CMPL runtime·nacl_irt_is_enabled(SB), $0 755 JNE now_irt 756 NACL_SYSCALL(SYS_clock_gettime) 757 JMP now_done 758 now_irt: 759 MOVL runtime·nacl_irt_clock_v0_1+(IRT_CLOCK_GETTIME*4)(SB), AX 760 CALL AX 761 now_done: 762 MOVL 8(SP), AX // low 32 sec 763 MOVL 12(SP), CX // high 32 sec 764 MOVL 16(SP), BX // nsec 765 766 // sec is in AX, nsec in BX 767 MOVL 20(SP), BP 768 MOVL AX, 0(BP) 769 MOVL CX, 4(BP) 770 MOVL BX, 8(BP) 771 ADDL $24, SP 772 CALL runtime·nacl_restorestack(SB) 773 RET 774 775 TEXT syscall·now(SB),NOSPLIT,$0 776 JMP time·now(SB) 777 778 TEXT runtime·nacl_clock_gettime(SB),NOSPLIT,$0 779 CALL runtime·nacl_swapstack(SB) 780 SUBL $8, SP 781 MOVL 0(BP), AX // clk_id 782 MOVL AX, 0(SP) 783 MOVL 4(BP), AX // *tp 784 MOVL AX, 4(SP) 785 CMPL runtime·nacl_irt_is_enabled(SB), $0 786 JNE clock_gettime_irt 787 NACL_SYSCALL(SYS_clock_gettime) 788 JMP clock_gettime_done 789 clock_gettime_irt: 790 MOVL runtime·nacl_irt_clock_v0_1+(IRT_CLOCK_GETTIME*4)(SB), AX 791 CALL AX 792 NEGL AX 793 clock_gettime_done: 794 ADDL $8, SP 795 CALL runtime·nacl_restorestack(SB) 796 MOVL AX, ret+8(FP) 797 RET 798 799 TEXT runtime·nanotime(SB),NOSPLIT,$0 800 CALL runtime·nacl_swapstack(SB) 801 SUBL $20, SP 802 MOVL $0, 0(SP) // real time clock 803 LEAL 8(SP), AX 804 MOVL AX, 4(SP) // timespec 805 CMPL runtime·nacl_irt_is_enabled(SB), $0 806 JNE nanotime_irt 807 NACL_SYSCALL(SYS_clock_gettime) 808 JMP nanotime_done 809 nanotime_irt: 810 MOVL runtime·nacl_irt_clock_v0_1+(IRT_CLOCK_GETTIME*4)(SB), AX 811 CALL AX 812 nanotime_done: 813 MOVL 8(SP), AX // low 32 sec 814 MOVL 16(SP), BX // nsec 815 816 // sec is in AX, nsec in BX 817 // convert to DX:AX nsec 818 MOVL $1000000000, CX 819 MULL CX 820 ADDL BX, AX 821 ADCL $0, DX 822 ADDL $20, SP 823 CALL runtime·nacl_restorestack(SB) 824 MOVL AX, 4(SP) 825 MOVL DX, 8(SP) 826 RET 827 828 TEXT runtime·setldt(SB),NOSPLIT,$8 829 MOVL addr+4(FP), BX // aka base 830 ADDL $0x8, BX 831 MOVL BX, 0(SP) 832 CMPL runtime·nacl_irt_is_enabled(SB), $0 833 JNE setldt_irt 834 NACL_SYSCALL(SYS_tls_init) 835 RET 836 setldt_irt: 837 MOVL runtime·nacl_irt_tls_v0_1+(IRT_TLS_INIT*4)(SB), AX 838 CALL AX 839 NEGL AX 840 RET 841 842 TEXT runtime·sigtramp(SB),NOSPLIT,$24 843 get_tls(CX) 844 845 // check that g exists 846 MOVL g(CX), DI 847 CMPL DI, $0 848 JNE 6(PC) 849 MOVL $11, BX 850 MOVL $0, 0(SP) 851 MOVL $runtime·badsignal(SB), AX 852 CALL AX 853 JMP sigtramp_ret 854 855 // save g 856 MOVL DI, 20(SP) 857 858 // g = m->gsignal 859 MOVL g_m(DI), BX 860 MOVL m_gsignal(BX), BX 861 MOVL BX, g(CX) 862 863 // copy arguments for sighandler 864 MOVL $11, 0(SP) // signal 865 MOVL $0, 4(SP) // siginfo 866 LEAL ctxt+4(FP), AX 867 MOVL AX, 8(SP) // context 868 MOVL DI, 12(SP) // g 869 870 CALL runtime·sighandler(SB) 871 872 // restore g 873 get_tls(CX) 874 MOVL 20(SP), BX 875 MOVL BX, g(CX) 876 877 sigtramp_ret: 878 // Enable exceptions again. 879 CMPL runtime·nacl_irt_is_enabled(SB), $0 880 JNE sigtramp_irt 881 NACL_SYSCALL(SYS_exception_clear_flag) 882 JMP sigtramp_ret2 883 sigtramp_irt: 884 MOVL runtime·nacl_irt_exception_handling_v0_1+(IRT_EXCEPTION_CLEAR*4)(SB), AX 885 CALL AX 886 sigtramp_ret2: 887 888 // NaCl has abdicated its traditional operating system responsibility 889 // and declined to implement 'sigreturn'. Instead the only way to return 890 // to the execution of our program is to restore the registers ourselves. 891 // Unfortunately, that is impossible to do with strict fidelity, because 892 // there is no way to do the final update of PC that ends the sequence 893 // without either (1) jumping to a register, in which case the register ends 894 // holding the PC value instead of its intended value or (2) storing the PC 895 // on the stack and using RET, which imposes the requirement that SP is 896 // valid and that is okay to smash the word below it. The second would 897 // normally be the lesser of the two evils, except that on NaCl, the linker 898 // must rewrite RET into "POP reg; AND $~31, reg; JMP reg", so either way 899 // we are going to lose a register as a result of the incoming signal. 900 // Similarly, there is no way to restore EFLAGS; the usual way is to use 901 // POPFL, but NaCl rejects that instruction. We could inspect the bits and 902 // execute a sequence of instructions designed to recreate those flag 903 // settings, but that's a lot of work. 904 // 905 // Thankfully, Go's signal handlers never try to return directly to the 906 // executing code, so all the registers and EFLAGS are dead and can be 907 // smashed. The only registers that matter are the ones that are setting 908 // up for the simulated call that the signal handler has created. 909 // Today those registers are just PC and SP, but in case additional registers 910 // are relevant in the future (for example DX is the Go func context register) 911 // we restore as many registers as possible. 912 // 913 // We smash BP, because that's what the linker smashes during RET. 914 // 915 LEAL ctxt+4(FP), BP 916 ADDL $64, BP 917 MOVL 0(BP), AX 918 MOVL 4(BP), CX 919 MOVL 8(BP), DX 920 MOVL 12(BP), BX 921 MOVL 16(BP), SP 922 // 20(BP) is saved BP, never to be seen again 923 MOVL 24(BP), SI 924 MOVL 28(BP), DI 925 // 36(BP) is saved EFLAGS, never to be seen again 926 MOVL 32(BP), BP // saved PC 927 JMP BP 928 929 #define AT_SYSINFO 32 930 TEXT runtime·nacl_sysinfo(SB),NOSPLIT,$16 931 // nacl_irt_query is passed via Elf aux vector, which starts at 932 // argv[argc + envc + 2]; 933 // 934 // typedef struct { 935 // int32 a_type; /* Entry type */ 936 // union { 937 // int32 a_val; /* Integer value */ 938 // } a_un; 939 // } Elf32_auxv_t; 940 // 941 MOVL di+0(FP), DI 942 LEAL 12(DI), BX // argv 943 MOVL 8(DI), AX // argc 944 ADDL 4(DI), AX // envc 945 ADDL $2, AX 946 LEAL (BX)(AX*4), BX // BX = &argv[argc + envc + 2] 947 MOVL BX, runtime·nacl_irt_query(SB) 948 auxloop: 949 MOVL 0(BX), DX // DX = BX->a_type 950 CMPL DX, $0 951 JE no_irt 952 CMPL DX, $AT_SYSINFO 953 JEQ auxfound 954 ADDL $8, BX 955 JMP auxloop 956 auxfound: 957 MOVL 4(BX), BX 958 MOVL BX, runtime·nacl_irt_query(SB) 959 LEAL runtime·nacl_irt_entries(SB), BX 960 queryloop: 961 MOVL 0(BX), AX // name 962 TESTL AX, AX 963 JE irt_done 964 MOVL AX, 0(SP) 965 MOVL 4(BX), AX // funtab 966 MOVL AX, 4(SP) 967 MOVL 8(BX), AX // size 968 MOVL AX, 8(SP) 969 ADDL $16, BX 970 MOVL runtime·nacl_irt_query(SB), AX 971 CALL AX 972 TESTL AX, AX 973 JNE queryloop 974 CMPL -4(BX), $0 // is_required 975 JE queryloop 976 CALL runtime·crash(SB) 977 no_irt: 978 MOVL $0, runtime·nacl_irt_is_enabled(SB) 979 RET 980 irt_done: 981 MOVL $1, runtime·nacl_irt_is_enabled(SB) 982 RET