Replace FSF snail mail address with URLs.
[glibc.git] / sysdeps / unix / sysv / linux / s390 / s390-64 / sysdep.h
blobc68a237449d03b7fd1ada1194afe48ba0df5853b
1 /* Assembler macros for 64 bit S/390.
2 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2011
3 Free Software Foundation, Inc.
4 Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
5 This file is part of the GNU C Library.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, see
19 <http://www.gnu.org/licenses/>. */
21 #ifndef _LINUX_S390_SYSDEP_H
22 #define _LINUX_S390_SYSDEP_H
24 #include <sysdeps/s390/s390-64/sysdep.h>
25 #include <sysdeps/unix/sysdep.h>
26 #include <dl-sysdep.h> /* For RTLD_PRIVATE_ERRNO. */
27 #include <tls.h>
29 /* Define __set_errno() for INLINE_SYSCALL macro below. */
30 #ifndef __ASSEMBLER__
31 #include <errno.h>
32 #endif
34 /* For Linux we can use the system call table in the header file
35 /usr/include/asm/unistd.h
36 of the kernel. But these symbols do not follow the SYS_* syntax
37 so we have to redefine the `SYS_ify' macro here. */
38 /* In newer 2.1 kernels __NR_syscall is missing so we define it here. */
39 #define __NR_syscall 0
42 * Newer kernel versions redefined __NR_pread and __NR_pwrite to
43 * __NR_pread64 and __NR_pwrite64.
45 #ifndef __NR_pread
46 # define __NR_pread __NR_pread64
47 #endif
48 #ifndef __NR_pwrite
49 # define __NR_pwrite __NR_pwrite64
50 #endif
52 #undef SYS_ify
53 #define SYS_ify(syscall_name) __NR_##syscall_name
55 #ifdef __ASSEMBLER__
57 /* Linux uses a negative return value to indicate syscall errors, unlike
58 most Unices, which use the condition codes' carry flag.
60 Since version 2.1 the return value of a system call might be negative
61 even if the call succeeded. E.g., the `lseek' system call might return
62 a large offset. Therefore we must not anymore test for < 0, but test
63 for a real error by making sure the value in gpr2 is a real error
64 number. Linus said he will make sure that no syscall returns a value
65 in -1 .. -4095 as a valid result so we can savely test with -4095. */
67 #undef PSEUDO
68 #define PSEUDO(name, syscall_name, args) \
69 .text; \
70 ENTRY (name) \
71 DO_CALL (syscall_name, args); \
72 lghi %r4,-4095 ; \
73 clgr %r2,%r4 ; \
74 jgnl SYSCALL_ERROR_LABEL
76 #undef PSEUDO_END
77 #define PSEUDO_END(name) \
78 SYSCALL_ERROR_HANDLER; \
79 END (name)
81 #undef PSEUDO_NOERRNO
82 #define PSEUDO_NOERRNO(name, syscall_name, args) \
83 .text; \
84 ENTRY (name) \
85 DO_CALL (syscall_name, args)
87 #undef PSEUDO_END_NOERRNO
88 #define PSEUDO_END_NOERRNO(name) \
89 SYSCALL_ERROR_HANDLER; \
90 END (name)
92 #undef PSEUDO_ERRVAL
93 #define PSEUDO_ERRVAL(name, syscall_name, args) \
94 .text; \
95 ENTRY (name) \
96 DO_CALL (syscall_name, args); \
97 lcgr %r2,%r2
99 #undef PSEUDO_END_ERRVAL
100 #define PSEUDO_END_ERRVAL(name) \
101 SYSCALL_ERROR_HANDLER; \
102 END (name)
104 #ifndef PIC
105 # define SYSCALL_ERROR_LABEL syscall_error
106 # define SYSCALL_ERROR_HANDLER
107 #else
108 # if RTLD_PRIVATE_ERRNO
109 # define SYSCALL_ERROR_LABEL 0f
110 # define SYSCALL_ERROR_HANDLER \
111 0: larl %r1,rtld_errno; \
112 lcr %r2,%r2; \
113 st %r2,0(%r1); \
114 lghi %r2,-1; \
115 br %r14
116 # elif defined _LIBC_REENTRANT
117 # ifndef NOT_IN_libc
118 # define SYSCALL_ERROR_ERRNO __libc_errno
119 # else
120 # define SYSCALL_ERROR_ERRNO errno
121 # endif
122 # define SYSCALL_ERROR_LABEL 0f
123 # define SYSCALL_ERROR_HANDLER \
124 0: lcr %r0,%r2; \
125 larl %r1,SYSCALL_ERROR_ERRNO@indntpoff; \
126 lg %r1,0(%r1); \
127 ear %r2,%a0; \
128 sllg %r2,%r2,32; \
129 ear %r2,%a1; \
130 st %r0,0(%r1,%r2); \
131 lghi %r2,-1; \
132 br %r14
133 # else
134 # define SYSCALL_ERROR_LABEL 0f
135 # define SYSCALL_ERROR_HANDLER \
136 0: larl %r1,_GLOBAL_OFFSET_TABLE_; \
137 lg %r1,errno@GOT(%r1); \
138 lcr %r2,%r2; \
139 st %r2,0(%r1); \
140 lghi %r2,-1; \
141 br %r14
142 # endif /* _LIBC_REENTRANT */
143 #endif /* PIC */
145 /* Linux takes system call arguments in registers:
147 syscall number 1 call-clobbered
148 arg 1 2 call-clobbered
149 arg 2 3 call-clobbered
150 arg 3 4 call-clobbered
151 arg 4 5 call-clobbered
152 arg 5 6 call-saved
153 arg 6 7 call-saved
155 (Of course a function with say 3 arguments does not have entries for
156 arguments 4 and 5.)
157 For system calls with 6 parameters a stack operation is required
158 to load the 6th parameter to register 7. Call saved register 7 is
159 moved to register 0 and back to avoid an additional stack frame.
162 #define DO_CALL(syscall, args) \
163 .if args > 5; \
164 lgr %r0,%r7; \
165 lg %r7,160(%r15); \
166 .endif; \
167 .if SYS_ify (syscall) < 256; \
168 svc SYS_ify (syscall); \
169 .else; \
170 lghi %r1,SYS_ify (syscall); \
171 svc 0; \
172 .endif; \
173 .if args > 5; \
174 lgr %r7,%r0; \
175 .endif
177 #define ret \
178 br 14
180 #define ret_NOERRNO \
181 br 14
183 #define ret_ERRVAL \
184 br 14
186 #endif /* __ASSEMBLER__ */
188 #undef INLINE_SYSCALL
189 #define INLINE_SYSCALL(name, nr, args...) \
190 ({ \
191 long _ret = INTERNAL_SYSCALL (name, , nr, args); \
192 if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_ret, ), 0)) \
194 __set_errno (INTERNAL_SYSCALL_ERRNO (_ret, )); \
195 _ret = -1; \
197 _ret; })
199 #undef INTERNAL_SYSCALL_DECL
200 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
202 #undef INTERNAL_SYSCALL_DIRECT
203 #define INTERNAL_SYSCALL_DIRECT(name, err, nr, args...) \
204 ({ \
205 DECLARGS_##nr(args) \
206 register long _ret asm("2"); \
207 asm volatile ( \
208 "svc %b1\n\t" \
209 : "=d" (_ret) \
210 : "i" (__NR_##name) ASMFMT_##nr \
211 : "memory" ); \
212 _ret; })
214 #undef INTERNAL_SYSCALL_SVC0
215 #define INTERNAL_SYSCALL_SVC0(name, err, nr, args...) \
216 ({ \
217 DECLARGS_##nr(args) \
218 register unsigned long _nr asm("1") = (unsigned long)(__NR_##name); \
219 register long _ret asm("2"); \
220 asm volatile ( \
221 "svc 0\n\t" \
222 : "=d" (_ret) \
223 : "d" (_nr) ASMFMT_##nr \
224 : "memory" ); \
225 _ret; })
227 #undef INTERNAL_SYSCALL_NCS
228 #define INTERNAL_SYSCALL_NCS(no, err, nr, args...) \
229 ({ \
230 DECLARGS_##nr(args) \
231 register unsigned long _nr asm("1") = (unsigned long)(no); \
232 register long _ret asm("2"); \
233 asm volatile ( \
234 "svc 0\n\t" \
235 : "=d" (_ret) \
236 : "d" (_nr) ASMFMT_##nr \
237 : "memory" ); \
238 _ret; })
240 #undef INTERNAL_SYSCALL
241 #define INTERNAL_SYSCALL(name, err, nr, args...) \
242 (((__NR_##name) < 256) ? \
243 INTERNAL_SYSCALL_DIRECT(name, err, nr, args) : \
244 INTERNAL_SYSCALL_SVC0(name, err,nr, args))
246 #undef INTERNAL_SYSCALL_ERROR_P
247 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
248 ((unsigned long) (val) >= -4095UL)
250 #undef INTERNAL_SYSCALL_ERRNO
251 #define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
253 #define DECLARGS_0()
254 #define DECLARGS_1(arg1) \
255 register unsigned long gpr2 asm ("2") = (unsigned long)(arg1);
256 #define DECLARGS_2(arg1, arg2) \
257 DECLARGS_1(arg1) \
258 register unsigned long gpr3 asm ("3") = (unsigned long)(arg2);
259 #define DECLARGS_3(arg1, arg2, arg3) \
260 DECLARGS_2(arg1, arg2) \
261 register unsigned long gpr4 asm ("4") = (unsigned long)(arg3);
262 #define DECLARGS_4(arg1, arg2, arg3, arg4) \
263 DECLARGS_3(arg1, arg2, arg3) \
264 register unsigned long gpr5 asm ("5") = (unsigned long)(arg4);
265 #define DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
266 DECLARGS_4(arg1, arg2, arg3, arg4) \
267 register unsigned long gpr6 asm ("6") = (unsigned long)(arg5);
268 #define DECLARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
269 DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
270 register unsigned long gpr7 asm ("7") = (unsigned long)(arg6);
272 #define ASMFMT_0
273 #define ASMFMT_1 , "0" (gpr2)
274 #define ASMFMT_2 , "0" (gpr2), "d" (gpr3)
275 #define ASMFMT_3 , "0" (gpr2), "d" (gpr3), "d" (gpr4)
276 #define ASMFMT_4 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5)
277 #define ASMFMT_5 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6)
278 #define ASMFMT_6 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6), "d" (gpr7)
280 #define CLOBBER_0 , "3", "4", "5"
281 #define CLOBBER_1 , "3", "4", "5"
282 #define CLOBBER_2 , "4", "5"
283 #define CLOBBER_3 , "5"
284 #define CLOBBER_4
285 #define CLOBBER_5
286 #define CLOBBER_6
288 /* List of system calls which are supported as vsyscalls. */
289 #define HAVE_CLOCK_GETRES_VSYSCALL 1
290 #define HAVE_CLOCK_GETTIME_VSYSCALL 1
292 /* This version is for kernels that implement system calls that
293 behave like function calls as far as register saving.
294 It falls back to the syscall in the case that the vDSO doesn't
295 exist or fails for ENOSYS */
296 #ifdef SHARED
297 # define INLINE_VSYSCALL(name, nr, args...) \
298 ({ \
299 __label__ out; \
300 __label__ iserr; \
301 long int _ret; \
303 if (__vdso_##name != NULL) \
305 _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, , nr, ##args); \
306 if (!INTERNAL_SYSCALL_ERROR_P (_ret, )) \
307 goto out; \
308 if (INTERNAL_SYSCALL_ERRNO (_ret, ) != ENOSYS) \
309 goto iserr; \
312 _ret = INTERNAL_SYSCALL (name, , nr, ##args); \
313 if (INTERNAL_SYSCALL_ERROR_P (_ret, )) \
315 iserr: \
316 __set_errno (INTERNAL_SYSCALL_ERRNO (_ret, )); \
317 _ret = -1L; \
319 out: \
320 (int) _ret; \
322 #else
323 # define INLINE_VSYSCALL(name, nr, args...) \
324 INLINE_SYSCALL (name, nr, ##args)
325 #endif
327 #ifdef SHARED
328 # define INTERNAL_VSYSCALL(name, err, nr, args...) \
329 ({ \
330 __label__ out; \
331 long int _ret; \
333 if (__vdso_##name != NULL) \
335 _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \
336 if (!INTERNAL_SYSCALL_ERROR_P (_ret, err) \
337 || INTERNAL_SYSCALL_ERRNO (_ret, err) != ENOSYS) \
338 goto out; \
340 _ret = INTERNAL_SYSCALL (name, err, nr, ##args); \
341 out: \
342 _ret; \
344 #else
345 # define INTERNAL_VSYSCALL(name, err, nr, args...) \
346 INTERNAL_SYSCALL (name, err, nr, ##args)
347 #endif
349 /* This version is for internal uses when there is no desire
350 to set errno */
351 #define INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK(name, err, nr, args...) \
352 ({ \
353 long int _ret = ENOSYS; \
355 if (__vdso_##name != NULL) \
356 _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \
357 else \
358 err = 1 << 28; \
359 _ret; \
362 #define INTERNAL_VSYSCALL_NCS(fn, err, nr, args...) \
363 ({ \
364 DECLARGS_##nr(args) \
365 register long _ret asm("2"); \
366 asm volatile ( \
367 "lgr 10,14\n\t" \
368 "basr 14,%1\n\t" \
369 "lgr 14,10\n\t" \
370 : "=d" (_ret) \
371 : "a" (fn) ASMFMT_##nr \
372 : "cc", "memory", "0", "1", "10" CLOBBER_##nr); \
373 _ret; })
375 /* Pointer mangling support. */
376 #if defined NOT_IN_libc && defined IS_IN_rtld
377 /* We cannot use the thread descriptor because in ld.so we use setjmp
378 earlier than the descriptor is initialized. */
379 #else
380 /* For the time being just use stack_guard rather than a separate
381 pointer_guard. */
382 # ifdef __ASSEMBLER__
383 # define PTR_MANGLE(reg, tmpreg) \
384 ear tmpreg,%a0; \
385 sllg tmpreg,tmpreg,32; \
386 ear tmpreg,%a1; \
387 xg reg,STACK_GUARD(tmpreg)
388 # define PTR_MANGLE2(reg, tmpreg) \
389 xg reg,STACK_GUARD(tmpreg)
390 # define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg)
391 # else
392 # define PTR_MANGLE(var) \
393 (var) = (void *) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ())
394 # define PTR_DEMANGLE(var) PTR_MANGLE (var)
395 # endif
396 #endif
398 #endif /* _LINUX_S390_SYSDEP_H */