1 // Copyright 2012 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 // System calls and other sys.stuff for ARM, FreeBSD 6 // /usr/src/sys/kern/syscalls.master for syscall numbers. 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_sigaltstack (SYS_BASE + 53) 24 #define SYS_munmap (SYS_BASE + 73) 25 #define SYS_madvise (SYS_BASE + 75) 26 #define SYS_setitimer (SYS_BASE + 83) 27 #define SYS_fcntl (SYS_BASE + 92) 28 #define SYS_getrlimit (SYS_BASE + 194) 29 #define SYS___sysctl (SYS_BASE + 202) 30 #define SYS_nanosleep (SYS_BASE + 240) 31 #define SYS_clock_gettime (SYS_BASE + 232) 32 #define SYS_sched_yield (SYS_BASE + 331) 33 #define SYS_sigprocmask (SYS_BASE + 340) 34 #define SYS_kqueue (SYS_BASE + 362) 35 #define SYS_kevent (SYS_BASE + 363) 36 #define SYS_sigaction (SYS_BASE + 416) 37 #define SYS_thr_exit (SYS_BASE + 431) 38 #define SYS_thr_self (SYS_BASE + 432) 39 #define SYS_thr_kill (SYS_BASE + 433) 40 #define SYS__umtx_op (SYS_BASE + 454) 41 #define SYS_thr_new (SYS_BASE + 455) 42 #define SYS_mmap (SYS_BASE + 477) 43 44 TEXT runtimesys_umtx_op(SB),NOSPLIT,$0 45 MOVW addr+0(FP), R0 46 MOVW mode+4(FP), R1 47 MOVW val+8(FP), R2 48 MOVW ptr2+12(FP), R3 49 ADD $20, R13 // arg 5 is passed on stack 50 MOVW $SYS__umtx_op, R7 51 SWI $0 52 SUB $20, R13 53 // BCS error 54 MOVW R0, ret+20(FP) 55 RET 56 57 TEXT runtimethr_new(SB),NOSPLIT,$0 58 MOVW param+0(FP), R0 59 MOVW size+4(FP), R1 60 MOVW $SYS_thr_new, R7 61 SWI $0 62 RET 63 64 TEXT runtimethr_start(SB),NOSPLIT,$0 65 // set up g 66 MOVW m_g0(R0), g 67 MOVW R0, g_m(g) 68 BL runtimeemptyfunc(SB) // fault if stack check is wrong 69 BL runtimemstart(SB) 70 71 MOVW $2, R8 // crash (not reached) 72 MOVW R8, (R8) 73 RET 74 75 // Exit the entire program (like C exit) 76 TEXT runtimeexit(SB),NOSPLIT,$-8 77 MOVW code+0(FP), R0 // arg 1 exit status 78 MOVW $SYS_exit, R7 79 SWI $0 80 MOVW.CS $0, R8 // crash on syscall failure 81 MOVW.CS R8, (R8) 82 RET 83 84 TEXT runtimeexit1(SB),NOSPLIT,$-8 85 MOVW code+0(FP), R0 // arg 1 exit status 86 MOVW $SYS_thr_exit, R7 87 SWI $0 88 MOVW.CS $0, R8 // crash on syscall failure 89 MOVW.CS R8, (R8) 90 RET 91 92 TEXT runtimeopen(SB),NOSPLIT,$-8 93 MOVW name+0(FP), R0 // arg 1 name 94 MOVW mode+4(FP), R1 // arg 2 mode 95 MOVW perm+8(FP), R2 // arg 3 perm 96 MOVW $SYS_open, R7 97 SWI $0 98 MOVW.CS $-1, R0 99 MOVW R0, ret+12(FP) 100 RET 101 102 TEXT runtimeread(SB),NOSPLIT,$-8 103 MOVW fd+0(FP), R0 // arg 1 fd 104 MOVW p+4(FP), R1 // arg 2 buf 105 MOVW n+8(FP), R2 // arg 3 count 106 MOVW $SYS_read, R7 107 SWI $0 108 MOVW.CS $-1, R0 109 MOVW R0, ret+12(FP) 110 RET 111 112 TEXT runtimewrite(SB),NOSPLIT,$-8 113 MOVW fd+0(FP), R0 // arg 1 fd 114 MOVW p+4(FP), R1 // arg 2 buf 115 MOVW n+8(FP), R2 // arg 3 count 116 MOVW $SYS_write, R7 117 SWI $0 118 MOVW.CS $-1, R0 119 MOVW R0, ret+12(FP) 120 RET 121 122 TEXT runtimeclosefd(SB),NOSPLIT,$-8 123 MOVW fd+0(FP), R0 // arg 1 fd 124 MOVW $SYS_close, R7 125 SWI $0 126 MOVW.CS $-1, R0 127 MOVW R0, ret+4(FP) 128 RET 129 130 TEXT runtimegetrlimit(SB),NOSPLIT,$-8 131 MOVW kind+0(FP), R0 132 MOVW limit+4(FP), R1 133 MOVW $SYS_getrlimit, R7 134 SWI $0 135 MOVW R0, ret+8(FP) 136 RET 137 138 TEXT runtimeraise(SB),NOSPLIT,$8 139 // thr_self(&4(R13)) 140 MOVW $4(R13), R0 // arg 1 &4(R13) 141 MOVW $SYS_thr_self, R7 142 SWI $0 143 // thr_kill(self, SIGPIPE) 144 MOVW 4(R13), R0 // arg 1 id 145 MOVW sig+0(FP), R1 // arg 2 - signal 146 MOVW $SYS_thr_kill, R7 147 SWI $0 148 RET 149 150 TEXT runtimeraiseproc(SB),NOSPLIT,$0 151 // getpid 152 MOVW $SYS_getpid, R7 153 SWI $0 154 // kill(self, sig) 155 // arg 1 - pid, now in R0 156 MOVW sig+0(FP), R1 // arg 2 - signal 157 MOVW $SYS_kill, R7 158 SWI $0 159 RET 160 161 TEXT runtimesetitimer(SB), NOSPLIT, $-8 162 MOVW mode+0(FP), R0 163 MOVW new+4(FP), R1 164 MOVW old+8(FP), R2 165 MOVW $SYS_setitimer, R7 166 SWI $0 167 RET 168 169 // func now() (sec int64, nsec int32) 170 TEXT timenow(SB), NOSPLIT, $32 171 MOVW $0, R0 // CLOCK_REALTIME 172 MOVW $8(R13), R1 173 MOVW $SYS_clock_gettime, R7 174 SWI $0 175 176 MOVW 8(R13), R0 // sec.low 177 MOVW 12(R13), R1 // sec.high 178 MOVW 16(R13), R2 // nsec 179 180 MOVW R0, sec_lo+0(FP) 181 MOVW R1, sec_hi+4(FP) 182 MOVW R2, nsec+8(FP) 183 RET 184 185 // int64 nanotime(void) so really 186 // void nanotime(int64 *nsec) 187 TEXT runtimenanotime(SB), NOSPLIT, $32 188 // We can use CLOCK_MONOTONIC_FAST here when we drop 189 // support for FreeBSD 8-STABLE. 190 MOVW $4, R0 // CLOCK_MONOTONIC 191 MOVW $8(R13), R1 192 MOVW $SYS_clock_gettime, R7 193 SWI $0 194 195 MOVW 8(R13), R0 // sec.low 196 MOVW 12(R13), R4 // sec.high 197 MOVW 16(R13), R2 // nsec 198 199 MOVW $1000000000, R3 200 MULLU R0, R3, (R1, R0) 201 MUL R3, R4 202 ADD.S R2, R0 203 ADC R4, R1 204 205 MOVW R0, ret_lo+0(FP) 206 MOVW R1, ret_hi+4(FP) 207 RET 208 209 TEXT runtimesigaction(SB),NOSPLIT,$-8 210 MOVW sig+0(FP), R0 // arg 1 sig 211 MOVW new+4(FP), R1 // arg 2 act 212 MOVW old+8(FP), R2 // arg 3 oact 213 MOVW $SYS_sigaction, R7 214 SWI $0 215 MOVW.CS $0, R8 // crash on syscall failure 216 MOVW.CS R8, (R8) 217 RET 218 219 TEXT runtimesigtramp(SB),NOSPLIT,$24 220 // this might be called in external code context, 221 // where g is not set. 222 // first save R0, because runtimeload_g will clobber it 223 MOVW R0, 4(R13) // signum 224 MOVB runtimeiscgo(SB), R0 225 CMP $0, R0 226 BL.NE runtimeload_g(SB) 227 228 CMP $0, g 229 BNE 4(PC) 230 // signal number is already prepared in 4(R13) 231 MOVW $runtimebadsignal(SB), R11 232 BL (R11) 233 RET 234 235 // save g 236 MOVW g, R4 237 MOVW g, 20(R13) 238 239 // g = m->signal 240 MOVW g_m(g), R8 241 MOVW m_gsignal(R8), g 242 243 // R0 is already saved 244 MOVW R1, 8(R13) // info 245 MOVW R2, 12(R13) // context 246 MOVW R4, 16(R13) // oldg 247 248 BL runtimesighandler(SB) 249 250 // restore g 251 MOVW 20(R13), g 252 RET 253 254 TEXT runtimemmap(SB),NOSPLIT,$16 255 MOVW addr+0(FP), R0 // arg 1 addr 256 MOVW n+4(FP), R1 // arg 2 len 257 MOVW prot+8(FP), R2 // arg 3 prot 258 MOVW flags+12(FP), R3 // arg 4 flags 259 // arg 5 (fid) and arg6 (offset_lo, offset_hi) are passed on stack 260 // note the C runtime only passes the 32-bit offset_lo to us 261 MOVW fd+16(FP), R4 // arg 5 262 MOVW R4, 4(R13) 263 MOVW off+20(FP), R5 // arg 6 lower 32-bit 264 // the word at 8(R13) is skipped due to 64-bit argument alignment. 265 MOVW R5, 12(R13) 266 MOVW $0, R6 // higher 32-bit for arg 6 267 MOVW R6, 16(R13) 268 ADD $4, R13 269 MOVW $SYS_mmap, R7 270 SWI $0 271 SUB $4, R13 272 // TODO(dfc) error checking ? 273 MOVW R0, ret+24(FP) 274 RET 275 276 TEXT runtimemunmap(SB),NOSPLIT,$0 277 MOVW addr+0(FP), R0 // arg 1 addr 278 MOVW n+4(FP), R1 // arg 2 len 279 MOVW $SYS_munmap, R7 280 SWI $0 281 MOVW.CS $0, R8 // crash on syscall failure 282 MOVW.CS R8, (R8) 283 RET 284 285 TEXT runtimemadvise(SB),NOSPLIT,$0 286 MOVW addr+0(FP), R0 // arg 1 addr 287 MOVW n+4(FP), R1 // arg 2 len 288 MOVW flags+8(FP), R2 // arg 3 flags 289 MOVW $SYS_madvise, R7 290 SWI $0 291 // ignore failure - maybe pages are locked 292 RET 293 294 TEXT runtimesigaltstack(SB),NOSPLIT,$-8 295 MOVW new+0(FP), R0 296 MOVW old+4(FP), R1 297 MOVW $SYS_sigaltstack, R7 298 SWI $0 299 MOVW.CS $0, R8 // crash on syscall failure 300 MOVW.CS R8, (R8) 301 RET 302 303 TEXT runtimeusleep(SB),NOSPLIT,$16 304 MOVW usec+0(FP), R0 305 CALL runtimeusplitR0(SB) 306 // 0(R13) is the saved LR, don't use it 307 MOVW R0, 4(R13) // tv_sec.low 308 MOVW $0, R0 309 MOVW R0, 8(R13) // tv_sec.high 310 MOVW $1000, R2 311 MUL R1, R2 312 MOVW R2, 12(R13) // tv_nsec 313 314 MOVW $4(R13), R0 // arg 1 - rqtp 315 MOVW $0, R1 // arg 2 - rmtp 316 MOVW $SYS_nanosleep, R7 317 SWI $0 318 RET 319 320 TEXT runtimesysctl(SB),NOSPLIT,$0 321 MOVW mib+0(FP), R0 // arg 1 - name 322 MOVW miblen+4(FP), R1 // arg 2 - namelen 323 MOVW out+8(FP), R2 // arg 3 - old 324 MOVW size+12(FP), R3 // arg 4 - oldlenp 325 // arg 5 (newp) and arg 6 (newlen) are passed on stack 326 ADD $20, R13 327 MOVW $SYS___sysctl, R7 328 SWI $0 329 SUB.CS $0, R0, R0 330 SUB $20, R13 331 MOVW R0, ret+24(FP) 332 RET 333 334 TEXT runtimeosyield(SB),NOSPLIT,$-4 335 MOVW $SYS_sched_yield, R7 336 SWI $0 337 RET 338 339 TEXT runtimesigprocmask(SB),NOSPLIT,$0 340 MOVW how+0(FP), R0 // arg 1 - how 341 MOVW new+4(FP), R1 // arg 2 - set 342 MOVW old+8(FP), R2 // arg 3 - oset 343 MOVW $SYS_sigprocmask, R7 344 SWI $0 345 MOVW.CS $0, R8 // crash on syscall failure 346 MOVW.CS R8, (R8) 347 RET 348 349 // int32 runtimekqueue(void) 350 TEXT runtimekqueue(SB),NOSPLIT,$0 351 MOVW $SYS_kqueue, R7 352 SWI $0 353 RSB.CS $0, R0 354 MOVW R0, ret+0(FP) 355 RET 356 357 // int32 runtimekevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout) 358 TEXT runtimekevent(SB),NOSPLIT,$0 359 MOVW kq+0(FP), R0 // kq 360 MOVW ch+4(FP), R1 // changelist 361 MOVW nch+8(FP), R2 // nchanges 362 MOVW ev+12(FP), R3 // eventlist 363 ADD $20, R13 // pass arg 5 and 6 on stack 364 MOVW $SYS_kevent, R7 365 SWI $0 366 RSB.CS $0, R0 367 SUB $20, R13 368 MOVW R0, ret+24(FP) 369 RET 370 371 // void runtimecloseonexec(int32 fd) 372 TEXT runtimecloseonexec(SB),NOSPLIT,$0 373 MOVW fd+0(FP), R0 // fd 374 MOVW $2, R1 // F_SETFD 375 MOVW $1, R2 // FD_CLOEXEC 376 MOVW $SYS_fcntl, R7 377 SWI $0 378 RET 379 380 TEXT runtimecasp1(SB),NOSPLIT,$0 381 B runtimecas(SB) 382 383 // TODO(minux): this is only valid for ARMv6+ 384 // bool armcas(int32 *val, int32 old, int32 new) 385 // Atomically: 386 // if(*val == old){ 387 // *val = new; 388 // return 1; 389 // }else 390 // return 0; 391 TEXT runtimecas(SB),NOSPLIT,$0 392 B runtimearmcas(SB) 393 394 // TODO: this is only valid for ARMv7+ 395 TEXT publicationBarrier(SB),NOSPLIT,$-4-0 396 B runtimearmPublicationBarrier(SB) 397 398 // TODO(minux): this only supports ARMv6K+. 399 TEXT runtimeread_tls_fallback(SB),NOSPLIT,$-4 400 WORD $0xee1d0f70 // mrc p15, 0, r0, c13, c0, 3 401 RET 402