Text file
src/runtime/sys_linux_ppc64x.s
Documentation: runtime
1// Copyright 2014 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//go:build linux && (ppc64 || ppc64le)
6
7//
8// System calls and other sys.stuff for ppc64, Linux
9//
10
11#include "go_asm.h"
12#include "go_tls.h"
13#include "textflag.h"
14#include "asm_ppc64x.h"
15#include "cgo/abi_ppc64x.h"
16
17#define SYS_exit 1
18#define SYS_read 3
19#define SYS_write 4
20#define SYS_open 5
21#define SYS_close 6
22#define SYS_getpid 20
23#define SYS_kill 37
24#define SYS_brk 45
25#define SYS_mmap 90
26#define SYS_munmap 91
27#define SYS_setitimer 104
28#define SYS_clone 120
29#define SYS_sched_yield 158
30#define SYS_nanosleep 162
31#define SYS_rt_sigreturn 172
32#define SYS_rt_sigaction 173
33#define SYS_rt_sigprocmask 174
34#define SYS_sigaltstack 185
35#define SYS_madvise 205
36#define SYS_mincore 206
37#define SYS_gettid 207
38#define SYS_futex 221
39#define SYS_sched_getaffinity 223
40#define SYS_exit_group 234
41#define SYS_timer_create 240
42#define SYS_timer_settime 241
43#define SYS_timer_delete 244
44#define SYS_clock_gettime 246
45#define SYS_tgkill 250
46#define SYS_pipe2 317
47
48TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4
49 MOVW code+0(FP), R3
50 SYSCALL $SYS_exit_group
51 RET
52
53// func exitThread(wait *atomic.Uint32)
54TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8
55 MOVD wait+0(FP), R1
56 // We're done using the stack.
57 MOVW $0, R2
58 SYNC
59 MOVW R2, (R1)
60 MOVW $0, R3 // exit code
61 SYSCALL $SYS_exit
62 JMP 0(PC)
63
64TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0-20
65 MOVD name+0(FP), R3
66 MOVW mode+8(FP), R4
67 MOVW perm+12(FP), R5
68 SYSCALL $SYS_open
69 BVC 2(PC)
70 MOVW $-1, R3
71 MOVW R3, ret+16(FP)
72 RET
73
74TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0-12
75 MOVW fd+0(FP), R3
76 SYSCALL $SYS_close
77 BVC 2(PC)
78 MOVW $-1, R3
79 MOVW R3, ret+8(FP)
80 RET
81
82TEXT runtime·write1(SB),NOSPLIT|NOFRAME,$0-28
83 MOVD fd+0(FP), R3
84 MOVD p+8(FP), R4
85 MOVW n+16(FP), R5
86 SYSCALL $SYS_write
87 BVC 2(PC)
88 NEG R3 // caller expects negative errno
89 MOVW R3, ret+24(FP)
90 RET
91
92TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0-28
93 MOVW fd+0(FP), R3
94 MOVD p+8(FP), R4
95 MOVW n+16(FP), R5
96 SYSCALL $SYS_read
97 BVC 2(PC)
98 NEG R3 // caller expects negative errno
99 MOVW R3, ret+24(FP)
100 RET
101
102// func pipe2(flags int32) (r, w int32, errno int32)
103TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20
104 ADD $FIXED_FRAME+8, R1, R3
105 MOVW flags+0(FP), R4
106 SYSCALL $SYS_pipe2
107 MOVW R3, errno+16(FP)
108 RET
109
110// func usleep(usec uint32)
111TEXT runtime·usleep(SB),NOSPLIT,$16-4
112 MOVW usec+0(FP), R3
113
114 // Use magic constant 0x8637bd06 and shift right 51
115 // to perform usec/1000000.
116 MOVD $0x8637bd06, R4
117 MULLD R3, R4, R4 // Convert usec to S.
118 SRD $51, R4, R4
119 MOVD R4, 8(R1) // Store to tv_sec
120
121 MOVD $1000000, R5
122 MULLW R4, R5, R5 // Convert tv_sec back into uS
123 SUB R5, R3, R5 // Compute remainder uS.
124 MULLD $1000, R5, R5 // Convert to nsec
125 MOVD R5, 16(R1) // Store to tv_nsec
126
127 // nanosleep(&ts, 0)
128 ADD $8, R1, R3
129 MOVW $0, R4
130 SYSCALL $SYS_nanosleep
131 RET
132
133TEXT runtime·gettid(SB),NOSPLIT,$0-4
134 SYSCALL $SYS_gettid
135 MOVW R3, ret+0(FP)
136 RET
137
138TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0
139 SYSCALL $SYS_getpid
140 MOVW R3, R14
141 SYSCALL $SYS_gettid
142 MOVW R3, R4 // arg 2 tid
143 MOVW R14, R3 // arg 1 pid
144 MOVW sig+0(FP), R5 // arg 3
145 SYSCALL $SYS_tgkill
146 RET
147
148TEXT runtime·raiseproc(SB),NOSPLIT|NOFRAME,$0
149 SYSCALL $SYS_getpid
150 MOVW R3, R3 // arg 1 pid
151 MOVW sig+0(FP), R4 // arg 2
152 SYSCALL $SYS_kill
153 RET
154
155TEXT ·getpid(SB),NOSPLIT|NOFRAME,$0-8
156 SYSCALL $SYS_getpid
157 MOVD R3, ret+0(FP)
158 RET
159
160TEXT ·tgkill(SB),NOSPLIT|NOFRAME,$0-24
161 MOVD tgid+0(FP), R3
162 MOVD tid+8(FP), R4
163 MOVD sig+16(FP), R5
164 SYSCALL $SYS_tgkill
165 RET
166
167TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24
168 MOVW mode+0(FP), R3
169 MOVD new+8(FP), R4
170 MOVD old+16(FP), R5
171 SYSCALL $SYS_setitimer
172 RET
173
174TEXT runtime·timer_create(SB),NOSPLIT,$0-28
175 MOVW clockid+0(FP), R3
176 MOVD sevp+8(FP), R4
177 MOVD timerid+16(FP), R5
178 SYSCALL $SYS_timer_create
179 MOVW R3, ret+24(FP)
180 RET
181
182TEXT runtime·timer_settime(SB),NOSPLIT,$0-28
183 MOVW timerid+0(FP), R3
184 MOVW flags+4(FP), R4
185 MOVD new+8(FP), R5
186 MOVD old+16(FP), R6
187 SYSCALL $SYS_timer_settime
188 MOVW R3, ret+24(FP)
189 RET
190
191TEXT runtime·timer_delete(SB),NOSPLIT,$0-12
192 MOVW timerid+0(FP), R3
193 SYSCALL $SYS_timer_delete
194 MOVW R3, ret+8(FP)
195 RET
196
197TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28
198 MOVD addr+0(FP), R3
199 MOVD n+8(FP), R4
200 MOVD dst+16(FP), R5
201 SYSCALL $SYS_mincore
202 NEG R3 // caller expects negative errno
203 MOVW R3, ret+24(FP)
204 RET
205
206// func walltime() (sec int64, nsec int32)
207TEXT runtime·walltime(SB),NOSPLIT,$16-12
208 MOVD R1, R15 // R15 is unchanged by C code
209 MOVD g_m(g), R21 // R21 = m
210
211 MOVD $0, R3 // CLOCK_REALTIME
212
213 MOVD runtime·vdsoClockgettimeSym(SB), R12 // Check for VDSO availability
214 CMP R12, $0
215 BEQ fallback
216
217 // Set vdsoPC and vdsoSP for SIGPROF traceback.
218 // Save the old values on stack and restore them on exit,
219 // so this function is reentrant.
220 MOVD m_vdsoPC(R21), R4
221 MOVD m_vdsoSP(R21), R5
222 MOVD R4, 32(R1)
223 MOVD R5, 40(R1)
224
225 MOVD LR, R14
226 MOVD $ret-FIXED_FRAME(FP), R5 // caller's SP
227 MOVD R14, m_vdsoPC(R21)
228 MOVD R5, m_vdsoSP(R21)
229
230 MOVD m_curg(R21), R6
231 CMP g, R6
232 BNE noswitch
233
234 MOVD m_g0(R21), R7
235 MOVD (g_sched+gobuf_sp)(R7), R1 // Set SP to g0 stack
236
237noswitch:
238 SUB $16, R1 // Space for results
239 RLDICR $0, R1, $59, R1 // Align for C code
240 MOVD R12, CTR
241 MOVD R1, R4
242
243 // Store g on gsignal's stack, so if we receive a signal
244 // during VDSO code we can find the g.
245 // If we don't have a signal stack, we won't receive signal,
246 // so don't bother saving g.
247 // When using cgo, we already saved g on TLS, also don't save
248 // g here.
249 // Also don't save g if we are already on the signal stack.
250 // We won't get a nested signal.
251 MOVBZ runtime·iscgo(SB), R22
252 CMP R22, $0
253 BNE nosaveg
254 MOVD m_gsignal(R21), R22 // g.m.gsignal
255 CMP R22, $0
256 BEQ nosaveg
257
258 CMP g, R22
259 BEQ nosaveg
260 MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
261 MOVD g, (R22)
262
263 BL (CTR) // Call from VDSO
264
265 MOVD $0, (R22) // clear g slot, R22 is unchanged by C code
266
267 JMP finish
268
269nosaveg:
270 BL (CTR) // Call from VDSO
271
272finish:
273 MOVD $0, R0 // Restore R0
274 MOVD 0(R1), R3 // sec
275 MOVD 8(R1), R5 // nsec
276 MOVD R15, R1 // Restore SP
277
278 // Restore vdsoPC, vdsoSP
279 // We don't worry about being signaled between the two stores.
280 // If we are not in a signal handler, we'll restore vdsoSP to 0,
281 // and no one will care about vdsoPC. If we are in a signal handler,
282 // we cannot receive another signal.
283 MOVD 40(R1), R6
284 MOVD R6, m_vdsoSP(R21)
285 MOVD 32(R1), R6
286 MOVD R6, m_vdsoPC(R21)
287
288return:
289 MOVD R3, sec+0(FP)
290 MOVW R5, nsec+8(FP)
291 RET
292
293 // Syscall fallback
294fallback:
295 ADD $32, R1, R4
296 SYSCALL $SYS_clock_gettime
297 MOVD 32(R1), R3
298 MOVD 40(R1), R5
299 JMP return
300
301TEXT runtime·nanotime1(SB),NOSPLIT,$16-8
302 MOVD $1, R3 // CLOCK_MONOTONIC
303
304 MOVD R1, R15 // R15 is unchanged by C code
305 MOVD g_m(g), R21 // R21 = m
306
307 MOVD runtime·vdsoClockgettimeSym(SB), R12 // Check for VDSO availability
308 CMP R12, $0
309 BEQ fallback
310
311 // Set vdsoPC and vdsoSP for SIGPROF traceback.
312 // Save the old values on stack and restore them on exit,
313 // so this function is reentrant.
314 MOVD m_vdsoPC(R21), R4
315 MOVD m_vdsoSP(R21), R5
316 MOVD R4, 32(R1)
317 MOVD R5, 40(R1)
318
319 MOVD LR, R14 // R14 is unchanged by C code
320 MOVD $ret-FIXED_FRAME(FP), R5 // caller's SP
321 MOVD R14, m_vdsoPC(R21)
322 MOVD R5, m_vdsoSP(R21)
323
324 MOVD m_curg(R21), R6
325 CMP g, R6
326 BNE noswitch
327
328 MOVD m_g0(R21), R7
329 MOVD (g_sched+gobuf_sp)(R7), R1 // Set SP to g0 stack
330
331noswitch:
332 SUB $16, R1 // Space for results
333 RLDICR $0, R1, $59, R1 // Align for C code
334 MOVD R12, CTR
335 MOVD R1, R4
336
337 // Store g on gsignal's stack, so if we receive a signal
338 // during VDSO code we can find the g.
339 // If we don't have a signal stack, we won't receive signal,
340 // so don't bother saving g.
341 // When using cgo, we already saved g on TLS, also don't save
342 // g here.
343 // Also don't save g if we are already on the signal stack.
344 // We won't get a nested signal.
345 MOVBZ runtime·iscgo(SB), R22
346 CMP R22, $0
347 BNE nosaveg
348 MOVD m_gsignal(R21), R22 // g.m.gsignal
349 CMP R22, $0
350 BEQ nosaveg
351
352 CMP g, R22
353 BEQ nosaveg
354 MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
355 MOVD g, (R22)
356
357 BL (CTR) // Call from VDSO
358
359 MOVD $0, (R22) // clear g slot, R22 is unchanged by C code
360
361 JMP finish
362
363nosaveg:
364 BL (CTR) // Call from VDSO
365
366finish:
367 MOVD $0, R0 // Restore R0
368 MOVD 0(R1), R3 // sec
369 MOVD 8(R1), R5 // nsec
370 MOVD R15, R1 // Restore SP
371
372 // Restore vdsoPC, vdsoSP
373 // We don't worry about being signaled between the two stores.
374 // If we are not in a signal handler, we'll restore vdsoSP to 0,
375 // and no one will care about vdsoPC. If we are in a signal handler,
376 // we cannot receive another signal.
377 MOVD 40(R1), R6
378 MOVD R6, m_vdsoSP(R21)
379 MOVD 32(R1), R6
380 MOVD R6, m_vdsoPC(R21)
381
382return:
383 // sec is in R3, nsec in R5
384 // return nsec in R3
385 MOVD $1000000000, R4
386 MULLD R4, R3
387 ADD R5, R3
388 MOVD R3, ret+0(FP)
389 RET
390
391 // Syscall fallback
392fallback:
393 ADD $32, R1, R4
394 SYSCALL $SYS_clock_gettime
395 MOVD 32(R1), R3
396 MOVD 40(R1), R5
397 JMP return
398
399TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28
400 MOVW how+0(FP), R3
401 MOVD new+8(FP), R4
402 MOVD old+16(FP), R5
403 MOVW size+24(FP), R6
404 SYSCALL $SYS_rt_sigprocmask
405 BVC 2(PC)
406 MOVD R0, 0xf0(R0) // crash
407 RET
408
409TEXT runtime·rt_sigaction(SB),NOSPLIT|NOFRAME,$0-36
410 MOVD sig+0(FP), R3
411 MOVD new+8(FP), R4
412 MOVD old+16(FP), R5
413 MOVD size+24(FP), R6
414 SYSCALL $SYS_rt_sigaction
415 BVC 2(PC)
416 NEG R3 // caller expects negative errno
417 MOVW R3, ret+32(FP)
418 RET
419
420#ifdef GOARCH_ppc64le
421// Call the function stored in _cgo_sigaction using the GCC calling convention.
422TEXT runtime·callCgoSigaction(SB),NOSPLIT,$0
423 MOVD sig+0(FP), R3
424 MOVD new+8(FP), R4
425 MOVD old+16(FP), R5
426 MOVD _cgo_sigaction(SB), R12
427 MOVD R12, CTR // R12 should contain the function address
428 MOVD R1, R15 // Save R1
429 MOVD R2, 24(R1) // Save R2
430 SUB $48, R1 // reserve 32 (frame) + 16 bytes for sp-8 where fp may be saved.
431 RLDICR $0, R1, $59, R1 // Align to 16 bytes for C code
432 BL (CTR)
433 XOR R0, R0, R0 // Clear R0 as Go expects
434 MOVD R15, R1 // Restore R1
435 MOVD 24(R1), R2 // Restore R2
436 MOVW R3, ret+24(FP) // Return result
437 RET
438#endif
439
440TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
441 MOVW sig+8(FP), R3
442 MOVD info+16(FP), R4
443 MOVD ctx+24(FP), R5
444 MOVD fn+0(FP), R12
445 MOVD R12, CTR
446 BL (CTR)
447 MOVD 24(R1), R2
448 RET
449
450#ifdef GO_PPC64X_HAS_FUNCDESC
451DEFINE_PPC64X_FUNCDESC(runtime·sigtramp, sigtramp<>)
452// cgo isn't supported on ppc64, but we need to supply a cgoSigTramp function.
453DEFINE_PPC64X_FUNCDESC(runtime·cgoSigtramp, sigtramp<>)
454TEXT sigtramp<>(SB),NOSPLIT|NOFRAME|TOPFRAME,$0
455#else
456// ppc64le doesn't need function descriptors
457// Save callee-save registers in the case of signal forwarding.
458// Same as on ARM64 https://golang.org/issue/31827 .
459//
460// Note, it is assumed this is always called indirectly (e.g via
461// a function pointer) as R2 may not be preserved when calling this
462// function. In those cases, the caller preserves their R2.
463TEXT runtime·sigtramp(SB),NOSPLIT|NOFRAME,$0
464#endif
465 // This is called with ELF calling conventions. Convert to Go.
466 // Allocate space for argument storage to call runtime.sigtrampgo.
467 STACK_AND_SAVE_HOST_TO_GO_ABI(32)
468
469 // this might be called in external code context,
470 // where g is not set.
471 MOVBZ runtime·iscgo(SB), R6
472 CMP R6, $0
473 BEQ 2(PC)
474 BL runtime·load_g(SB)
475
476 // R3,R4,R5 already hold the arguments. Forward them on.
477 // TODO: Indirectly call runtime.sigtrampgo to avoid the linker's static NOSPLIT stack
478 // overflow detection. It thinks this might be called on a small Go stack, but this is only
479 // called from a larger pthread or sigaltstack stack. Can the checker be improved to not
480 // flag a direct call here?
481 MOVD $runtime·sigtrampgo<ABIInternal>(SB), R12
482 MOVD R12, CTR
483 BL (CTR)
484 // Restore R2 (TOC pointer) in the event it might be used later in this function.
485 // If this was not compiled as shared code, R2 is undefined, reloading it is harmless.
486 MOVD 24(R1), R2
487
488 UNSTACK_AND_RESTORE_GO_TO_HOST_ABI(32)
489 RET
490
491#ifdef GOARCH_ppc64le
492TEXT runtime·cgoSigtramp(SB),NOSPLIT|NOFRAME,$0
493 // The stack unwinder, presumably written in C, may not be able to
494 // handle Go frame correctly. So, this function is NOFRAME, and we
495 // save/restore LR manually, and obey ELFv2 calling conventions.
496 MOVD LR, R10
497
498 // We're coming from C code, initialize R0
499 MOVD $0, R0
500
501 // If no traceback function, do usual sigtramp.
502 MOVD runtime·cgoTraceback(SB), R6
503 CMP $0, R6
504 BEQ sigtramp
505
506 // If no traceback support function, which means that
507 // runtime/cgo was not linked in, do usual sigtramp.
508 MOVD _cgo_callers(SB), R6
509 CMP $0, R6
510 BEQ sigtramp
511
512 // Inspect the g in TLS without clobbering R30/R31 via runtime.load_g.
513 MOVD runtime·tls_g(SB), R9
514 MOVD 0(R9), R9
515
516 // Figure out if we are currently in a cgo call.
517 // If not, just do usual sigtramp.
518 // compared to ARM64 and others.
519 CMP $0, R9
520 BEQ sigtrampnog // g == nil
521
522 // g is not nil. Check further.
523 MOVD g_m(R9), R6
524 CMP $0, R6
525 BEQ sigtramp // g.m == nil
526 MOVW m_ncgo(R6), R7
527 CMPW $0, R7
528 BEQ sigtramp // g.m.ncgo = 0
529 MOVD m_curg(R6), R7
530 CMP $0, R7
531 BEQ sigtramp // g.m.curg == nil
532 MOVD g_syscallsp(R7), R7
533 CMP $0, R7
534 BEQ sigtramp // g.m.curg.syscallsp == 0
535 MOVD m_cgoCallers(R6), R7 // R7 is the fifth arg in C calling convention.
536 CMP $0, R7
537 BEQ sigtramp // g.m.cgoCallers == nil
538 MOVW m_cgoCallersUse(R6), R8
539 CMPW $0, R8
540 BNE sigtramp // g.m.cgoCallersUse != 0
541
542 // Jump to a function in runtime/cgo.
543 // That function, written in C, will call the user's traceback
544 // function with proper unwind info, and will then call back here.
545 // The first three arguments, and the fifth, are already in registers.
546 // Set the two remaining arguments now.
547 MOVD runtime·cgoTraceback(SB), R6
548 MOVD $runtime·sigtramp(SB), R8
549 MOVD _cgo_callers(SB), R12
550 MOVD R12, CTR
551 MOVD R10, LR // restore LR
552 JMP (CTR)
553
554sigtramp:
555 MOVD R10, LR // restore LR
556 JMP runtime·sigtramp(SB)
557
558sigtrampnog:
559 // Signal arrived on a non-Go thread. If this is SIGPROF, get a
560 // stack trace.
561 CMPW R3, $27 // 27 == SIGPROF
562 BNE sigtramp
563
564 // Lock sigprofCallersUse (cas from 0 to 1).
565 MOVW $1, R7
566 MOVD $runtime·sigprofCallersUse(SB), R8
567 SYNC
568 LWAR (R8), R6
569 CMPW $0, R6
570 BNE sigtramp
571 STWCCC R7, (R8)
572 BNE -4(PC)
573 ISYNC
574
575 // Jump to the traceback function in runtime/cgo.
576 // It will call back to sigprofNonGo, which will ignore the
577 // arguments passed in registers.
578 // First three arguments to traceback function are in registers already.
579 MOVD runtime·cgoTraceback(SB), R6
580 MOVD $runtime·sigprofCallers(SB), R7
581 MOVD $runtime·sigprofNonGoWrapper<>(SB), R8
582 MOVD _cgo_callers(SB), R12
583 MOVD R12, CTR
584 MOVD R10, LR // restore LR
585 JMP (CTR)
586#endif
587
588// Used by cgoSigtramp to inspect without clobbering R30/R31 via runtime.load_g.
589GLOBL runtime·tls_g+0(SB), TLSBSS+DUPOK, $8
590
591TEXT runtime·sigprofNonGoWrapper<>(SB),NOSPLIT|NOFRAME,$0
592 // This is called from C code. Callee save registers must be saved.
593 // R3,R4,R5 hold arguments, and allocate argument space to call sigprofNonGo.
594 STACK_AND_SAVE_HOST_TO_GO_ABI(32)
595
596 CALL runtime·sigprofNonGo<ABIInternal>(SB)
597
598 UNSTACK_AND_RESTORE_GO_TO_HOST_ABI(32)
599 RET
600
601TEXT runtime·mmap(SB),NOSPLIT|NOFRAME,$0
602 MOVD addr+0(FP), R3
603 MOVD n+8(FP), R4
604 MOVW prot+16(FP), R5
605 MOVW flags+20(FP), R6
606 MOVW fd+24(FP), R7
607 MOVW off+28(FP), R8
608
609 SYSCALL $SYS_mmap
610 BVC ok
611 MOVD $0, p+32(FP)
612 MOVD R3, err+40(FP)
613 RET
614ok:
615 MOVD R3, p+32(FP)
616 MOVD $0, err+40(FP)
617 RET
618
619TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0
620 MOVD addr+0(FP), R3
621 MOVD n+8(FP), R4
622 SYSCALL $SYS_munmap
623 BVC 2(PC)
624 MOVD R0, 0xf0(R0)
625 RET
626
627TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
628 MOVD addr+0(FP), R3
629 MOVD n+8(FP), R4
630 MOVW flags+16(FP), R5
631 SYSCALL $SYS_madvise
632 MOVW R3, ret+24(FP)
633 RET
634
635// int64 futex(int32 *uaddr, int32 op, int32 val,
636// struct timespec *timeout, int32 *uaddr2, int32 val2);
637TEXT runtime·futex(SB),NOSPLIT|NOFRAME,$0
638 MOVD addr+0(FP), R3
639 MOVW op+8(FP), R4
640 MOVW val+12(FP), R5
641 MOVD ts+16(FP), R6
642 MOVD addr2+24(FP), R7
643 MOVW val3+32(FP), R8
644 SYSCALL $SYS_futex
645 BVC 2(PC)
646 NEG R3 // caller expects negative errno
647 MOVW R3, ret+40(FP)
648 RET
649
650// int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
651TEXT runtime·clone(SB),NOSPLIT|NOFRAME,$0
652 MOVW flags+0(FP), R3
653 MOVD stk+8(FP), R4
654
655 // Copy mp, gp, fn off parent stack for use by child.
656 // Careful: Linux system call clobbers ???.
657 MOVD mp+16(FP), R7
658 MOVD gp+24(FP), R8
659 MOVD fn+32(FP), R12
660
661 MOVD R7, -8(R4)
662 MOVD R8, -16(R4)
663 MOVD R12, -24(R4)
664 MOVD $1234, R7
665 MOVD R7, -32(R4)
666
667 SYSCALL $SYS_clone
668 BVC 2(PC)
669 NEG R3 // caller expects negative errno
670
671 // In parent, return.
672 CMP R3, $0
673 BEQ 3(PC)
674 MOVW R3, ret+40(FP)
675 RET
676
677 // In child, on new stack.
678 // initialize essential registers
679 BL runtime·reginit(SB)
680 MOVD -32(R1), R7
681 CMP R7, $1234
682 BEQ 2(PC)
683 MOVD R0, 0(R0)
684
685 // Initialize m->procid to Linux tid
686 SYSCALL $SYS_gettid
687
688 MOVD -24(R1), R12 // fn
689 MOVD -16(R1), R8 // g
690 MOVD -8(R1), R7 // m
691
692 CMP R7, $0
693 BEQ nog
694 CMP R8, $0
695 BEQ nog
696
697 MOVD R3, m_procid(R7)
698
699 // TODO: setup TLS.
700
701 // In child, set up new stack
702 MOVD R7, g_m(R8)
703 MOVD R8, g
704 //CALL runtime·stackcheck(SB)
705
706nog:
707 // Call fn
708 MOVD R12, CTR
709 BL (CTR)
710
711 // It shouldn't return. If it does, exit that thread.
712 MOVW $111, R3
713 SYSCALL $SYS_exit
714 BR -2(PC) // keep exiting
715
716TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0
717 MOVD new+0(FP), R3
718 MOVD old+8(FP), R4
719 SYSCALL $SYS_sigaltstack
720 BVC 2(PC)
721 MOVD R0, 0xf0(R0) // crash
722 RET
723
724TEXT runtime·osyield(SB),NOSPLIT|NOFRAME,$0
725 SYSCALL $SYS_sched_yield
726 RET
727
728TEXT runtime·sched_getaffinity(SB),NOSPLIT|NOFRAME,$0
729 MOVD pid+0(FP), R3
730 MOVD len+8(FP), R4
731 MOVD buf+16(FP), R5
732 SYSCALL $SYS_sched_getaffinity
733 BVC 2(PC)
734 NEG R3 // caller expects negative errno
735 MOVW R3, ret+24(FP)
736 RET
737
738// func sbrk0() uintptr
739TEXT runtime·sbrk0(SB),NOSPLIT|NOFRAME,$0
740 // Implemented as brk(NULL).
741 MOVD $0, R3
742 SYSCALL $SYS_brk
743 MOVD R3, ret+0(FP)
744 RET
745
746TEXT runtime·access(SB),$0-20
747 MOVD R0, 0(R0) // unimplemented, only needed for android; declared in stubs_linux.go
748 MOVW R0, ret+16(FP) // for vet
749 RET
750
751TEXT runtime·connect(SB),$0-28
752 MOVD R0, 0(R0) // unimplemented, only needed for android; declared in stubs_linux.go
753 MOVW R0, ret+24(FP) // for vet
754 RET
755
756TEXT runtime·socket(SB),$0-20
757 MOVD R0, 0(R0) // unimplemented, only needed for android; declared in stubs_linux.go
758 MOVW R0, ret+16(FP) // for vet
759 RET
View as plain text