Text file
src/runtime/sys_linux_s390x.s
1 // Copyright 2016 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 system stuff for Linux s390x; see
6 // /usr/include/asm/unistd.h for the syscall number definitions.
7
8 #include "go_asm.h"
9 #include "go_tls.h"
10 #include "textflag.h"
11
12 #define SYS_exit 1
13 #define SYS_read 3
14 #define SYS_write 4
15 #define SYS_open 5
16 #define SYS_close 6
17 #define SYS_getpid 20
18 #define SYS_kill 37
19 #define SYS_brk 45
20 #define SYS_mmap 90
21 #define SYS_munmap 91
22 #define SYS_setitimer 104
23 #define SYS_clone 120
24 #define SYS_sched_yield 158
25 #define SYS_nanosleep 162
26 #define SYS_rt_sigreturn 173
27 #define SYS_rt_sigaction 174
28 #define SYS_rt_sigprocmask 175
29 #define SYS_sigaltstack 186
30 #define SYS_madvise 219
31 #define SYS_mincore 218
32 #define SYS_gettid 236
33 #define SYS_futex 238
34 #define SYS_sched_getaffinity 240
35 #define SYS_tgkill 241
36 #define SYS_exit_group 248
37 #define SYS_timer_create 254
38 #define SYS_timer_settime 255
39 #define SYS_timer_delete 258
40 #define SYS_clock_gettime 260
41 #define SYS_pipe2 325
42
43 TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4
44 MOVW code+0(FP), R2
45 MOVW $SYS_exit_group, R1
46 SYSCALL
47 RET
48
49 // func exitThread(wait *atomic.Uint32)
50 TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8
51 MOVD wait+0(FP), R1
52 // We're done using the stack.
53 MOVW $0, R2
54 MOVW R2, (R1)
55 MOVW $0, R2 // exit code
56 MOVW $SYS_exit, R1
57 SYSCALL
58 JMP 0(PC)
59
60 TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0-20
61 MOVD name+0(FP), R2
62 MOVW mode+8(FP), R3
63 MOVW perm+12(FP), R4
64 MOVW $SYS_open, R1
65 SYSCALL
66 MOVD $-4095, R3
67 CMPUBLT R2, R3, 2(PC)
68 MOVW $-1, R2
69 MOVW R2, ret+16(FP)
70 RET
71
72 TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0-12
73 MOVW fd+0(FP), R2
74 MOVW $SYS_close, R1
75 SYSCALL
76 MOVD $-4095, R3
77 CMPUBLT R2, R3, 2(PC)
78 MOVW $-1, R2
79 MOVW R2, ret+8(FP)
80 RET
81
82 TEXT runtime·write1(SB),NOSPLIT|NOFRAME,$0-28
83 MOVD fd+0(FP), R2
84 MOVD p+8(FP), R3
85 MOVW n+16(FP), R4
86 MOVW $SYS_write, R1
87 SYSCALL
88 MOVW R2, ret+24(FP)
89 RET
90
91 TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0-28
92 MOVW fd+0(FP), R2
93 MOVD p+8(FP), R3
94 MOVW n+16(FP), R4
95 MOVW $SYS_read, R1
96 SYSCALL
97 MOVW R2, ret+24(FP)
98 RET
99
100 // func pipe2() (r, w int32, errno int32)
101 TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20
102 MOVD $r+8(FP), R2
103 MOVW flags+0(FP), R3
104 MOVW $SYS_pipe2, R1
105 SYSCALL
106 MOVW R2, errno+16(FP)
107 RET
108
109 TEXT runtime·usleep(SB),NOSPLIT,$16-4
110 MOVW usec+0(FP), R2
111 MOVD R2, R4
112 MOVW $1000000, R3
113 DIVD R3, R2
114 MOVD R2, 8(R15)
115 MULLD R2, R3 // Convert sec to usec and subtract
116 SUB R3, R4
117 MOVW $1000, R3
118 MULLD R3, R4 // Convert remaining usec into nsec.
119 MOVD R4, 16(R15)
120
121 // nanosleep(&ts, 0)
122 ADD $8, R15, R2
123 MOVW $0, R3
124 MOVW $SYS_nanosleep, R1
125 SYSCALL
126 RET
127
128 TEXT runtime·gettid(SB),NOSPLIT,$0-4
129 MOVW $SYS_gettid, R1
130 SYSCALL
131 MOVW R2, ret+0(FP)
132 RET
133
134 TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0
135 MOVW $SYS_getpid, R1
136 SYSCALL
137 MOVW R2, R10
138 MOVW $SYS_gettid, R1
139 SYSCALL
140 MOVW R2, R3 // arg 2 tid
141 MOVW R10, R2 // arg 1 pid
142 MOVW sig+0(FP), R4 // arg 2
143 MOVW $SYS_tgkill, R1
144 SYSCALL
145 RET
146
147 TEXT runtime·raiseproc(SB),NOSPLIT|NOFRAME,$0
148 MOVW $SYS_getpid, R1
149 SYSCALL
150 MOVW R2, R2 // arg 1 pid
151 MOVW sig+0(FP), R3 // arg 2
152 MOVW $SYS_kill, R1
153 SYSCALL
154 RET
155
156 TEXT ·getpid(SB),NOSPLIT|NOFRAME,$0-8
157 MOVW $SYS_getpid, R1
158 SYSCALL
159 MOVD R2, ret+0(FP)
160 RET
161
162 TEXT ·tgkill(SB),NOSPLIT|NOFRAME,$0-24
163 MOVD tgid+0(FP), R2
164 MOVD tid+8(FP), R3
165 MOVD sig+16(FP), R4
166 MOVW $SYS_tgkill, R1
167 SYSCALL
168 RET
169
170 TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24
171 MOVW mode+0(FP), R2
172 MOVD new+8(FP), R3
173 MOVD old+16(FP), R4
174 MOVW $SYS_setitimer, R1
175 SYSCALL
176 RET
177
178 TEXT runtime·timer_create(SB),NOSPLIT|NOFRAME,$0-28
179 MOVW clockid+0(FP), R2
180 MOVD sevp+8(FP), R3
181 MOVD timerid+16(FP), R4
182 MOVW $SYS_timer_create, R1
183 SYSCALL
184 MOVW R2, ret+24(FP)
185 RET
186
187 TEXT runtime·timer_settime(SB),NOSPLIT|NOFRAME,$0-28
188 MOVW timerid+0(FP), R2
189 MOVW flags+4(FP), R3
190 MOVD new+8(FP), R4
191 MOVD old+16(FP), R5
192 MOVW $SYS_timer_settime, R1
193 SYSCALL
194 MOVW R2, ret+24(FP)
195 RET
196
197 TEXT runtime·timer_delete(SB),NOSPLIT|NOFRAME,$0-12
198 MOVW timerid+0(FP), R2
199 MOVW $SYS_timer_delete, R1
200 SYSCALL
201 MOVW R2, ret+8(FP)
202 RET
203
204 TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28
205 MOVD addr+0(FP), R2
206 MOVD n+8(FP), R3
207 MOVD dst+16(FP), R4
208 MOVW $SYS_mincore, R1
209 SYSCALL
210 MOVW R2, ret+24(FP)
211 RET
212
213 // func walltime() (sec int64, nsec int32)
214 TEXT runtime·walltime(SB),NOSPLIT,$32-12
215 MOVW $0, R2 // CLOCK_REALTIME
216 MOVD R15, R7 // Backup stack pointer
217
218 MOVD g_m(g), R6 //m
219
220 MOVD runtime·vdsoClockgettimeSym(SB), R9 // Check for VDSO availability
221 CMPBEQ R9, $0, fallback
222
223 MOVD m_vdsoPC(R6), R4
224 MOVD R4, 16(R15)
225 MOVD m_vdsoSP(R6), R4
226 MOVD R4, 24(R15)
227
228 MOVD R14, R8 // Backup return address
229 MOVD $sec+0(FP), R4 // return parameter caller
230
231 MOVD R8, m_vdsoPC(R6)
232 MOVD R4, m_vdsoSP(R6)
233
234 MOVD m_curg(R6), R5
235 CMP g, R5
236 BNE noswitch
237
238 MOVD m_g0(R6), R4
239 MOVD (g_sched+gobuf_sp)(R4), R15 // Set SP to g0 stack
240
241 noswitch:
242 SUB $16, R15 // reserve 2x 8 bytes for parameters
243 MOVD $~7, R4 // align to 8 bytes because of gcc ABI
244 AND R4, R15
245 MOVD R15, R3 // R15 needs to be in R3 as expected by kernel_clock_gettime
246
247 MOVB runtime·iscgo(SB),R12
248 CMPBNE R12, $0, nosaveg
249
250 MOVD m_gsignal(R6), R12 // g.m.gsignal
251 CMPBEQ R12, $0, nosaveg
252
253 CMPBEQ g, R12, nosaveg
254 MOVD (g_stack+stack_lo)(R12), R12 // g.m.gsignal.stack.lo
255 MOVD g, (R12)
256
257 BL R9 // to vdso lookup
258
259 MOVD $0, (R12)
260
261 JMP finish
262
263 nosaveg:
264 BL R9 // to vdso lookup
265
266 finish:
267 MOVD 0(R15), R3 // sec
268 MOVD 8(R15), R5 // nsec
269 MOVD R7, R15 // Restore SP
270
271 // Restore vdsoPC, vdsoSP
272 // We don't worry about being signaled between the two stores.
273 // If we are not in a signal handler, we'll restore vdsoSP to 0,
274 // and no one will care about vdsoPC. If we are in a signal handler,
275 // we cannot receive another signal.
276 MOVD 24(R15), R12
277 MOVD R12, m_vdsoSP(R6)
278 MOVD 16(R15), R12
279 MOVD R12, m_vdsoPC(R6)
280
281 return:
282 // sec is in R3, nsec in R5
283 // return nsec in R3
284 MOVD R3, sec+0(FP)
285 MOVW R5, nsec+8(FP)
286 RET
287
288 // Syscall fallback
289 fallback:
290 MOVD $tp-16(SP), R3
291 MOVW $SYS_clock_gettime, R1
292 SYSCALL
293 LMG tp-16(SP), R2, R3
294 // sec is in R2, nsec in R3
295 MOVD R2, sec+0(FP)
296 MOVW R3, nsec+8(FP)
297 RET
298
299 TEXT runtime·nanotime1(SB),NOSPLIT,$32-8
300 MOVW $1, R2 // CLOCK_MONOTONIC
301
302 MOVD R15, R7 // Backup stack pointer
303
304 MOVD g_m(g), R6 //m
305
306 MOVD runtime·vdsoClockgettimeSym(SB), R9 // Check for VDSO availability
307 CMPBEQ R9, $0, fallback
308
309 MOVD m_vdsoPC(R6), R4
310 MOVD R4, 16(R15)
311 MOVD m_vdsoSP(R6), R4
312 MOVD R4, 24(R15)
313
314 MOVD R14, R8 // Backup return address
315 MOVD $ret+0(FP), R4 // caller's SP
316
317 MOVD R8, m_vdsoPC(R6)
318 MOVD R4, m_vdsoSP(R6)
319
320 MOVD m_curg(R6), R5
321 CMP g, R5
322 BNE noswitch
323
324 MOVD m_g0(R6), R4
325 MOVD (g_sched+gobuf_sp)(R4), R15 // Set SP to g0 stack
326
327 noswitch:
328 SUB $16, R15 // reserve 2x 8 bytes for parameters
329 MOVD $~7, R4 // align to 8 bytes because of gcc ABI
330 AND R4, R15
331 MOVD R15, R3 // R15 needs to be in R3 as expected by kernel_clock_gettime
332
333 MOVB runtime·iscgo(SB),R12
334 CMPBNE R12, $0, nosaveg
335
336 MOVD m_gsignal(R6), R12 // g.m.gsignal
337 CMPBEQ R12, $0, nosaveg
338
339 CMPBEQ g, R12, nosaveg
340 MOVD (g_stack+stack_lo)(R12), R12 // g.m.gsignal.stack.lo
341 MOVD g, (R12)
342
343 BL R9 // to vdso lookup
344
345 MOVD $0, (R12)
346
347 JMP finish
348
349 nosaveg:
350 BL R9 // to vdso lookup
351
352 finish:
353 MOVD 0(R15), R3 // sec
354 MOVD 8(R15), R5 // nsec
355 MOVD R7, R15 // Restore SP
356
357 // Restore vdsoPC, vdsoSP
358 // We don't worry about being signaled between the two stores.
359 // If we are not in a signal handler, we'll restore vdsoSP to 0,
360 // and no one will care about vdsoPC. If we are in a signal handler,
361 // we cannot receive another signal.
362
363 MOVD 24(R15), R12
364 MOVD R12, m_vdsoSP(R6)
365 MOVD 16(R15), R12
366 MOVD R12, m_vdsoPC(R6)
367
368 return:
369 // sec is in R3, nsec in R5
370 // return nsec in R3
371 MULLD $1000000000, R3
372 ADD R5, R3
373 MOVD R3, ret+0(FP)
374 RET
375
376 // Syscall fallback
377 fallback:
378 MOVD $tp-16(SP), R3
379 MOVD $SYS_clock_gettime, R1
380 SYSCALL
381 LMG tp-16(SP), R2, R3
382 MOVD R3, R5
383 MOVD R2, R3
384 JMP return
385
386 TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28
387 MOVW how+0(FP), R2
388 MOVD new+8(FP), R3
389 MOVD old+16(FP), R4
390 MOVW size+24(FP), R5
391 MOVW $SYS_rt_sigprocmask, R1
392 SYSCALL
393 MOVD $-4095, R3
394 CMPUBLT R2, R3, 2(PC)
395 MOVD R0, 0(R0) // crash
396 RET
397
398 TEXT runtime·rt_sigaction(SB),NOSPLIT|NOFRAME,$0-36
399 MOVD sig+0(FP), R2
400 MOVD new+8(FP), R3
401 MOVD old+16(FP), R4
402 MOVD size+24(FP), R5
403 MOVW $SYS_rt_sigaction, R1
404 SYSCALL
405 MOVW R2, ret+32(FP)
406 RET
407
408 TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
409 MOVW sig+8(FP), R2
410 MOVD info+16(FP), R3
411 MOVD ctx+24(FP), R4
412 MOVD fn+0(FP), R5
413 BL R5
414 RET
415
416 TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME,$64
417 // initialize essential registers (just in case)
418 XOR R0, R0
419
420 // this might be called in external code context,
421 // where g is not set.
422 MOVB runtime·iscgo(SB), R6
423 CMPBEQ R6, $0, 2(PC)
424 BL runtime·load_g(SB)
425
426 MOVW R2, 8(R15)
427 MOVD R3, 16(R15)
428 MOVD R4, 24(R15)
429 MOVD $runtime·sigtrampgo(SB), R5
430 BL R5
431 RET
432
433 TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
434 BR runtime·sigtramp(SB)
435
436 // func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
437 TEXT runtime·mmap(SB),NOSPLIT,$48-48
438 MOVD addr+0(FP), R2
439 MOVD n+8(FP), R3
440 MOVW prot+16(FP), R4
441 MOVW flags+20(FP), R5
442 MOVW fd+24(FP), R6
443 MOVWZ off+28(FP), R7
444
445 // s390x uses old_mmap, so the arguments need to be placed into
446 // a struct and a pointer to the struct passed to mmap.
447 MOVD R2, addr-48(SP)
448 MOVD R3, n-40(SP)
449 MOVD R4, prot-32(SP)
450 MOVD R5, flags-24(SP)
451 MOVD R6, fd-16(SP)
452 MOVD R7, off-8(SP)
453
454 MOVD $addr-48(SP), R2
455 MOVW $SYS_mmap, R1
456 SYSCALL
457 MOVD $-4095, R3
458 CMPUBLT R2, R3, ok
459 NEG R2
460 MOVD $0, p+32(FP)
461 MOVD R2, err+40(FP)
462 RET
463 ok:
464 MOVD R2, p+32(FP)
465 MOVD $0, err+40(FP)
466 RET
467
468 TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0
469 MOVD addr+0(FP), R2
470 MOVD n+8(FP), R3
471 MOVW $SYS_munmap, R1
472 SYSCALL
473 MOVD $-4095, R3
474 CMPUBLT R2, R3, 2(PC)
475 MOVD R0, 0(R0) // crash
476 RET
477
478 TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
479 MOVD addr+0(FP), R2
480 MOVD n+8(FP), R3
481 MOVW flags+16(FP), R4
482 MOVW $SYS_madvise, R1
483 SYSCALL
484 MOVW R2, ret+24(FP)
485 RET
486
487 // int64 futex(int32 *uaddr, int32 op, int32 val,
488 // struct timespec *timeout, int32 *uaddr2, int32 val2);
489 TEXT runtime·futex(SB),NOSPLIT|NOFRAME,$0
490 MOVD addr+0(FP), R2
491 MOVW op+8(FP), R3
492 MOVW val+12(FP), R4
493 MOVD ts+16(FP), R5
494 MOVD addr2+24(FP), R6
495 MOVW val3+32(FP), R7
496 MOVW $SYS_futex, R1
497 SYSCALL
498 MOVW R2, ret+40(FP)
499 RET
500
501 // int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
502 TEXT runtime·clone(SB),NOSPLIT|NOFRAME,$0
503 MOVW flags+0(FP), R3
504 MOVD stk+8(FP), R2
505
506 // Copy mp, gp, fn off parent stack for use by child.
507 // Careful: Linux system call clobbers ???.
508 MOVD mp+16(FP), R7
509 MOVD gp+24(FP), R8
510 MOVD fn+32(FP), R9
511
512 MOVD R7, -8(R2)
513 MOVD R8, -16(R2)
514 MOVD R9, -24(R2)
515 MOVD $1234, R7
516 MOVD R7, -32(R2)
517
518 SYSCALL $SYS_clone
519
520 // In parent, return.
521 CMPBEQ R2, $0, 3(PC)
522 MOVW R2, ret+40(FP)
523 RET
524
525 // In child, on new stack.
526 // initialize essential registers
527 XOR R0, R0
528 MOVD -32(R15), R7
529 CMP R7, $1234
530 BEQ 2(PC)
531 MOVD R0, 0(R0)
532
533 // Initialize m->procid to Linux tid
534 SYSCALL $SYS_gettid
535
536 MOVD -24(R15), R9 // fn
537 MOVD -16(R15), R8 // g
538 MOVD -8(R15), R7 // m
539
540 CMPBEQ R7, $0, nog
541 CMP R8, $0
542 BEQ nog
543
544 MOVD R2, m_procid(R7)
545
546 // In child, set up new stack
547 MOVD R7, g_m(R8)
548 MOVD R8, g
549 //CALL runtime·stackcheck(SB)
550
551 nog:
552 // Call fn
553 BL R9
554
555 // It shouldn't return. If it does, exit that thread.
556 MOVW $111, R2
557 MOVW $SYS_exit, R1
558 SYSCALL
559 BR -2(PC) // keep exiting
560
561 TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0
562 MOVD new+0(FP), R2
563 MOVD old+8(FP), R3
564 MOVW $SYS_sigaltstack, R1
565 SYSCALL
566 MOVD $-4095, R3
567 CMPUBLT R2, R3, 2(PC)
568 MOVD R0, 0(R0) // crash
569 RET
570
571 TEXT runtime·osyield(SB),NOSPLIT|NOFRAME,$0
572 MOVW $SYS_sched_yield, R1
573 SYSCALL
574 RET
575
576 TEXT runtime·sched_getaffinity(SB),NOSPLIT|NOFRAME,$0
577 MOVD pid+0(FP), R2
578 MOVD len+8(FP), R3
579 MOVD buf+16(FP), R4
580 MOVW $SYS_sched_getaffinity, R1
581 SYSCALL
582 MOVW R2, ret+24(FP)
583 RET
584
585 // func sbrk0() uintptr
586 TEXT runtime·sbrk0(SB),NOSPLIT|NOFRAME,$0-8
587 // Implemented as brk(NULL).
588 MOVD $0, R2
589 MOVW $SYS_brk, R1
590 SYSCALL
591 MOVD R2, ret+0(FP)
592 RET
593
594 TEXT runtime·access(SB),$0-20
595 MOVD $0, 2(R0) // unimplemented, only needed for android; declared in stubs_linux.go
596 MOVW R0, ret+16(FP)
597 RET
598
599 TEXT runtime·connect(SB),$0-28
600 MOVD $0, 2(R0) // unimplemented, only needed for android; declared in stubs_linux.go
601 MOVW R0, ret+24(FP)
602 RET
603
604 TEXT runtime·socket(SB),$0-20
605 MOVD $0, 2(R0) // unimplemented, only needed for android; declared in stubs_linux.go
606 MOVW R0, ret+16(FP)
607 RET
608
609 // func vgetrandom1(buf *byte, length uintptr, flags uint32, state uintptr, stateSize uintptr) int
610 TEXT runtime·vgetrandom1(SB),NOSPLIT,$16-48
611 MOVD buf+0(FP), R2
612 MOVD length+8(FP), R3
613 MOVW flags+16(FP), R4
614 MOVD state+24(FP), R5
615 MOVD stateSize+32(FP), R6
616
617 MOVD R15, R7
618
619 MOVD runtime·vdsoGetrandomSym(SB), R1
620 MOVD g_m(g), R9
621
622 MOVD m_vdsoPC(R9), R12
623 MOVD R12, 8(R15)
624 MOVD m_vdsoSP(R9), R12
625 MOVD R12, 16(R15)
626 MOVD R14, m_vdsoPC(R9)
627 MOVD $buf+0(FP), R12
628 MOVD R12, m_vdsoSP(R9)
629
630 SUB $160, R15
631 MOVD $~7, R12
632 AND R12, R15
633
634 MOVB runtime·iscgo(SB), R12
635 CMPBNE R12, $0, nosaveg
636 MOVD m_gsignal(R9), R12
637 CMPBEQ R12, $0, nosaveg
638 CMPBEQ g, R12, nosaveg
639 MOVD (g_stack+stack_lo)(R12), R12
640 MOVD g, (R12)
641
642 BL R1
643
644 MOVD $0, (R12)
645 JMP restore
646
647 nosaveg:
648 BL R1
649
650 restore:
651 MOVD R7, R15
652 MOVD 16(R15), R12
653 MOVD R12, m_vdsoSP(R9)
654 MOVD 8(R15), R12
655 MOVD R12, m_vdsoPC(R9)
656 MOVD R2, ret+40(FP)
657 RET
658
View as plain text