1/* Assembler macros for 64 bit S/390.
2 Copyright (C) 2001-2026 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#ifndef _LINUX_S390_SYSDEP_H
20#define _LINUX_S390_SYSDEP_H
21
22#include <sysdeps/s390/sysdep.h>
23#include <sysdeps/unix/sysdep.h>
24#include <sysdeps/unix/sysv/linux/sysdep.h>
25#include <dl-sysdep.h> /* For RTLD_PRIVATE_ERRNO. */
26#include <tls.h>
27
28/* For Linux we can use the system call table in the header file
29 /usr/include/asm/unistd.h
30 of the kernel. But these symbols do not follow the SYS_* syntax
31 so we have to redefine the `SYS_ify' macro here. */
32/* In newer 2.1 kernels __NR_syscall is missing so we define it here. */
33#define __NR_syscall 0
34
35#undef SYS_ify
36#define SYS_ify(syscall_name) __NR_##syscall_name
37
38#ifdef __ASSEMBLER__
39
40/* Linux uses a negative return value to indicate syscall errors, unlike
41 most Unices, which use the condition codes' carry flag.
42
43 Since version 2.1 the return value of a system call might be negative
44 even if the call succeeded. E.g., the `lseek' system call might return
45 a large offset. Therefore we must not anymore test for < 0, but test
46 for a real error by making sure the value in gpr2 is a real error
47 number. Linus said he will make sure that no syscall returns a value
48 in -1 .. -4095 as a valid result so we can safely test with -4095. */
49
50# undef PSEUDO
51# define PSEUDO(name, syscall_name, args) \
52 .text; \
53 ENTRY (name) \
54 DO_CALL (syscall_name, args); \
55 lghi %r4,-4095 ; \
56 clgr %r2,%r4 ; \
57 jgnl SYSCALL_ERROR_LABEL
58
59# undef PSEUDO_END
60# define PSEUDO_END(name) \
61 SYSCALL_ERROR_HANDLER; \
62 END (name)
63
64# undef PSEUDO_NOERRNO
65# define PSEUDO_NOERRNO(name, syscall_name, args) \
66 .text; \
67 ENTRY (name) \
68 DO_CALL (syscall_name, args)
69
70# undef PSEUDO_END_NOERRNO
71# define PSEUDO_END_NOERRNO(name) \
72 SYSCALL_ERROR_HANDLER; \
73 END (name)
74
75# undef PSEUDO_ERRVAL
76# define PSEUDO_ERRVAL(name, syscall_name, args) \
77 .text; \
78 ENTRY (name) \
79 DO_CALL (syscall_name, args); \
80 lcgr %r2,%r2
81
82# undef PSEUDO_END_ERRVAL
83# define PSEUDO_END_ERRVAL(name) \
84 SYSCALL_ERROR_HANDLER; \
85 END (name)
86
87# undef SYSCALL_ERROR_LABEL
88# ifndef PIC
89# undef SYSCALL_ERROR_LABEL
90# define SYSCALL_ERROR_LABEL syscall_error
91# define SYSCALL_ERROR_HANDLER
92# else
93# if RTLD_PRIVATE_ERRNO
94# undef SYSCALL_ERROR_LABEL
95# define SYSCALL_ERROR_LABEL 0f
96# define SYSCALL_ERROR_HANDLER \
970: larl %r1,rtld_errno; \
98 lcr %r2,%r2; \
99 st %r2,0(%r1); \
100 lghi %r2,-1; \
101 br %r14
102# elif defined _LIBC_REENTRANT
103# if IS_IN (libc)
104# define SYSCALL_ERROR_ERRNO __libc_errno
105# else
106# define SYSCALL_ERROR_ERRNO errno
107# endif
108# undef SYSCALL_ERROR_LABEL
109# define SYSCALL_ERROR_LABEL 0f
110# define SYSCALL_ERROR_HANDLER \
1110: lcr %r0,%r2; \
112 larl %r1,SYSCALL_ERROR_ERRNO@indntpoff; \
113 lg %r1,0(%r1); \
114 ear %r2,%a0; \
115 sllg %r2,%r2,32; \
116 ear %r2,%a1; \
117 st %r0,0(%r1,%r2); \
118 lghi %r2,-1; \
119 br %r14
120# else
121# undef SYSCALL_ERROR_LABEL
122# define SYSCALL_ERROR_LABEL 0f
123# define SYSCALL_ERROR_HANDLER \
1240: larl %r1,_GLOBAL_OFFSET_TABLE_; \
125 lg %r1,errno@GOT(%r1); \
126 lcr %r2,%r2; \
127 st %r2,0(%r1); \
128 lghi %r2,-1; \
129 br %r14
130# endif /* _LIBC_REENTRANT */
131# endif /* PIC */
132
133/* Linux takes system call arguments in registers:
134
135 syscall number 1 call-clobbered
136 arg 1 2 call-clobbered
137 arg 2 3 call-clobbered
138 arg 3 4 call-clobbered
139 arg 4 5 call-clobbered
140 arg 5 6 call-saved
141 arg 6 7 call-saved
142
143 (Of course a function with say 3 arguments does not have entries for
144 arguments 4 and 5.)
145 For system calls with 6 parameters a stack operation is required
146 to load the 6th parameter to register 7. Call saved register 7 is
147 moved to register 0 and back to avoid an additional stack frame.
148 */
149
150# define DO_CALL(syscall, args) \
151 .if args > 5; \
152 lgr %r0,%r7; \
153 lg %r7,160(%r15); \
154 .endif; \
155 lghi %r1,SYS_ify (syscall); \
156 svc 0; \
157 .if args > 5; \
158 lgr %r7,%r0; \
159 .endif
160
161# define ret \
162 br 14
163
164# define ret_NOERRNO \
165 br 14
166
167# define ret_ERRVAL \
168 br 14
169
170#else /* not __ASSEMBLER__ */
171
172# undef INTERNAL_SYSCALL_NCS
173# define INTERNAL_SYSCALL_NCS(no, nr, args...) \
174 ({ \
175 DECLARGS_##nr(args) \
176 register unsigned long int _nr __asm__("1") = (unsigned long int)(no); \
177 register long int _ret __asm__("2"); \
178 __asm__ __volatile__ ( \
179 "svc 0\n\t" \
180 : "=d" (_ret) \
181 : "d" (_nr) ASMFMT_##nr \
182 : "memory" ); \
183 _ret; })
184
185# undef INTERNAL_SYSCALL
186# define INTERNAL_SYSCALL(name, nr, args...) \
187 INTERNAL_SYSCALL_NCS(__NR_##name, nr, args)
188
189# define DECLARGS_0()
190# define DECLARGS_1(arg1) \
191 register unsigned long int gpr2 __asm__ ("2") = (unsigned long int)(arg1);
192# define DECLARGS_2(arg1, arg2) \
193 DECLARGS_1(arg1) \
194 register unsigned long int gpr3 __asm__ ("3") = (unsigned long int)(arg2);
195# define DECLARGS_3(arg1, arg2, arg3) \
196 DECLARGS_2(arg1, arg2) \
197 register unsigned long int gpr4 __asm__ ("4") = (unsigned long int)(arg3);
198# define DECLARGS_4(arg1, arg2, arg3, arg4) \
199 DECLARGS_3(arg1, arg2, arg3) \
200 register unsigned long int gpr5 __asm__ ("5") = (unsigned long int)(arg4);
201# define DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
202 DECLARGS_4(arg1, arg2, arg3, arg4) \
203 register unsigned long int gpr6 __asm__ ("6") = (unsigned long int)(arg5);
204# define DECLARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
205 DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
206 register unsigned long int gpr7 __asm__ ("7") = (unsigned long int)(arg6);
207
208# define ASMFMT_0
209# define ASMFMT_1 , "0" (gpr2)
210# define ASMFMT_2 , "0" (gpr2), "d" (gpr3)
211# define ASMFMT_3 , "0" (gpr2), "d" (gpr3), "d" (gpr4)
212# define ASMFMT_4 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5)
213# define ASMFMT_5 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6)
214# define ASMFMT_6 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6), "d" (gpr7)
215
216# define VDSO_NAME "LINUX_2.6.29"
217# define VDSO_HASH 123718585
218
219/* List of system calls which are supported as vsyscalls. */
220# define HAVE_CLOCK_GETRES64_VSYSCALL "__kernel_clock_getres"
221# define HAVE_CLOCK_GETTIME64_VSYSCALL "__kernel_clock_gettime"
222# define HAVE_GETRANDOM_VSYSCALL "__kernel_getrandom"
223# define HAVE_GETTIMEOFDAY_VSYSCALL "__kernel_gettimeofday"
224# define HAVE_GETCPU_VSYSCALL "__kernel_getcpu"
225
226# define HAVE_CLONE3_WRAPPER 1
227
228# undef HAVE_INTERNAL_BRK_ADDR_SYMBOL
229# define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1
230
231#endif /* __ASSEMBLER__ */
232
233#endif /* _LINUX_S390_SYSDEP_H */