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