github.com/fjballest/golang@v0.0.0-20151209143359-e4c5fe594ca8/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 BL (R11) 343 RET 344 345 TEXT runtime·sigtramp(SB),NOSPLIT,$12 346 // this might be called in external code context, 347 // where g is not set. 348 // first save R0, because runtime·load_g will clobber it 349 MOVW R0, 4(R13) 350 MOVB runtime·iscgo(SB), R0 351 CMP $0, R0 352 BL.NE runtime·load_g(SB) 353 354 MOVW R1, 8(R13) 355 MOVW R2, 12(R13) 356 MOVW $runtime·sigtrampgo(SB), R11 357 BL (R11) 358 RET 359 360 TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0 361 MOVW sig+0(FP), R0 362 MOVW new+4(FP), R1 363 MOVW old+8(FP), R2 364 MOVW size+12(FP), R3 365 MOVW $SYS_rt_sigprocmask, R7 366 SWI $0 367 RET 368 369 TEXT runtime·rt_sigaction(SB),NOSPLIT,$0 370 MOVW sig+0(FP), R0 371 MOVW new+4(FP), R1 372 MOVW old+8(FP), R2 373 MOVW size+12(FP), R3 374 MOVW $SYS_rt_sigaction, R7 375 SWI $0 376 MOVW R0, ret+16(FP) 377 RET 378 379 TEXT runtime·usleep(SB),NOSPLIT,$12 380 MOVW usec+0(FP), R0 381 CALL runtime·usplitR0(SB) 382 MOVW R0, 4(R13) 383 MOVW R1, 8(R13) 384 MOVW $0, R0 385 MOVW $0, R1 386 MOVW $0, R2 387 MOVW $0, R3 388 MOVW $4(R13), R4 389 MOVW $SYS_select, R7 390 SWI $0 391 RET 392 393 // As for cas, memory barriers are complicated on ARM, but the kernel 394 // provides a user helper. ARMv5 does not support SMP and has no 395 // memory barrier instruction at all. ARMv6 added SMP support and has 396 // a memory barrier, but it requires writing to a coprocessor 397 // register. ARMv7 introduced the DMB instruction, but it's expensive 398 // even on single-core devices. The kernel helper takes care of all of 399 // this for us. 400 401 TEXT publicationBarrier<>(SB),NOSPLIT,$0 402 // void __kuser_memory_barrier(void); 403 MOVW $0xffff0fa0, R15 // R15 is hardware PC. 404 405 TEXT ·publicationBarrier(SB),NOSPLIT,$0 406 BL publicationBarrier<>(SB) 407 RET 408 409 TEXT runtime·osyield(SB),NOSPLIT,$0 410 MOVW $SYS_sched_yield, R7 411 SWI $0 412 RET 413 414 TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0 415 MOVW pid+0(FP), R0 416 MOVW len+4(FP), R1 417 MOVW buf+8(FP), R2 418 MOVW $SYS_sched_getaffinity, R7 419 SWI $0 420 MOVW R0, ret+12(FP) 421 RET 422 423 // int32 runtime·epollcreate(int32 size) 424 TEXT runtime·epollcreate(SB),NOSPLIT,$0 425 MOVW size+0(FP), R0 426 MOVW $SYS_epoll_create, R7 427 SWI $0 428 MOVW R0, ret+4(FP) 429 RET 430 431 // int32 runtime·epollcreate1(int32 flags) 432 TEXT runtime·epollcreate1(SB),NOSPLIT,$0 433 MOVW flags+0(FP), R0 434 MOVW $SYS_epoll_create1, R7 435 SWI $0 436 MOVW R0, ret+4(FP) 437 RET 438 439 // func epollctl(epfd, op, fd int32, ev *epollEvent) int 440 TEXT runtime·epollctl(SB),NOSPLIT,$0 441 MOVW epfd+0(FP), R0 442 MOVW op+4(FP), R1 443 MOVW fd+8(FP), R2 444 MOVW ev+12(FP), R3 445 MOVW $SYS_epoll_ctl, R7 446 SWI $0 447 MOVW R0, ret+16(FP) 448 RET 449 450 // int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout) 451 TEXT runtime·epollwait(SB),NOSPLIT,$0 452 MOVW epfd+0(FP), R0 453 MOVW ev+4(FP), R1 454 MOVW nev+8(FP), R2 455 MOVW timeout+12(FP), R3 456 MOVW $SYS_epoll_wait, R7 457 SWI $0 458 MOVW R0, ret+16(FP) 459 RET 460 461 // void runtime·closeonexec(int32 fd) 462 TEXT runtime·closeonexec(SB),NOSPLIT,$0 463 MOVW fd+0(FP), R0 // fd 464 MOVW $2, R1 // F_SETFD 465 MOVW $1, R2 // FD_CLOEXEC 466 MOVW $SYS_fcntl, R7 467 SWI $0 468 RET 469 470 // b __kuser_get_tls @ 0xffff0fe0 471 TEXT runtime·read_tls_fallback(SB),NOSPLIT,$-4 472 MOVW $0xffff0fe0, R0 473 B (R0) 474 475 TEXT runtime·access(SB),NOSPLIT,$0 476 MOVW name+0(FP), R0 477 MOVW mode+4(FP), R1 478 MOVW $SYS_access, R7 479 SWI $0 480 MOVW R0, ret+8(FP) 481 RET 482 483 TEXT runtime·connect(SB),NOSPLIT,$0 484 MOVW fd+0(FP), R0 485 MOVW addr+4(FP), R1 486 MOVW addrlen+8(FP), R2 487 MOVW $SYS_connect, R7 488 SWI $0 489 MOVW R0, ret+12(FP) 490 RET 491 492 TEXT runtime·socket(SB),NOSPLIT,$0 493 MOVW domain+0(FP), R0 494 MOVW type+4(FP), R1 495 MOVW protocol+8(FP), R2 496 MOVW $SYS_socket, R7 497 SWI $0 498 MOVW R0, ret+12(FP) 499 RET