github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/runtime/sys_linux_arm64.s (about) 1 // Copyright 2014 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 // 6 // System calls and other sys.stuff for arm64, Linux 7 // 8 9 #include "go_asm.h" 10 #include "go_tls.h" 11 #include "textflag.h" 12 #include "cgo/abi_arm64.h" 13 14 #define AT_FDCWD -100 15 16 #define CLOCK_REALTIME 0 17 #define CLOCK_MONOTONIC 1 18 19 #define SYS_exit 93 20 #define SYS_read 63 21 #define SYS_write 64 22 #define SYS_openat 56 23 #define SYS_close 57 24 #define SYS_pipe2 59 25 #define SYS_nanosleep 101 26 #define SYS_mmap 222 27 #define SYS_munmap 215 28 #define SYS_setitimer 103 29 #define SYS_clone 220 30 #define SYS_sched_yield 124 31 #define SYS_rt_sigreturn 139 32 #define SYS_rt_sigaction 134 33 #define SYS_rt_sigprocmask 135 34 #define SYS_sigaltstack 132 35 #define SYS_madvise 233 36 #define SYS_mincore 232 37 #define SYS_getpid 172 38 #define SYS_gettid 178 39 #define SYS_kill 129 40 #define SYS_tgkill 131 41 #define SYS_futex 98 42 #define SYS_sched_getaffinity 123 43 #define SYS_exit_group 94 44 #define SYS_clock_gettime 113 45 #define SYS_faccessat 48 46 #define SYS_socket 198 47 #define SYS_connect 203 48 #define SYS_brk 214 49 #define SYS_timer_create 107 50 #define SYS_timer_settime 110 51 #define SYS_timer_delete 111 52 53 TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4 54 MOVW code+0(FP), R0 55 MOVD $SYS_exit_group, R8 56 SVC 57 RET 58 59 // func exitThread(wait *atomic.Uint32) 60 TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8 61 MOVD wait+0(FP), R0 62 // We're done using the stack. 63 MOVW $0, R1 64 STLRW R1, (R0) 65 MOVW $0, R0 // exit code 66 MOVD $SYS_exit, R8 67 SVC 68 JMP 0(PC) 69 70 TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0-20 71 MOVD $AT_FDCWD, R0 72 MOVD name+0(FP), R1 73 MOVW mode+8(FP), R2 74 MOVW perm+12(FP), R3 75 MOVD $SYS_openat, R8 76 SVC 77 CMN $4095, R0 78 BCC done 79 MOVW $-1, R0 80 done: 81 MOVW R0, ret+16(FP) 82 RET 83 84 TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0-12 85 MOVW fd+0(FP), R0 86 MOVD $SYS_close, R8 87 SVC 88 CMN $4095, R0 89 BCC done 90 MOVW $-1, R0 91 done: 92 MOVW R0, ret+8(FP) 93 RET 94 95 TEXT runtime·write1(SB),NOSPLIT|NOFRAME,$0-28 96 MOVD fd+0(FP), R0 97 MOVD p+8(FP), R1 98 MOVW n+16(FP), R2 99 MOVD $SYS_write, R8 100 SVC 101 MOVW R0, ret+24(FP) 102 RET 103 104 TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0-28 105 MOVW fd+0(FP), R0 106 MOVD p+8(FP), R1 107 MOVW n+16(FP), R2 108 MOVD $SYS_read, R8 109 SVC 110 MOVW R0, ret+24(FP) 111 RET 112 113 // func pipe2(flags int32) (r, w int32, errno int32) 114 TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20 115 MOVD $r+8(FP), R0 116 MOVW flags+0(FP), R1 117 MOVW $SYS_pipe2, R8 118 SVC 119 MOVW R0, errno+16(FP) 120 RET 121 122 TEXT runtime·usleep(SB),NOSPLIT,$24-4 123 MOVWU usec+0(FP), R3 124 MOVD R3, R5 125 MOVW $1000000, R4 126 UDIV R4, R3 127 MOVD R3, 8(RSP) 128 MUL R3, R4 129 SUB R4, R5 130 MOVW $1000, R4 131 MUL R4, R5 132 MOVD R5, 16(RSP) 133 134 // nanosleep(&ts, 0) 135 ADD $8, RSP, R0 136 MOVD $0, R1 137 MOVD $SYS_nanosleep, R8 138 SVC 139 RET 140 141 TEXT runtime·gettid(SB),NOSPLIT,$0-4 142 MOVD $SYS_gettid, R8 143 SVC 144 MOVW R0, ret+0(FP) 145 RET 146 147 TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0 148 MOVD $SYS_getpid, R8 149 SVC 150 MOVW R0, R19 151 MOVD $SYS_gettid, R8 152 SVC 153 MOVW R0, R1 // arg 2 tid 154 MOVW R19, R0 // arg 1 pid 155 MOVW sig+0(FP), R2 // arg 3 156 MOVD $SYS_tgkill, R8 157 SVC 158 RET 159 160 TEXT runtime·raiseproc(SB),NOSPLIT|NOFRAME,$0 161 MOVD $SYS_getpid, R8 162 SVC 163 MOVW R0, R0 // arg 1 pid 164 MOVW sig+0(FP), R1 // arg 2 165 MOVD $SYS_kill, R8 166 SVC 167 RET 168 169 TEXT ·getpid(SB),NOSPLIT|NOFRAME,$0-8 170 MOVD $SYS_getpid, R8 171 SVC 172 MOVD R0, ret+0(FP) 173 RET 174 175 TEXT ·tgkill(SB),NOSPLIT,$0-24 176 MOVD tgid+0(FP), R0 177 MOVD tid+8(FP), R1 178 MOVD sig+16(FP), R2 179 MOVD $SYS_tgkill, R8 180 SVC 181 RET 182 183 TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24 184 MOVW mode+0(FP), R0 185 MOVD new+8(FP), R1 186 MOVD old+16(FP), R2 187 MOVD $SYS_setitimer, R8 188 SVC 189 RET 190 191 TEXT runtime·timer_create(SB),NOSPLIT,$0-28 192 MOVW clockid+0(FP), R0 193 MOVD sevp+8(FP), R1 194 MOVD timerid+16(FP), R2 195 MOVD $SYS_timer_create, R8 196 SVC 197 MOVW R0, ret+24(FP) 198 RET 199 200 TEXT runtime·timer_settime(SB),NOSPLIT,$0-28 201 MOVW timerid+0(FP), R0 202 MOVW flags+4(FP), R1 203 MOVD new+8(FP), R2 204 MOVD old+16(FP), R3 205 MOVD $SYS_timer_settime, R8 206 SVC 207 MOVW R0, ret+24(FP) 208 RET 209 210 TEXT runtime·timer_delete(SB),NOSPLIT,$0-12 211 MOVW timerid+0(FP), R0 212 MOVD $SYS_timer_delete, R8 213 SVC 214 MOVW R0, ret+8(FP) 215 RET 216 217 TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28 218 MOVD addr+0(FP), R0 219 MOVD n+8(FP), R1 220 MOVD dst+16(FP), R2 221 MOVD $SYS_mincore, R8 222 SVC 223 MOVW R0, ret+24(FP) 224 RET 225 226 // func walltime() (sec int64, nsec int32) 227 TEXT runtime·walltime(SB),NOSPLIT,$24-12 228 MOVD RSP, R20 // R20 is unchanged by C code 229 MOVD RSP, R1 230 231 MOVD g_m(g), R21 // R21 = m 232 233 // Set vdsoPC and vdsoSP for SIGPROF traceback. 234 // Save the old values on stack and restore them on exit, 235 // so this function is reentrant. 236 MOVD m_vdsoPC(R21), R2 237 MOVD m_vdsoSP(R21), R3 238 MOVD R2, 8(RSP) 239 MOVD R3, 16(RSP) 240 241 MOVD $ret-8(FP), R2 // caller's SP 242 MOVD LR, m_vdsoPC(R21) 243 MOVD R2, m_vdsoSP(R21) 244 245 MOVD m_curg(R21), R0 246 CMP g, R0 247 BNE noswitch 248 249 MOVD m_g0(R21), R3 250 MOVD (g_sched+gobuf_sp)(R3), R1 // Set RSP to g0 stack 251 252 noswitch: 253 SUB $16, R1 254 BIC $15, R1 // Align for C code 255 MOVD R1, RSP 256 257 MOVW $CLOCK_REALTIME, R0 258 MOVD runtime·vdsoClockgettimeSym(SB), R2 259 CBZ R2, fallback 260 261 // Store g on gsignal's stack, so if we receive a signal 262 // during VDSO code we can find the g. 263 // If we don't have a signal stack, we won't receive signal, 264 // so don't bother saving g. 265 // When using cgo, we already saved g on TLS, also don't save 266 // g here. 267 // Also don't save g if we are already on the signal stack. 268 // We won't get a nested signal. 269 MOVBU runtime·iscgo(SB), R22 270 CBNZ R22, nosaveg 271 MOVD m_gsignal(R21), R22 // g.m.gsignal 272 CBZ R22, nosaveg 273 CMP g, R22 274 BEQ nosaveg 275 MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo 276 MOVD g, (R22) 277 278 BL (R2) 279 280 MOVD ZR, (R22) // clear g slot, R22 is unchanged by C code 281 282 B finish 283 284 nosaveg: 285 BL (R2) 286 B finish 287 288 fallback: 289 MOVD $SYS_clock_gettime, R8 290 SVC 291 292 finish: 293 MOVD 0(RSP), R3 // sec 294 MOVD 8(RSP), R5 // nsec 295 296 MOVD R20, RSP // restore SP 297 // Restore vdsoPC, vdsoSP 298 // We don't worry about being signaled between the two stores. 299 // If we are not in a signal handler, we'll restore vdsoSP to 0, 300 // and no one will care about vdsoPC. If we are in a signal handler, 301 // we cannot receive another signal. 302 MOVD 16(RSP), R1 303 MOVD R1, m_vdsoSP(R21) 304 MOVD 8(RSP), R1 305 MOVD R1, m_vdsoPC(R21) 306 307 MOVD R3, sec+0(FP) 308 MOVW R5, nsec+8(FP) 309 RET 310 311 TEXT runtime·nanotime1(SB),NOSPLIT,$24-8 312 MOVD RSP, R20 // R20 is unchanged by C code 313 MOVD RSP, R1 314 315 MOVD g_m(g), R21 // R21 = m 316 317 // Set vdsoPC and vdsoSP for SIGPROF traceback. 318 // Save the old values on stack and restore them on exit, 319 // so this function is reentrant. 320 MOVD m_vdsoPC(R21), R2 321 MOVD m_vdsoSP(R21), R3 322 MOVD R2, 8(RSP) 323 MOVD R3, 16(RSP) 324 325 MOVD $ret-8(FP), R2 // caller's SP 326 MOVD LR, m_vdsoPC(R21) 327 MOVD R2, m_vdsoSP(R21) 328 329 MOVD m_curg(R21), R0 330 CMP g, R0 331 BNE noswitch 332 333 MOVD m_g0(R21), R3 334 MOVD (g_sched+gobuf_sp)(R3), R1 // Set RSP to g0 stack 335 336 noswitch: 337 SUB $32, R1 338 BIC $15, R1 339 MOVD R1, RSP 340 341 MOVW $CLOCK_MONOTONIC, R0 342 MOVD runtime·vdsoClockgettimeSym(SB), R2 343 CBZ R2, fallback 344 345 // Store g on gsignal's stack, so if we receive a signal 346 // during VDSO code we can find the g. 347 // If we don't have a signal stack, we won't receive signal, 348 // so don't bother saving g. 349 // When using cgo, we already saved g on TLS, also don't save 350 // g here. 351 // Also don't save g if we are already on the signal stack. 352 // We won't get a nested signal. 353 MOVBU runtime·iscgo(SB), R22 354 CBNZ R22, nosaveg 355 MOVD m_gsignal(R21), R22 // g.m.gsignal 356 CBZ R22, nosaveg 357 CMP g, R22 358 BEQ nosaveg 359 MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo 360 MOVD g, (R22) 361 362 BL (R2) 363 364 MOVD ZR, (R22) // clear g slot, R22 is unchanged by C code 365 366 B finish 367 368 nosaveg: 369 BL (R2) 370 B finish 371 372 fallback: 373 MOVD $SYS_clock_gettime, R8 374 SVC 375 376 finish: 377 MOVD 0(RSP), R3 // sec 378 MOVD 8(RSP), R5 // nsec 379 380 MOVD R20, RSP // restore SP 381 // Restore vdsoPC, vdsoSP 382 // We don't worry about being signaled between the two stores. 383 // If we are not in a signal handler, we'll restore vdsoSP to 0, 384 // and no one will care about vdsoPC. If we are in a signal handler, 385 // we cannot receive another signal. 386 MOVD 16(RSP), R1 387 MOVD R1, m_vdsoSP(R21) 388 MOVD 8(RSP), R1 389 MOVD R1, m_vdsoPC(R21) 390 391 // sec is in R3, nsec in R5 392 // return nsec in R3 393 MOVD $1000000000, R4 394 MUL R4, R3 395 ADD R5, R3 396 MOVD R3, ret+0(FP) 397 RET 398 399 TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28 400 MOVW how+0(FP), R0 401 MOVD new+8(FP), R1 402 MOVD old+16(FP), R2 403 MOVW size+24(FP), R3 404 MOVD $SYS_rt_sigprocmask, R8 405 SVC 406 CMN $4095, R0 407 BCC done 408 MOVD $0, R0 409 MOVD R0, (R0) // crash 410 done: 411 RET 412 413 TEXT runtime·rt_sigaction(SB),NOSPLIT|NOFRAME,$0-36 414 MOVD sig+0(FP), R0 415 MOVD new+8(FP), R1 416 MOVD old+16(FP), R2 417 MOVD size+24(FP), R3 418 MOVD $SYS_rt_sigaction, R8 419 SVC 420 MOVW R0, ret+32(FP) 421 RET 422 423 // Call the function stored in _cgo_sigaction using the GCC calling convention. 424 TEXT runtime·callCgoSigaction(SB),NOSPLIT,$0 425 MOVD sig+0(FP), R0 426 MOVD new+8(FP), R1 427 MOVD old+16(FP), R2 428 MOVD _cgo_sigaction(SB), R3 429 SUB $16, RSP // reserve 16 bytes for sp-8 where fp may be saved. 430 BL R3 431 ADD $16, RSP 432 MOVW R0, ret+24(FP) 433 RET 434 435 TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 436 MOVW sig+8(FP), R0 437 MOVD info+16(FP), R1 438 MOVD ctx+24(FP), R2 439 MOVD fn+0(FP), R11 440 BL (R11) 441 RET 442 443 // Called from c-abi, R0: sig, R1: info, R2: cxt 444 TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME,$176 445 // Save callee-save registers in the case of signal forwarding. 446 // Please refer to https://golang.org/issue/31827 . 447 SAVE_R19_TO_R28(8*4) 448 SAVE_F8_TO_F15(8*14) 449 450 // this might be called in external code context, 451 // where g is not set. 452 // first save R0, because runtime·load_g will clobber it 453 MOVW R0, 8(RSP) 454 MOVBU runtime·iscgo(SB), R0 455 CBZ R0, 2(PC) 456 BL runtime·load_g(SB) 457 458 // Restore signum to R0. 459 MOVW 8(RSP), R0 460 // R1 and R2 already contain info and ctx, respectively. 461 MOVD $runtime·sigtrampgo<ABIInternal>(SB), R3 462 BL (R3) 463 464 // Restore callee-save registers. 465 RESTORE_R19_TO_R28(8*4) 466 RESTORE_F8_TO_F15(8*14) 467 468 RET 469 470 // Called from c-abi, R0: sig, R1: info, R2: cxt 471 TEXT runtime·sigprofNonGoWrapper<>(SB),NOSPLIT,$176 472 // Save callee-save registers because it's a callback from c code. 473 SAVE_R19_TO_R28(8*4) 474 SAVE_F8_TO_F15(8*14) 475 476 // R0, R1 and R2 already contain sig, info and ctx, respectively. 477 CALL runtime·sigprofNonGo<ABIInternal>(SB) 478 479 // Restore callee-save registers. 480 RESTORE_R19_TO_R28(8*4) 481 RESTORE_F8_TO_F15(8*14) 482 RET 483 484 // Called from c-abi, R0: sig, R1: info, R2: cxt 485 TEXT runtime·cgoSigtramp(SB),NOSPLIT|NOFRAME,$0 486 // The stack unwinder, presumably written in C, may not be able to 487 // handle Go frame correctly. So, this function is NOFRAME, and we 488 // save/restore LR manually. 489 MOVD LR, R10 490 // Save R27, g because they will be clobbered, 491 // we need to restore them before jump to sigtramp. 492 MOVD R27, R11 493 MOVD g, R12 494 495 // If no traceback function, do usual sigtramp. 496 MOVD runtime·cgoTraceback(SB), R6 497 CBZ R6, sigtramp 498 499 // If no traceback support function, which means that 500 // runtime/cgo was not linked in, do usual sigtramp. 501 MOVD _cgo_callers(SB), R7 502 CBZ R7, sigtramp 503 504 // Figure out if we are currently in a cgo call. 505 // If not, just do usual sigtramp. 506 // first save R0, because runtime·load_g will clobber it. 507 MOVD R0, R8 508 // Set up g register. 509 CALL runtime·load_g(SB) 510 MOVD R8, R0 511 512 CBZ g, sigtrampnog // g == nil 513 MOVD g_m(g), R6 514 CBZ R6, sigtramp // g.m == nil 515 MOVW m_ncgo(R6), R7 516 CBZW R7, sigtramp // g.m.ncgo = 0 517 MOVD m_curg(R6), R8 518 CBZ R8, sigtramp // g.m.curg == nil 519 MOVD g_syscallsp(R8), R7 520 CBZ R7, sigtramp // g.m.curg.syscallsp == 0 521 MOVD m_cgoCallers(R6), R4 // R4 is the fifth arg in C calling convention. 522 CBZ R4, sigtramp // g.m.cgoCallers == nil 523 MOVW m_cgoCallersUse(R6), R8 524 CBNZW R8, sigtramp // g.m.cgoCallersUse != 0 525 526 // Jump to a function in runtime/cgo. 527 // That function, written in C, will call the user's traceback 528 // function with proper unwind info, and will then call back here. 529 // The first three arguments, and the fifth, are already in registers. 530 // Set the two remaining arguments now. 531 MOVD runtime·cgoTraceback(SB), R3 532 MOVD $runtime·sigtramp(SB), R5 533 MOVD _cgo_callers(SB), R13 534 MOVD R10, LR // restore 535 MOVD R11, R27 536 MOVD R12, g 537 B (R13) 538 539 sigtramp: 540 MOVD R10, LR // restore 541 MOVD R11, R27 542 MOVD R12, g 543 B runtime·sigtramp(SB) 544 545 sigtrampnog: 546 // Signal arrived on a non-Go thread. If this is SIGPROF, get a 547 // stack trace. 548 CMPW $27, R0 // 27 == SIGPROF 549 BNE sigtramp 550 551 // Lock sigprofCallersUse (cas from 0 to 1). 552 MOVW $1, R7 553 MOVD $runtime·sigprofCallersUse(SB), R8 554 load_store_loop: 555 LDAXRW (R8), R9 556 CBNZW R9, sigtramp // Skip stack trace if already locked. 557 STLXRW R7, (R8), R9 558 CBNZ R9, load_store_loop 559 560 // Jump to the traceback function in runtime/cgo. 561 // It will call back to sigprofNonGo, which will ignore the 562 // arguments passed in registers. 563 // First three arguments to traceback function are in registers already. 564 MOVD runtime·cgoTraceback(SB), R3 565 MOVD $runtime·sigprofCallers(SB), R4 566 MOVD $runtime·sigprofNonGoWrapper<>(SB), R5 567 MOVD _cgo_callers(SB), R13 568 MOVD R10, LR // restore 569 MOVD R11, R27 570 MOVD R12, g 571 B (R13) 572 573 TEXT runtime·sysMmap(SB),NOSPLIT|NOFRAME,$0 574 MOVD addr+0(FP), R0 575 MOVD n+8(FP), R1 576 MOVW prot+16(FP), R2 577 MOVW flags+20(FP), R3 578 MOVW fd+24(FP), R4 579 MOVW off+28(FP), R5 580 581 MOVD $SYS_mmap, R8 582 SVC 583 CMN $4095, R0 584 BCC ok 585 NEG R0,R0 586 MOVD $0, p+32(FP) 587 MOVD R0, err+40(FP) 588 RET 589 ok: 590 MOVD R0, p+32(FP) 591 MOVD $0, err+40(FP) 592 RET 593 594 // Call the function stored in _cgo_mmap using the GCC calling convention. 595 // This must be called on the system stack. 596 TEXT runtime·callCgoMmap(SB),NOSPLIT,$0 597 MOVD addr+0(FP), R0 598 MOVD n+8(FP), R1 599 MOVW prot+16(FP), R2 600 MOVW flags+20(FP), R3 601 MOVW fd+24(FP), R4 602 MOVW off+28(FP), R5 603 MOVD _cgo_mmap(SB), R9 604 SUB $16, RSP // reserve 16 bytes for sp-8 where fp may be saved. 605 BL R9 606 ADD $16, RSP 607 MOVD R0, ret+32(FP) 608 RET 609 610 TEXT runtime·sysMunmap(SB),NOSPLIT|NOFRAME,$0 611 MOVD addr+0(FP), R0 612 MOVD n+8(FP), R1 613 MOVD $SYS_munmap, R8 614 SVC 615 CMN $4095, R0 616 BCC cool 617 MOVD R0, 0xf0(R0) 618 cool: 619 RET 620 621 // Call the function stored in _cgo_munmap using the GCC calling convention. 622 // This must be called on the system stack. 623 TEXT runtime·callCgoMunmap(SB),NOSPLIT,$0 624 MOVD addr+0(FP), R0 625 MOVD n+8(FP), R1 626 MOVD _cgo_munmap(SB), R9 627 SUB $16, RSP // reserve 16 bytes for sp-8 where fp may be saved. 628 BL R9 629 ADD $16, RSP 630 RET 631 632 TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0 633 MOVD addr+0(FP), R0 634 MOVD n+8(FP), R1 635 MOVW flags+16(FP), R2 636 MOVD $SYS_madvise, R8 637 SVC 638 MOVW R0, ret+24(FP) 639 RET 640 641 // int64 futex(int32 *uaddr, int32 op, int32 val, 642 // struct timespec *timeout, int32 *uaddr2, int32 val2); 643 TEXT runtime·futex(SB),NOSPLIT|NOFRAME,$0 644 MOVD addr+0(FP), R0 645 MOVW op+8(FP), R1 646 MOVW val+12(FP), R2 647 MOVD ts+16(FP), R3 648 MOVD addr2+24(FP), R4 649 MOVW val3+32(FP), R5 650 MOVD $SYS_futex, R8 651 SVC 652 MOVW R0, ret+40(FP) 653 RET 654 655 // int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void)); 656 TEXT runtime·clone(SB),NOSPLIT|NOFRAME,$0 657 MOVW flags+0(FP), R0 658 MOVD stk+8(FP), R1 659 660 // Copy mp, gp, fn off parent stack for use by child. 661 MOVD mp+16(FP), R10 662 MOVD gp+24(FP), R11 663 MOVD fn+32(FP), R12 664 665 MOVD R10, -8(R1) 666 MOVD R11, -16(R1) 667 MOVD R12, -24(R1) 668 MOVD $1234, R10 669 MOVD R10, -32(R1) 670 671 MOVD $SYS_clone, R8 672 SVC 673 674 // In parent, return. 675 CMP ZR, R0 676 BEQ child 677 MOVW R0, ret+40(FP) 678 RET 679 child: 680 681 // In child, on new stack. 682 MOVD -32(RSP), R10 683 MOVD $1234, R0 684 CMP R0, R10 685 BEQ good 686 MOVD $0, R0 687 MOVD R0, (R0) // crash 688 689 good: 690 // Initialize m->procid to Linux tid 691 MOVD $SYS_gettid, R8 692 SVC 693 694 MOVD -24(RSP), R12 // fn 695 MOVD -16(RSP), R11 // g 696 MOVD -8(RSP), R10 // m 697 698 CMP $0, R10 699 BEQ nog 700 CMP $0, R11 701 BEQ nog 702 703 MOVD R0, m_procid(R10) 704 705 // TODO: setup TLS. 706 707 // In child, set up new stack 708 MOVD R10, g_m(R11) 709 MOVD R11, g 710 //CALL runtime·stackcheck(SB) 711 712 nog: 713 // Call fn 714 MOVD R12, R0 715 BL (R0) 716 717 // It shouldn't return. If it does, exit that thread. 718 MOVW $111, R0 719 again: 720 MOVD $SYS_exit, R8 721 SVC 722 B again // keep exiting 723 724 TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0 725 MOVD new+0(FP), R0 726 MOVD old+8(FP), R1 727 MOVD $SYS_sigaltstack, R8 728 SVC 729 CMN $4095, R0 730 BCC ok 731 MOVD $0, R0 732 MOVD R0, (R0) // crash 733 ok: 734 RET 735 736 TEXT runtime·osyield(SB),NOSPLIT|NOFRAME,$0 737 MOVD $SYS_sched_yield, R8 738 SVC 739 RET 740 741 TEXT runtime·sched_getaffinity(SB),NOSPLIT|NOFRAME,$0 742 MOVD pid+0(FP), R0 743 MOVD len+8(FP), R1 744 MOVD buf+16(FP), R2 745 MOVD $SYS_sched_getaffinity, R8 746 SVC 747 MOVW R0, ret+24(FP) 748 RET 749 750 // int access(const char *name, int mode) 751 TEXT runtime·access(SB),NOSPLIT,$0-20 752 MOVD $AT_FDCWD, R0 753 MOVD name+0(FP), R1 754 MOVW mode+8(FP), R2 755 MOVD $SYS_faccessat, R8 756 SVC 757 MOVW R0, ret+16(FP) 758 RET 759 760 // int connect(int fd, const struct sockaddr *addr, socklen_t len) 761 TEXT runtime·connect(SB),NOSPLIT,$0-28 762 MOVW fd+0(FP), R0 763 MOVD addr+8(FP), R1 764 MOVW len+16(FP), R2 765 MOVD $SYS_connect, R8 766 SVC 767 MOVW R0, ret+24(FP) 768 RET 769 770 // int socket(int domain, int typ, int prot) 771 TEXT runtime·socket(SB),NOSPLIT,$0-20 772 MOVW domain+0(FP), R0 773 MOVW typ+4(FP), R1 774 MOVW prot+8(FP), R2 775 MOVD $SYS_socket, R8 776 SVC 777 MOVW R0, ret+16(FP) 778 RET 779 780 // func sbrk0() uintptr 781 TEXT runtime·sbrk0(SB),NOSPLIT,$0-8 782 // Implemented as brk(NULL). 783 MOVD $0, R0 784 MOVD $SYS_brk, R8 785 SVC 786 MOVD R0, ret+0(FP) 787 RET