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