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 13 #define AT_FDCWD -100 14 15 #define SYS_exit 93 16 #define SYS_read 63 17 #define SYS_write 64 18 #define SYS_openat 56 19 #define SYS_close 57 20 #define SYS_fcntl 25 21 #define SYS_gettimeofday 169 22 #define SYS_pselect6 72 23 #define SYS_mmap 222 24 #define SYS_munmap 215 25 #define SYS_setitimer 103 26 #define SYS_clone 220 27 #define SYS_sched_yield 124 28 #define SYS_rt_sigreturn 139 29 #define SYS_rt_sigaction 134 30 #define SYS_rt_sigprocmask 135 31 #define SYS_sigaltstack 132 32 #define SYS_getrlimit 163 33 #define SYS_madvise 233 34 #define SYS_mincore 232 35 #define SYS_getpid 172 36 #define SYS_gettid 178 37 #define SYS_kill 129 38 #define SYS_tkill 130 39 #define SYS_futex 98 40 #define SYS_sched_getaffinity 123 41 #define SYS_exit_group 94 42 #define SYS_epoll_create1 20 43 #define SYS_epoll_ctl 21 44 #define SYS_epoll_pwait 22 45 #define SYS_clock_gettime 113 46 #define SYS_faccessat 48 47 #define SYS_socket 198 48 #define SYS_connect 203 49 #define SYS_brk 214 50 51 TEXT runtimeexit(SB),NOSPLIT,$-8-4 52 MOVW code+0(FP), R0 53 MOVD $SYS_exit_group, R8 54 SVC 55 RET 56 57 // func exitThread(wait *uint32) 58 TEXT runtimeexitThread(SB),NOSPLIT,$-8-8 59 MOVD wait+0(FP), R0 60 // We're done using the stack. 61 MOVW $0, R1 62 STLRW R1, (R0) 63 MOVW $0, R0 // exit code 64 MOVD $SYS_exit, R8 65 SVC 66 JMP 0(PC) 67 68 TEXT runtimeopen(SB),NOSPLIT,$-8-20 69 MOVD $AT_FDCWD, R0 70 MOVD name+0(FP), R1 71 MOVW mode+8(FP), R2 72 MOVW perm+12(FP), R3 73 MOVD $SYS_openat, R8 74 SVC 75 CMN $4095, R0 76 BCC done 77 MOVW $-1, R0 78 done: 79 MOVW R0, ret+16(FP) 80 RET 81 82 TEXT runtimeclosefd(SB),NOSPLIT,$-8-12 83 MOVW fd+0(FP), R0 84 MOVD $SYS_close, R8 85 SVC 86 CMN $4095, R0 87 BCC done 88 MOVW $-1, R0 89 done: 90 MOVW R0, ret+8(FP) 91 RET 92 93 TEXT runtimewrite(SB),NOSPLIT,$-8-28 94 MOVD fd+0(FP), R0 95 MOVD p+8(FP), R1 96 MOVW n+16(FP), R2 97 MOVD $SYS_write, R8 98 SVC 99 CMN $4095, R0 100 BCC done 101 MOVW $-1, R0 102 done: 103 MOVW R0, ret+24(FP) 104 RET 105 106 TEXT runtimeread(SB),NOSPLIT,$-8-28 107 MOVW fd+0(FP), R0 108 MOVD p+8(FP), R1 109 MOVW n+16(FP), R2 110 MOVD $SYS_read, R8 111 SVC 112 CMN $4095, R0 113 BCC done 114 MOVW $-1, R0 115 done: 116 MOVW R0, ret+24(FP) 117 RET 118 119 TEXT runtimegetrlimit(SB),NOSPLIT,$-8-20 120 MOVW kind+0(FP), R0 121 MOVD limit+8(FP), R1 122 MOVD $SYS_getrlimit, R8 123 SVC 124 MOVW R0, ret+16(FP) 125 RET 126 127 TEXT runtimeusleep(SB),NOSPLIT,$24-4 128 MOVWU usec+0(FP), R3 129 MOVD R3, R5 130 MOVW $1000000, R4 131 UDIV R4, R3 132 MOVD R3, 8(RSP) 133 MUL R3, R4 134 SUB R4, R5 135 MOVW $1000, R4 136 MUL R4, R5 137 MOVD R5, 16(RSP) 138 139 // pselect6(0, 0, 0, 0, &ts, 0) 140 MOVD $0, R0 141 MOVD R0, R1 142 MOVD R0, R2 143 MOVD R0, R3 144 ADD $8, RSP, R4 145 MOVD R0, R5 146 MOVD $SYS_pselect6, R8 147 SVC 148 RET 149 150 TEXT runtimegettid(SB),NOSPLIT,$0-4 151 MOVD $SYS_gettid, R8 152 SVC 153 MOVW R0, ret+0(FP) 154 RET 155 156 TEXT runtimeraise(SB),NOSPLIT,$-8 157 MOVD $SYS_gettid, R8 158 SVC 159 MOVW R0, R0 // arg 1 tid 160 MOVW sig+0(FP), R1 // arg 2 161 MOVD $SYS_tkill, R8 162 SVC 163 RET 164 165 TEXT runtimeraiseproc(SB),NOSPLIT,$-8 166 MOVD $SYS_getpid, R8 167 SVC 168 MOVW R0, R0 // arg 1 pid 169 MOVW sig+0(FP), R1 // arg 2 170 MOVD $SYS_kill, R8 171 SVC 172 RET 173 174 TEXT runtimesetitimer(SB),NOSPLIT,$-8-24 175 MOVW mode+0(FP), R0 176 MOVD new+8(FP), R1 177 MOVD old+16(FP), R2 178 MOVD $SYS_setitimer, R8 179 SVC 180 RET 181 182 TEXT runtimemincore(SB),NOSPLIT,$-8-28 183 MOVD addr+0(FP), R0 184 MOVD n+8(FP), R1 185 MOVD dst+16(FP), R2 186 MOVD $SYS_mincore, R8 187 SVC 188 MOVW R0, ret+24(FP) 189 RET 190 191 // func walltime() (sec int64, nsec int32) 192 TEXT runtimewalltime(SB),NOSPLIT,$24-12 193 MOVW $0, R0 // CLOCK_REALTIME 194 MOVD RSP, R1 195 MOVD $SYS_clock_gettime, R8 196 SVC 197 MOVD 0(RSP), R3 // sec 198 MOVD 8(RSP), R5 // nsec 199 MOVD R3, sec+0(FP) 200 MOVW R5, nsec+8(FP) 201 RET 202 203 TEXT runtimenanotime(SB),NOSPLIT,$24-8 204 MOVW $1, R0 // CLOCK_MONOTONIC 205 MOVD RSP, R1 206 MOVD $SYS_clock_gettime, R8 207 SVC 208 MOVD 0(RSP), R3 // sec 209 MOVD 8(RSP), R5 // nsec 210 // sec is in R3, nsec in R5 211 // return nsec in R3 212 MOVD $1000000000, R4 213 MUL R4, R3 214 ADD R5, R3 215 MOVD R3, ret+0(FP) 216 RET 217 218 TEXT runtimertsigprocmask(SB),NOSPLIT,$-8-28 219 MOVW how+0(FP), R0 220 MOVD new+8(FP), R1 221 MOVD old+16(FP), R2 222 MOVW size+24(FP), R3 223 MOVD $SYS_rt_sigprocmask, R8 224 SVC 225 CMN $4095, R0 226 BCC done 227 MOVD $0, R0 228 MOVD R0, (R0) // crash 229 done: 230 RET 231 232 TEXT runtimert_sigaction(SB),NOSPLIT,$-8-36 233 MOVD sig+0(FP), R0 234 MOVD new+8(FP), R1 235 MOVD old+16(FP), R2 236 MOVD size+24(FP), R3 237 MOVD $SYS_rt_sigaction, R8 238 SVC 239 MOVW R0, ret+32(FP) 240 RET 241 242 TEXT runtimesigfwd(SB),NOSPLIT,$0-32 243 MOVW sig+8(FP), R0 244 MOVD info+16(FP), R1 245 MOVD ctx+24(FP), R2 246 MOVD fn+0(FP), R11 247 BL (R11) 248 RET 249 250 TEXT runtimesigtramp(SB),NOSPLIT,$24 251 // this might be called in external code context, 252 // where g is not set. 253 // first save R0, because runtimeload_g will clobber it 254 MOVW R0, 8(RSP) 255 MOVBU runtimeiscgo(SB), R0 256 CMP $0, R0 257 BEQ 2(PC) 258 BL runtimeload_g(SB) 259 260 MOVD R1, 16(RSP) 261 MOVD R2, 24(RSP) 262 MOVD $runtimesigtrampgo(SB), R0 263 BL (R0) 264 RET 265 266 TEXT runtimecgoSigtramp(SB),NOSPLIT,$0 267 MOVD $runtimesigtramp(SB), R3 268 B (R3) 269 270 TEXT runtimemmap(SB),NOSPLIT,$-8 271 MOVD addr+0(FP), R0 272 MOVD n+8(FP), R1 273 MOVW prot+16(FP), R2 274 MOVW flags+20(FP), R3 275 MOVW fd+24(FP), R4 276 MOVW off+28(FP), R5 277 278 MOVD $SYS_mmap, R8 279 SVC 280 CMN $4095, R0 281 BCC ok 282 NEG R0,R0 283 MOVD $0, p+32(FP) 284 MOVD R0, err+40(FP) 285 RET 286 ok: 287 MOVD R0, p+32(FP) 288 MOVD $0, err+40(FP) 289 RET 290 291 TEXT runtimemunmap(SB),NOSPLIT,$-8 292 MOVD addr+0(FP), R0 293 MOVD n+8(FP), R1 294 MOVD $SYS_munmap, R8 295 SVC 296 CMN $4095, R0 297 BCC cool 298 MOVD R0, 0xf0(R0) 299 cool: 300 RET 301 302 TEXT runtimemadvise(SB),NOSPLIT,$-8 303 MOVD addr+0(FP), R0 304 MOVD n+8(FP), R1 305 MOVW flags+16(FP), R2 306 MOVD $SYS_madvise, R8 307 SVC 308 // ignore failure - maybe pages are locked 309 RET 310 311 // int64 futex(int32 *uaddr, int32 op, int32 val, 312 // struct timespec *timeout, int32 *uaddr2, int32 val2); 313 TEXT runtimefutex(SB),NOSPLIT,$-8 314 MOVD addr+0(FP), R0 315 MOVW op+8(FP), R1 316 MOVW val+12(FP), R2 317 MOVD ts+16(FP), R3 318 MOVD addr2+24(FP), R4 319 MOVW val3+32(FP), R5 320 MOVD $SYS_futex, R8 321 SVC 322 MOVW R0, ret+40(FP) 323 RET 324 325 // int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void)); 326 TEXT runtimeclone(SB),NOSPLIT,$-8 327 MOVW flags+0(FP), R0 328 MOVD stk+8(FP), R1 329 330 // Copy mp, gp, fn off parent stack for use by child. 331 MOVD mp+16(FP), R10 332 MOVD gp+24(FP), R11 333 MOVD fn+32(FP), R12 334 335 MOVD R10, -8(R1) 336 MOVD R11, -16(R1) 337 MOVD R12, -24(R1) 338 MOVD $1234, R10 339 MOVD R10, -32(R1) 340 341 MOVD $SYS_clone, R8 342 SVC 343 344 // In parent, return. 345 CMP ZR, R0 346 BEQ child 347 MOVW R0, ret+40(FP) 348 RET 349 child: 350 351 // In child, on new stack. 352 MOVD -32(RSP), R10 353 MOVD $1234, R0 354 CMP R0, R10 355 BEQ good 356 MOVD $0, R0 357 MOVD R0, (R0) // crash 358 359 good: 360 // Initialize m->procid to Linux tid 361 MOVD $SYS_gettid, R8 362 SVC 363 364 MOVD -24(RSP), R12 // fn 365 MOVD -16(RSP), R11 // g 366 MOVD -8(RSP), R10 // m 367 368 CMP $0, R10 369 BEQ nog 370 CMP $0, R11 371 BEQ nog 372 373 MOVD R0, m_procid(R10) 374 375 // TODO: setup TLS. 376 377 // In child, set up new stack 378 MOVD R10, g_m(R11) 379 MOVD R11, g 380 //CALL runtimestackcheck(SB) 381 382 nog: 383 // Call fn 384 MOVD R12, R0 385 BL (R0) 386 387 // It shouldn't return. If it does, exit that thread. 388 MOVW $111, R0 389 again: 390 MOVD $SYS_exit, R8 391 SVC 392 B again // keep exiting 393 394 TEXT runtimesigaltstack(SB),NOSPLIT,$-8 395 MOVD new+0(FP), R0 396 MOVD old+8(FP), R1 397 MOVD $SYS_sigaltstack, R8 398 SVC 399 CMN $4095, R0 400 BCC ok 401 MOVD $0, R0 402 MOVD R0, (R0) // crash 403 ok: 404 RET 405 406 TEXT runtimeosyield(SB),NOSPLIT,$-8 407 MOVD $SYS_sched_yield, R8 408 SVC 409 RET 410 411 TEXT runtimesched_getaffinity(SB),NOSPLIT,$-8 412 MOVD pid+0(FP), R0 413 MOVD len+8(FP), R1 414 MOVD buf+16(FP), R2 415 MOVD $SYS_sched_getaffinity, R8 416 SVC 417 MOVW R0, ret+24(FP) 418 RET 419 420 // int32 runtimeepollcreate(int32 size); 421 TEXT runtimeepollcreate(SB),NOSPLIT,$-8 422 MOVW $0, R0 423 MOVD $SYS_epoll_create1, R8 424 SVC 425 MOVW R0, ret+8(FP) 426 RET 427 428 // int32 runtimeepollcreate1(int32 flags); 429 TEXT runtimeepollcreate1(SB),NOSPLIT,$-8 430 MOVW flags+0(FP), R0 431 MOVD $SYS_epoll_create1, R8 432 SVC 433 MOVW R0, ret+8(FP) 434 RET 435 436 // func epollctl(epfd, op, fd int32, ev *epollEvent) int 437 TEXT runtimeepollctl(SB),NOSPLIT,$-8 438 MOVW epfd+0(FP), R0 439 MOVW op+4(FP), R1 440 MOVW fd+8(FP), R2 441 MOVD ev+16(FP), R3 442 MOVD $SYS_epoll_ctl, R8 443 SVC 444 MOVW R0, ret+24(FP) 445 RET 446 447 // int32 runtimeepollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout); 448 TEXT runtimeepollwait(SB),NOSPLIT,$-8 449 MOVW epfd+0(FP), R0 450 MOVD ev+8(FP), R1 451 MOVW nev+16(FP), R2 452 MOVW timeout+20(FP), R3 453 MOVD $0, R4 454 MOVD $SYS_epoll_pwait, R8 455 SVC 456 MOVW R0, ret+24(FP) 457 RET 458 459 // void runtimecloseonexec(int32 fd); 460 TEXT runtimecloseonexec(SB),NOSPLIT,$-8 461 MOVW fd+0(FP), R0 // fd 462 MOVD $2, R1 // F_SETFD 463 MOVD $1, R2 // FD_CLOEXEC 464 MOVD $SYS_fcntl, R8 465 SVC 466 RET 467 468 // int access(const char *name, int mode) 469 TEXT runtimeaccess(SB),NOSPLIT,$0-20 470 MOVD $AT_FDCWD, R0 471 MOVD name+0(FP), R1 472 MOVW mode+8(FP), R2 473 MOVD $SYS_faccessat, R8 474 SVC 475 MOVW R0, ret+16(FP) 476 RET 477 478 // int connect(int fd, const struct sockaddr *addr, socklen_t len) 479 TEXT runtimeconnect(SB),NOSPLIT,$0-28 480 MOVW fd+0(FP), R0 481 MOVD addr+8(FP), R1 482 MOVW len+16(FP), R2 483 MOVD $SYS_connect, R8 484 SVC 485 MOVW R0, ret+24(FP) 486 RET 487 488 // int socket(int domain, int typ, int prot) 489 TEXT runtimesocket(SB),NOSPLIT,$0-20 490 MOVW domain+0(FP), R0 491 MOVW typ+4(FP), R1 492 MOVW prot+8(FP), R2 493 MOVD $SYS_socket, R8 494 SVC 495 MOVW R0, ret+16(FP) 496 RET 497 498 // func sbrk0() uintptr 499 TEXT runtimesbrk0(SB),NOSPLIT,$0-8 500 // Implemented as brk(NULL). 501 MOVD $0, R0 502 MOVD $SYS_brk, R8 503 SVC 504 MOVD R0, ret+0(FP) 505 RET 506