github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/src/runtime/sys_linux_arm.s (about) 1 // Copyright 2009 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 arm, Linux 7 // 8 9 #include "go_asm.h" 10 #include "go_tls.h" 11 #include "textflag.h" 12 13 // for EABI, as we don't support OABI 14 #define SYS_BASE 0x0 15 16 #define SYS_exit (SYS_BASE + 1) 17 #define SYS_read (SYS_BASE + 3) 18 #define SYS_write (SYS_BASE + 4) 19 #define SYS_open (SYS_BASE + 5) 20 #define SYS_close (SYS_BASE + 6) 21 #define SYS_getpid (SYS_BASE + 20) 22 #define SYS_kill (SYS_BASE + 37) 23 #define SYS_gettimeofday (SYS_BASE + 78) 24 #define SYS_clone (SYS_BASE + 120) 25 #define SYS_rt_sigreturn (SYS_BASE + 173) 26 #define SYS_rt_sigaction (SYS_BASE + 174) 27 #define SYS_rt_sigprocmask (SYS_BASE + 175) 28 #define SYS_sigaltstack (SYS_BASE + 186) 29 #define SYS_mmap2 (SYS_BASE + 192) 30 #define SYS_futex (SYS_BASE + 240) 31 #define SYS_exit_group (SYS_BASE + 248) 32 #define SYS_munmap (SYS_BASE + 91) 33 #define SYS_madvise (SYS_BASE + 220) 34 #define SYS_setitimer (SYS_BASE + 104) 35 #define SYS_mincore (SYS_BASE + 219) 36 #define SYS_gettid (SYS_BASE + 224) 37 #define SYS_tkill (SYS_BASE + 238) 38 #define SYS_sched_yield (SYS_BASE + 158) 39 #define SYS_pselect6 (SYS_BASE + 335) 40 #define SYS_ugetrlimit (SYS_BASE + 191) 41 #define SYS_sched_getaffinity (SYS_BASE + 242) 42 #define SYS_clock_gettime (SYS_BASE + 263) 43 #define SYS_epoll_create (SYS_BASE + 250) 44 #define SYS_epoll_ctl (SYS_BASE + 251) 45 #define SYS_epoll_wait (SYS_BASE + 252) 46 #define SYS_epoll_create1 (SYS_BASE + 357) 47 #define SYS_fcntl (SYS_BASE + 55) 48 #define SYS_access (SYS_BASE + 33) 49 #define SYS_connect (SYS_BASE + 283) 50 #define SYS_socket (SYS_BASE + 281) 51 #define SYS_brk (SYS_BASE + 45) 52 53 #define ARM_BASE (SYS_BASE + 0x0f0000) 54 55 TEXT runtime·open(SB),NOSPLIT,$0 56 MOVW name+0(FP), R0 57 MOVW mode+4(FP), R1 58 MOVW perm+8(FP), R2 59 MOVW $SYS_open, R7 60 SWI $0 61 MOVW $0xfffff001, R1 62 CMP R1, R0 63 MOVW.HI $-1, R0 64 MOVW R0, ret+12(FP) 65 RET 66 67 TEXT runtime·closefd(SB),NOSPLIT,$0 68 MOVW fd+0(FP), R0 69 MOVW $SYS_close, R7 70 SWI $0 71 MOVW $0xfffff001, R1 72 CMP R1, R0 73 MOVW.HI $-1, R0 74 MOVW R0, ret+4(FP) 75 RET 76 77 TEXT runtime·write(SB),NOSPLIT,$0 78 MOVW fd+0(FP), R0 79 MOVW p+4(FP), R1 80 MOVW n+8(FP), R2 81 MOVW $SYS_write, R7 82 SWI $0 83 MOVW $0xfffff001, R1 84 CMP R1, R0 85 MOVW.HI $-1, R0 86 MOVW R0, ret+12(FP) 87 RET 88 89 TEXT runtime·read(SB),NOSPLIT,$0 90 MOVW fd+0(FP), R0 91 MOVW p+4(FP), R1 92 MOVW n+8(FP), R2 93 MOVW $SYS_read, R7 94 SWI $0 95 MOVW $0xfffff001, R1 96 CMP R1, R0 97 MOVW.HI $-1, R0 98 MOVW R0, ret+12(FP) 99 RET 100 101 TEXT runtime·getrlimit(SB),NOSPLIT,$0 102 MOVW kind+0(FP), R0 103 MOVW limit+4(FP), R1 104 MOVW $SYS_ugetrlimit, R7 105 SWI $0 106 MOVW R0, ret+8(FP) 107 RET 108 109 TEXT runtime·exit(SB),NOSPLIT,$-4 110 MOVW code+0(FP), R0 111 MOVW $SYS_exit_group, R7 112 SWI $0 113 MOVW $1234, R0 114 MOVW $1002, R1 115 MOVW R0, (R1) // fail hard 116 117 TEXT exit1<>(SB),NOSPLIT,$-4 118 MOVW code+0(FP), R0 119 MOVW $SYS_exit, R7 120 SWI $0 121 MOVW $1234, R0 122 MOVW $1003, R1 123 MOVW R0, (R1) // fail hard 124 125 // func exitThread(wait *uint32) 126 TEXT runtime·exitThread(SB),NOSPLIT,$-4-4 127 MOVW wait+0(FP), R0 128 // We're done using the stack. 129 // Alas, there's no reliable way to make this write atomic 130 // without potentially using the stack. So it goes. 131 MOVW $0, R1 132 MOVW R1, (R0) 133 MOVW $0, R0 // exit code 134 MOVW $SYS_exit, R7 135 SWI $0 136 MOVW $1234, R0 137 MOVW $1004, R1 138 MOVW R0, (R1) // fail hard 139 JMP 0(PC) 140 141 TEXT runtime·gettid(SB),NOSPLIT,$0-4 142 MOVW $SYS_gettid, R7 143 SWI $0 144 MOVW R0, ret+0(FP) 145 RET 146 147 TEXT runtime·raise(SB),NOSPLIT,$-4 148 MOVW $SYS_gettid, R7 149 SWI $0 150 // arg 1 tid already in R0 from gettid 151 MOVW sig+0(FP), R1 // arg 2 - signal 152 MOVW $SYS_tkill, R7 153 SWI $0 154 RET 155 156 TEXT runtime·raiseproc(SB),NOSPLIT,$-4 157 MOVW $SYS_getpid, R7 158 SWI $0 159 // arg 1 tid already in R0 from getpid 160 MOVW sig+0(FP), R1 // arg 2 - signal 161 MOVW $SYS_kill, R7 162 SWI $0 163 RET 164 165 TEXT runtime·mmap(SB),NOSPLIT,$0 166 MOVW addr+0(FP), R0 167 MOVW n+4(FP), R1 168 MOVW prot+8(FP), R2 169 MOVW flags+12(FP), R3 170 MOVW fd+16(FP), R4 171 MOVW off+20(FP), R5 172 MOVW $SYS_mmap2, R7 173 SWI $0 174 MOVW $0xfffff001, R6 175 CMP R6, R0 176 MOVW $0, R1 177 RSB.HI $0, R0 178 MOVW.HI R0, R1 // if error, put in R1 179 MOVW.HI $0, R0 180 MOVW R0, p+24(FP) 181 MOVW R1, err+28(FP) 182 RET 183 184 TEXT runtime·munmap(SB),NOSPLIT,$0 185 MOVW addr+0(FP), R0 186 MOVW n+4(FP), R1 187 MOVW $SYS_munmap, R7 188 SWI $0 189 MOVW $0xfffff001, R6 190 CMP R6, R0 191 MOVW.HI $0, R8 // crash on syscall failure 192 MOVW.HI R8, (R8) 193 RET 194 195 TEXT runtime·madvise(SB),NOSPLIT,$0 196 MOVW addr+0(FP), R0 197 MOVW n+4(FP), R1 198 MOVW flags+8(FP), R2 199 MOVW $SYS_madvise, R7 200 SWI $0 201 // ignore failure - maybe pages are locked 202 RET 203 204 TEXT runtime·setitimer(SB),NOSPLIT,$0 205 MOVW mode+0(FP), R0 206 MOVW new+4(FP), R1 207 MOVW old+8(FP), R2 208 MOVW $SYS_setitimer, R7 209 SWI $0 210 RET 211 212 TEXT runtime·mincore(SB),NOSPLIT,$0 213 MOVW addr+0(FP), R0 214 MOVW n+4(FP), R1 215 MOVW dst+8(FP), R2 216 MOVW $SYS_mincore, R7 217 SWI $0 218 MOVW R0, ret+12(FP) 219 RET 220 221 TEXT runtime·walltime(SB), NOSPLIT, $32 222 MOVW $0, R0 // CLOCK_REALTIME 223 MOVW $8(R13), R1 // timespec 224 MOVW $SYS_clock_gettime, R7 225 SWI $0 226 227 MOVW 8(R13), R0 // sec 228 MOVW 12(R13), R2 // nsec 229 230 MOVW R0, sec_lo+0(FP) 231 MOVW $0, R1 232 MOVW R1, sec_hi+4(FP) 233 MOVW R2, nsec+8(FP) 234 RET 235 236 // int64 nanotime(void) 237 TEXT runtime·nanotime(SB),NOSPLIT,$32 238 MOVW $1, R0 // CLOCK_MONOTONIC 239 MOVW $8(R13), R1 // timespec 240 MOVW $SYS_clock_gettime, R7 241 SWI $0 242 243 MOVW 8(R13), R0 // sec 244 MOVW 12(R13), R2 // nsec 245 246 MOVW $1000000000, R3 247 MULLU R0, R3, (R1, R0) 248 MOVW $0, R4 249 ADD.S R2, R0 250 ADC R4, R1 251 252 MOVW R0, ret_lo+0(FP) 253 MOVW R1, ret_hi+4(FP) 254 RET 255 256 // int32 futex(int32 *uaddr, int32 op, int32 val, 257 // struct timespec *timeout, int32 *uaddr2, int32 val2); 258 TEXT runtime·futex(SB),NOSPLIT,$0 259 MOVW addr+0(FP), R0 260 MOVW op+4(FP), R1 261 MOVW val+8(FP), R2 262 MOVW ts+12(FP), R3 263 MOVW addr2+16(FP), R4 264 MOVW val3+20(FP), R5 265 MOVW $SYS_futex, R7 266 SWI $0 267 MOVW R0, ret+24(FP) 268 RET 269 270 // int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void)); 271 TEXT runtime·clone(SB),NOSPLIT,$0 272 MOVW flags+0(FP), R0 273 MOVW stk+4(FP), R1 274 MOVW $0, R2 // parent tid ptr 275 MOVW $0, R3 // tls_val 276 MOVW $0, R4 // child tid ptr 277 MOVW $0, R5 278 279 // Copy mp, gp, fn off parent stack for use by child. 280 // TODO(kaib): figure out which registers are clobbered by clone and avoid stack copying 281 MOVW $-16(R1), R1 282 MOVW mp+8(FP), R6 283 MOVW R6, 0(R1) 284 MOVW gp+12(FP), R6 285 MOVW R6, 4(R1) 286 MOVW fn+16(FP), R6 287 MOVW R6, 8(R1) 288 MOVW $1234, R6 289 MOVW R6, 12(R1) 290 291 MOVW $SYS_clone, R7 292 SWI $0 293 294 // In parent, return. 295 CMP $0, R0 296 BEQ 3(PC) 297 MOVW R0, ret+20(FP) 298 RET 299 300 // Paranoia: check that SP is as we expect. Use R13 to avoid linker 'fixup' 301 MOVW 12(R13), R0 302 MOVW $1234, R1 303 CMP R0, R1 304 BEQ 2(PC) 305 BL runtime·abort(SB) 306 307 MOVW 0(R13), R8 // m 308 MOVW 4(R13), R0 // g 309 310 CMP $0, R8 311 BEQ nog 312 CMP $0, R0 313 BEQ nog 314 315 MOVW R0, g 316 MOVW R8, g_m(g) 317 318 // paranoia; check they are not nil 319 MOVW 0(R8), R0 320 MOVW 0(g), R0 321 322 BL runtime·emptyfunc(SB) // fault if stack check is wrong 323 324 // Initialize m->procid to Linux tid 325 MOVW $SYS_gettid, R7 326 SWI $0 327 MOVW g_m(g), R8 328 MOVW R0, m_procid(R8) 329 330 nog: 331 // Call fn 332 MOVW 8(R13), R0 333 MOVW $16(R13), R13 334 BL (R0) 335 336 // It shouldn't return. If it does, exit that thread. 337 SUB $16, R13 // restore the stack pointer to avoid memory corruption 338 MOVW $0, R0 339 MOVW R0, 4(R13) 340 BL exit1<>(SB) 341 342 MOVW $1234, R0 343 MOVW $1005, R1 344 MOVW R0, (R1) 345 346 TEXT runtime·sigaltstack(SB),NOSPLIT,$0 347 MOVW new+0(FP), R0 348 MOVW old+4(FP), R1 349 MOVW $SYS_sigaltstack, R7 350 SWI $0 351 MOVW $0xfffff001, R6 352 CMP R6, R0 353 MOVW.HI $0, R8 // crash on syscall failure 354 MOVW.HI R8, (R8) 355 RET 356 357 TEXT runtime·sigfwd(SB),NOSPLIT,$0-16 358 MOVW sig+4(FP), R0 359 MOVW info+8(FP), R1 360 MOVW ctx+12(FP), R2 361 MOVW fn+0(FP), R11 362 MOVW R13, R4 363 SUB $24, R13 364 BIC $0x7, R13 // alignment for ELF ABI 365 BL (R11) 366 MOVW R4, R13 367 RET 368 369 TEXT runtime·sigtramp(SB),NOSPLIT,$12 370 // this might be called in external code context, 371 // where g is not set. 372 // first save R0, because runtime·load_g will clobber it 373 MOVW R0, 4(R13) 374 MOVB runtime·iscgo(SB), R0 375 CMP $0, R0 376 BL.NE runtime·load_g(SB) 377 378 MOVW R1, 8(R13) 379 MOVW R2, 12(R13) 380 MOVW $runtime·sigtrampgo(SB), R11 381 BL (R11) 382 RET 383 384 TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 385 MOVW $runtime·sigtramp(SB), R11 386 B (R11) 387 388 TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0 389 MOVW how+0(FP), R0 390 MOVW new+4(FP), R1 391 MOVW old+8(FP), R2 392 MOVW size+12(FP), R3 393 MOVW $SYS_rt_sigprocmask, R7 394 SWI $0 395 RET 396 397 TEXT runtime·rt_sigaction(SB),NOSPLIT,$0 398 MOVW sig+0(FP), R0 399 MOVW new+4(FP), R1 400 MOVW old+8(FP), R2 401 MOVW size+12(FP), R3 402 MOVW $SYS_rt_sigaction, R7 403 SWI $0 404 MOVW R0, ret+16(FP) 405 RET 406 407 TEXT runtime·usleep(SB),NOSPLIT,$12 408 MOVW usec+0(FP), R0 409 CALL runtime·usplitR0(SB) 410 MOVW R0, 4(R13) 411 MOVW $1000, R0 // usec to nsec 412 MUL R0, R1 413 MOVW R1, 8(R13) 414 MOVW $0, R0 415 MOVW $0, R1 416 MOVW $0, R2 417 MOVW $0, R3 418 MOVW $4(R13), R4 419 MOVW $0, R5 420 MOVW $SYS_pselect6, R7 421 SWI $0 422 RET 423 424 // As for cas, memory barriers are complicated on ARM, but the kernel 425 // provides a user helper. ARMv5 does not support SMP and has no 426 // memory barrier instruction at all. ARMv6 added SMP support and has 427 // a memory barrier, but it requires writing to a coprocessor 428 // register. ARMv7 introduced the DMB instruction, but it's expensive 429 // even on single-core devices. The kernel helper takes care of all of 430 // this for us. 431 432 TEXT publicationBarrier<>(SB),NOSPLIT,$0 433 // void __kuser_memory_barrier(void); 434 MOVW $0xffff0fa0, R15 // R15 is hardware PC. 435 436 TEXT ·publicationBarrier(SB),NOSPLIT,$0 437 BL publicationBarrier<>(SB) 438 RET 439 440 TEXT runtime·osyield(SB),NOSPLIT,$0 441 MOVW $SYS_sched_yield, R7 442 SWI $0 443 RET 444 445 TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0 446 MOVW pid+0(FP), R0 447 MOVW len+4(FP), R1 448 MOVW buf+8(FP), R2 449 MOVW $SYS_sched_getaffinity, R7 450 SWI $0 451 MOVW R0, ret+12(FP) 452 RET 453 454 // int32 runtime·epollcreate(int32 size) 455 TEXT runtime·epollcreate(SB),NOSPLIT,$0 456 MOVW size+0(FP), R0 457 MOVW $SYS_epoll_create, R7 458 SWI $0 459 MOVW R0, ret+4(FP) 460 RET 461 462 // int32 runtime·epollcreate1(int32 flags) 463 TEXT runtime·epollcreate1(SB),NOSPLIT,$0 464 MOVW flags+0(FP), R0 465 MOVW $SYS_epoll_create1, R7 466 SWI $0 467 MOVW R0, ret+4(FP) 468 RET 469 470 // func epollctl(epfd, op, fd int32, ev *epollEvent) int 471 TEXT runtime·epollctl(SB),NOSPLIT,$0 472 MOVW epfd+0(FP), R0 473 MOVW op+4(FP), R1 474 MOVW fd+8(FP), R2 475 MOVW ev+12(FP), R3 476 MOVW $SYS_epoll_ctl, R7 477 SWI $0 478 MOVW R0, ret+16(FP) 479 RET 480 481 // int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout) 482 TEXT runtime·epollwait(SB),NOSPLIT,$0 483 MOVW epfd+0(FP), R0 484 MOVW ev+4(FP), R1 485 MOVW nev+8(FP), R2 486 MOVW timeout+12(FP), R3 487 MOVW $SYS_epoll_wait, R7 488 SWI $0 489 MOVW R0, ret+16(FP) 490 RET 491 492 // void runtime·closeonexec(int32 fd) 493 TEXT runtime·closeonexec(SB),NOSPLIT,$0 494 MOVW fd+0(FP), R0 // fd 495 MOVW $2, R1 // F_SETFD 496 MOVW $1, R2 // FD_CLOEXEC 497 MOVW $SYS_fcntl, R7 498 SWI $0 499 RET 500 501 // b __kuser_get_tls @ 0xffff0fe0 502 TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4 503 MOVW $0xffff0fe0, R0 504 B (R0) 505 506 TEXT runtime·access(SB),NOSPLIT,$0 507 MOVW name+0(FP), R0 508 MOVW mode+4(FP), R1 509 MOVW $SYS_access, R7 510 SWI $0 511 MOVW R0, ret+8(FP) 512 RET 513 514 TEXT runtime·connect(SB),NOSPLIT,$0 515 MOVW fd+0(FP), R0 516 MOVW addr+4(FP), R1 517 MOVW len+8(FP), R2 518 MOVW $SYS_connect, R7 519 SWI $0 520 MOVW R0, ret+12(FP) 521 RET 522 523 TEXT runtime·socket(SB),NOSPLIT,$0 524 MOVW domain+0(FP), R0 525 MOVW typ+4(FP), R1 526 MOVW prot+8(FP), R2 527 MOVW $SYS_socket, R7 528 SWI $0 529 MOVW R0, ret+12(FP) 530 RET 531 532 // func sbrk0() uintptr 533 TEXT runtime·sbrk0(SB),NOSPLIT,$0-4 534 // Implemented as brk(NULL). 535 MOVW $0, R0 536 MOVW $SYS_brk, R7 537 SWI $0 538 MOVW R0, ret+0(FP) 539 RET