github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/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 time·now(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+0(FP) 210 MOVW $0, R1 211 MOVW R1, loc+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 // TODO: Rewrite to use FP references. Vet complains. 239 MOVW 4(R13), R0 240 MOVW 8(R13), R1 241 MOVW 12(R13), R2 242 MOVW 16(R13), R3 243 MOVW 20(R13), R4 244 MOVW 24(R13), R5 245 MOVW $SYS_futex, R7 246 SWI $0 247 MOVW R0, ret+24(FP) 248 RET 249 250 // int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void)); 251 TEXT runtime·clone(SB),NOSPLIT,$0 252 MOVW flags+0(FP), R0 253 MOVW stk+4(FP), R1 254 MOVW $0, R2 // parent tid ptr 255 MOVW $0, R3 // tls_val 256 MOVW $0, R4 // child tid ptr 257 MOVW $0, R5 258 259 // Copy mp, gp, fn off parent stack for use by child. 260 // TODO(kaib): figure out which registers are clobbered by clone and avoid stack copying 261 MOVW $-16(R1), R1 262 MOVW mm+8(FP), R6 263 MOVW R6, 0(R1) 264 MOVW gg+12(FP), R6 265 MOVW R6, 4(R1) 266 MOVW fn+16(FP), R6 267 MOVW R6, 8(R1) 268 MOVW $1234, R6 269 MOVW R6, 12(R1) 270 271 MOVW $SYS_clone, R7 272 SWI $0 273 274 // In parent, return. 275 CMP $0, R0 276 BEQ 3(PC) 277 MOVW R0, ret+20(FP) 278 RET 279 280 // Paranoia: check that SP is as we expect. Use R13 to avoid linker 'fixup' 281 MOVW 12(R13), R0 282 MOVW $1234, R1 283 CMP R0, R1 284 BEQ 2(PC) 285 BL runtime·abort(SB) 286 287 MOVW 0(R13), R8 // m 288 MOVW 4(R13), R0 // g 289 290 CMP $0, R8 291 BEQ nog 292 CMP $0, R0 293 BEQ nog 294 295 MOVW R0, g 296 MOVW R8, g_m(g) 297 298 // paranoia; check they are not nil 299 MOVW 0(R8), R0 300 MOVW 0(g), R0 301 302 BL runtime·emptyfunc(SB) // fault if stack check is wrong 303 304 // Initialize m->procid to Linux tid 305 MOVW $SYS_gettid, R7 306 SWI $0 307 MOVW g_m(g), R8 308 MOVW R0, m_procid(R8) 309 310 nog: 311 // Call fn 312 MOVW 8(R13), R0 313 MOVW $16(R13), R13 314 BL (R0) 315 316 // It shouldn't return. If it does, exit that thread. 317 SUB $16, R13 // restore the stack pointer to avoid memory corruption 318 MOVW $0, R0 319 MOVW R0, 4(R13) 320 BL runtime·exit1(SB) 321 322 MOVW $1234, R0 323 MOVW $1005, R1 324 MOVW R0, (R1) 325 326 TEXT runtime·sigaltstack(SB),NOSPLIT,$0 327 MOVW new+0(FP), R0 328 MOVW old+4(FP), R1 329 MOVW $SYS_sigaltstack, R7 330 SWI $0 331 MOVW $0xfffff001, R6 332 CMP R6, R0 333 MOVW.HI $0, R8 // crash on syscall failure 334 MOVW.HI R8, (R8) 335 RET 336 337 TEXT runtime·sigfwd(SB),NOSPLIT,$0-16 338 MOVW sig+4(FP), R0 339 MOVW info+8(FP), R1 340 MOVW ctx+12(FP), R2 341 MOVW fn+0(FP), R11 342 MOVW R13, R4 343 SUB $24, R13 344 BIC $0x7, R13 // alignment for ELF ABI 345 BL (R11) 346 MOVW R4, R13 347 RET 348 349 TEXT runtime·sigtramp(SB),NOSPLIT,$12 350 // this might be called in external code context, 351 // where g is not set. 352 // first save R0, because runtime·load_g will clobber it 353 MOVW R0, 4(R13) 354 MOVB runtime·iscgo(SB), R0 355 CMP $0, R0 356 BL.NE runtime·load_g(SB) 357 358 MOVW R1, 8(R13) 359 MOVW R2, 12(R13) 360 MOVW $runtime·sigtrampgo(SB), R11 361 BL (R11) 362 RET 363 364 TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 365 MOVW $runtime·sigtramp(SB), R11 366 B (R11) 367 368 TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0 369 MOVW sig+0(FP), R0 370 MOVW new+4(FP), R1 371 MOVW old+8(FP), R2 372 MOVW size+12(FP), R3 373 MOVW $SYS_rt_sigprocmask, R7 374 SWI $0 375 RET 376 377 TEXT runtime·rt_sigaction(SB),NOSPLIT,$0 378 MOVW sig+0(FP), R0 379 MOVW new+4(FP), R1 380 MOVW old+8(FP), R2 381 MOVW size+12(FP), R3 382 MOVW $SYS_rt_sigaction, R7 383 SWI $0 384 MOVW R0, ret+16(FP) 385 RET 386 387 TEXT runtime·usleep(SB),NOSPLIT,$12 388 MOVW usec+0(FP), R0 389 CALL runtime·usplitR0(SB) 390 MOVW R0, 4(R13) 391 MOVW R1, 8(R13) 392 MOVW $0, R0 393 MOVW $0, R1 394 MOVW $0, R2 395 MOVW $0, R3 396 MOVW $4(R13), R4 397 MOVW $SYS_select, R7 398 SWI $0 399 RET 400 401 // As for cas, memory barriers are complicated on ARM, but the kernel 402 // provides a user helper. ARMv5 does not support SMP and has no 403 // memory barrier instruction at all. ARMv6 added SMP support and has 404 // a memory barrier, but it requires writing to a coprocessor 405 // register. ARMv7 introduced the DMB instruction, but it's expensive 406 // even on single-core devices. The kernel helper takes care of all of 407 // this for us. 408 409 TEXT publicationBarrier<>(SB),NOSPLIT,$0 410 // void __kuser_memory_barrier(void); 411 MOVW $0xffff0fa0, R15 // R15 is hardware PC. 412 413 TEXT ·publicationBarrier(SB),NOSPLIT,$0 414 BL publicationBarrier<>(SB) 415 RET 416 417 TEXT runtime·osyield(SB),NOSPLIT,$0 418 MOVW $SYS_sched_yield, R7 419 SWI $0 420 RET 421 422 TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0 423 MOVW pid+0(FP), R0 424 MOVW len+4(FP), R1 425 MOVW buf+8(FP), R2 426 MOVW $SYS_sched_getaffinity, R7 427 SWI $0 428 MOVW R0, ret+12(FP) 429 RET 430 431 // int32 runtime·epollcreate(int32 size) 432 TEXT runtime·epollcreate(SB),NOSPLIT,$0 433 MOVW size+0(FP), R0 434 MOVW $SYS_epoll_create, R7 435 SWI $0 436 MOVW R0, ret+4(FP) 437 RET 438 439 // int32 runtime·epollcreate1(int32 flags) 440 TEXT runtime·epollcreate1(SB),NOSPLIT,$0 441 MOVW flags+0(FP), R0 442 MOVW $SYS_epoll_create1, R7 443 SWI $0 444 MOVW R0, ret+4(FP) 445 RET 446 447 // func epollctl(epfd, op, fd int32, ev *epollEvent) int 448 TEXT runtime·epollctl(SB),NOSPLIT,$0 449 MOVW epfd+0(FP), R0 450 MOVW op+4(FP), R1 451 MOVW fd+8(FP), R2 452 MOVW ev+12(FP), R3 453 MOVW $SYS_epoll_ctl, R7 454 SWI $0 455 MOVW R0, ret+16(FP) 456 RET 457 458 // int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout) 459 TEXT runtime·epollwait(SB),NOSPLIT,$0 460 MOVW epfd+0(FP), R0 461 MOVW ev+4(FP), R1 462 MOVW nev+8(FP), R2 463 MOVW timeout+12(FP), R3 464 MOVW $SYS_epoll_wait, R7 465 SWI $0 466 MOVW R0, ret+16(FP) 467 RET 468 469 // void runtime·closeonexec(int32 fd) 470 TEXT runtime·closeonexec(SB),NOSPLIT,$0 471 MOVW fd+0(FP), R0 // fd 472 MOVW $2, R1 // F_SETFD 473 MOVW $1, R2 // FD_CLOEXEC 474 MOVW $SYS_fcntl, R7 475 SWI $0 476 RET 477 478 // b __kuser_get_tls @ 0xffff0fe0 479 TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4 480 MOVW $0xffff0fe0, R0 481 B (R0) 482 483 TEXT runtime·access(SB),NOSPLIT,$0 484 MOVW name+0(FP), R0 485 MOVW mode+4(FP), R1 486 MOVW $SYS_access, R7 487 SWI $0 488 MOVW R0, ret+8(FP) 489 RET 490 491 TEXT runtime·connect(SB),NOSPLIT,$0 492 MOVW fd+0(FP), R0 493 MOVW addr+4(FP), R1 494 MOVW addrlen+8(FP), R2 495 MOVW $SYS_connect, R7 496 SWI $0 497 MOVW R0, ret+12(FP) 498 RET 499 500 TEXT runtime·socket(SB),NOSPLIT,$0 501 MOVW domain+0(FP), R0 502 MOVW type+4(FP), R1 503 MOVW protocol+8(FP), R2 504 MOVW $SYS_socket, R7 505 SWI $0 506 MOVW R0, ret+12(FP) 507 RET