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