Home | History | Annotate | Download | only in runtime
      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