]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
Replace FSF snail mail address with URLs.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / s390 / s390-32 / sysdep.h
CommitLineData
d063d164 1/* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2011
00c2b3b9 2 Free Software Foundation, Inc.
847b055c
AJ
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.
847b055c
AJ
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.
847b055c 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/>. */
847b055c
AJ
19
20#ifndef _LINUX_S390_SYSDEP_H
8cbdd648 21#define _LINUX_S390_SYSDEP_H
847b055c 22
ffeac417 23#include <sysdeps/s390/s390-32/sysdep.h>
847b055c 24#include <sysdeps/unix/sysdep.h>
2c03b6db 25#include <dl-sysdep.h> /* For RTLD_PRIVATE_ERRNO. */
00c2b3b9 26#include <tls.h>
847b055c 27
0480c901
UD
28/* Define __set_errno() for INLINE_SYSCALL macro below. */
29#ifndef __ASSEMBLER__
30#include <errno.h>
31#endif
32
847b055c
AJ
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
40#undef SYS_ify
41#define SYS_ify(syscall_name) __NR_##syscall_name
42
847b055c
AJ
43#ifdef __ASSEMBLER__
44
45/* Linux uses a negative return value to indicate syscall errors, unlike
46 most Unices, which use the condition codes' carry flag.
47
48 Since version 2.1 the return value of a system call might be negative
49 even if the call succeeded. E.g., the `lseek' system call might return
50 a large offset. Therefore we must not anymore test for < 0, but test
51 for a real error by making sure the value in gpr2 is a real error
19df733e 52 number. Linus said he will make sure that no syscall returns a value
847b055c
AJ
53 in -1 .. -4095 as a valid result so we can savely test with -4095. */
54
847b055c
AJ
55#undef PSEUDO
56#define PSEUDO(name, syscall_name, args) \
57 .text; \
d063d164 58 ENTRY (name) \
ffa8d2a0 59 DO_CALL (syscall_name, args); \
847b055c 60 lhi %r4,-4095 ; \
d063d164 61 clr %r2,%r4 ; \
e6ebd2e4 62 jnl SYSCALL_ERROR_LABEL
847b055c
AJ
63
64#undef PSEUDO_END
65#define PSEUDO_END(name) \
66 SYSCALL_ERROR_HANDLER; \
67 END (name)
68
441ee043 69#undef PSEUDO_NOERRNO
9eb88290
UD
70#define PSEUDO_NOERRNO(name, syscall_name, args) \
71 .text; \
d063d164 72 ENTRY (name) \
9eb88290
UD
73 DO_CALL (syscall_name, args)
74
75#undef PSEUDO_END_NOERRNO
76#define PSEUDO_END_NOERRNO(name) \
77 END (name)
78
137ffcdc
UD
79#undef PSEUDO_ERRVAL
80#define PSEUDO_ERRVAL(name, syscall_name, args) \
81 .text; \
d063d164 82 ENTRY (name) \
137ffcdc
UD
83 DO_CALL (syscall_name, args); \
84 lcr %r2,%r2
85
86#undef PSEUDO_END_ERRVAL
87#define PSEUDO_END_ERRVAL(name) \
88 END (name)
89
847b055c 90#ifndef PIC
e6ebd2e4
UD
91# define SYSCALL_ERROR_LABEL 0f
92# define SYSCALL_ERROR_HANDLER \
930: basr %r1,0; \
941: l %r1,2f-1b(%r1); \
95 br %r1; \
962: .long syscall_error
847b055c 97#else
e6ebd2e4
UD
98# if RTLD_PRIVATE_ERRNO
99# define SYSCALL_ERROR_LABEL 0f
100# define SYSCALL_ERROR_HANDLER \
1010: basr %r1,0; \
1021: al %r1,2f-1b(%r1); \
103 lcr %r2,%r2; \
104 st %r2,0(%r1); \
105 lhi %r2,-1; \
106 br %r14; \
96c82b3f 1072: .long rtld_errno-1b
e6ebd2e4 108# elif defined _LIBC_REENTRANT
d063d164
UD
109# ifndef NOT_IN_libc
110# define SYSCALL_ERROR_ERRNO __libc_errno
111# else
112# define SYSCALL_ERROR_ERRNO errno
113# endif
114# define SYSCALL_ERROR_LABEL 0f
115# define SYSCALL_ERROR_HANDLER \
e6ebd2e4
UD
1160: lcr %r0,%r2; \
117 basr %r1,0; \
1181: al %r1,2f-1b(%r1); \
00c2b3b9
UD
119 l %r1,SYSCALL_ERROR_ERRNO@gotntpoff(%r1); \
120 ear %r2,%a0; \
e6ebd2e4
UD
121 st %r0,0(%r1,%r2); \
122 lhi %r2,-1; \
123 br %r14; \
1242: .long _GLOBAL_OFFSET_TABLE_-1b
e6ebd2e4
UD
125# else
126# define SYSCALL_ERROR_LABEL 0f
127# define SYSCALL_ERROR_HANDLER \
1280: basr %r1,0; \
1291: al %r1,2f-1b(%r1); \
130 l %r1,errno@GOT(%r1); \
131 lcr %r2,%r2; \
132 st %r2,0(%r1); \
133 lhi %r2,-1; \
134 br %r14; \
1352: .long _GLOBAL_OFFSET_TABLE_-1b
136# endif /* _LIBC_REENTRANT */
847b055c 137#endif /* PIC */
847b055c
AJ
138
139/* Linux takes system call arguments in registers:
140
141 syscall number 1 call-clobbered
142 arg 1 2 call-clobbered
143 arg 2 3 call-clobbered
144 arg 3 4 call-clobbered
145 arg 4 5 call-clobbered
146 arg 5 6 call-saved
8d2e6a03 147 arg 6 7 call-saved
847b055c
AJ
148
149 (Of course a function with say 3 arguments does not have entries for
150 arguments 4 and 5.)
8d2e6a03
RM
151 For system calls with 6 parameters a stack operation is required
152 to load the 6th parameter to register 7. Call saved register 7 is
153 moved to register 0 and back to avoid an additional stack frame.
847b055c
AJ
154 */
155
ffa8d2a0 156#define DO_CALL(syscall, args) \
8d2e6a03
RM
157 .if args > 5; \
158 lr %r0,%r7; \
159 l %r7,96(%r15); \
160 .endif; \
1739d268
UD
161 .if SYS_ify (syscall) < 256; \
162 svc SYS_ify (syscall); \
163 .else; \
164 lhi %r1,SYS_ify (syscall); \
165 svc 0; \
8d2e6a03
RM
166 .endif; \
167 .if args > 5; \
168 lr %r7,%r0; \
1739d268 169 .endif
847b055c
AJ
170
171#define ret \
172 br 14
173
9eb88290
UD
174#define ret_NOERRNO \
175 br 14
176
137ffcdc
UD
177#define ret_ERRVAL \
178 br 14
179
847b055c
AJ
180#endif /* __ASSEMBLER__ */
181
182#undef INLINE_SYSCALL
369b849f
RM
183#define INLINE_SYSCALL(name, nr, args...) \
184 ({ \
6aca81bb
UD
185 unsigned int _ret = INTERNAL_SYSCALL (name, , nr, args); \
186 if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_ret, ), 0)) \
369b849f 187 { \
6aca81bb
UD
188 __set_errno (INTERNAL_SYSCALL_ERRNO (_ret, )); \
189 _ret = 0xffffffff; \
369b849f 190 } \
6aca81bb
UD
191 (int) _ret; })
192
193#undef INTERNAL_SYSCALL_DECL
194#define INTERNAL_SYSCALL_DECL(err) do { } while (0)
847b055c 195
1739d268
UD
196#undef INTERNAL_SYSCALL_DIRECT
197#define INTERNAL_SYSCALL_DIRECT(name, err, nr, args...) \
369b849f
RM
198 ({ \
199 DECLARGS_##nr(args) \
d5b6c817 200 register int _ret asm("2"); \
369b849f 201 asm volatile ( \
369b849f 202 "svc %b1\n\t" \
6aca81bb 203 : "=d" (_ret) \
d5b6c817
UD
204 : "i" (__NR_##name) ASMFMT_##nr \
205 : "memory" ); \
206 _ret; })
369b849f 207
1739d268
UD
208#undef INTERNAL_SYSCALL_SVC0
209#define INTERNAL_SYSCALL_SVC0(name, err, nr, args...) \
210 ({ \
211 DECLARGS_##nr(args) \
212 register unsigned long _nr asm("1") = (unsigned long)(__NR_##name); \
213 register int _ret asm("2"); \
214 asm volatile ( \
215 "svc 0\n\t" \
216 : "=d" (_ret) \
bbb5e55c
UD
217 : "d" (_nr) ASMFMT_##nr \
218 : "memory" ); \
219 _ret; })
220
221#undef INTERNAL_SYSCALL_NCS
222#define INTERNAL_SYSCALL_NCS(no, err, nr, args...) \
223 ({ \
224 DECLARGS_##nr(args) \
225 register unsigned long _nr asm("1") = (unsigned long)(no); \
226 register int _ret asm("2"); \
227 asm volatile ( \
228 "svc 0\n\t" \
229 : "=d" (_ret) \
230 : "d" (_nr) ASMFMT_##nr \
1739d268
UD
231 : "memory" ); \
232 _ret; })
233
234#undef INTERNAL_SYSCALL
235#define INTERNAL_SYSCALL(name, err, nr, args...) \
236 (((__NR_##name) < 256) ? \
237 INTERNAL_SYSCALL_DIRECT(name, err, nr, args) : \
238 INTERNAL_SYSCALL_SVC0(name, err,nr, args))
239
369b849f 240#undef INTERNAL_SYSCALL_ERROR_P
6aca81bb
UD
241#define INTERNAL_SYSCALL_ERROR_P(val, err) \
242 ((unsigned int) (val) >= 0xfffff001u)
369b849f
RM
243
244#undef INTERNAL_SYSCALL_ERRNO
6aca81bb 245#define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
369b849f 246
847b055c
AJ
247#define DECLARGS_0()
248#define DECLARGS_1(arg1) \
d5b6c817 249 register unsigned long gpr2 asm ("2") = (unsigned long)(arg1);
847b055c
AJ
250#define DECLARGS_2(arg1, arg2) \
251 DECLARGS_1(arg1) \
d5b6c817 252 register unsigned long gpr3 asm ("3") = (unsigned long)(arg2);
847b055c
AJ
253#define DECLARGS_3(arg1, arg2, arg3) \
254 DECLARGS_2(arg1, arg2) \
d5b6c817 255 register unsigned long gpr4 asm ("4") = (unsigned long)(arg3);
847b055c
AJ
256#define DECLARGS_4(arg1, arg2, arg3, arg4) \
257 DECLARGS_3(arg1, arg2, arg3) \
d5b6c817 258 register unsigned long gpr5 asm ("5") = (unsigned long)(arg4);
847b055c
AJ
259#define DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
260 DECLARGS_4(arg1, arg2, arg3, arg4) \
d5b6c817 261 register unsigned long gpr6 asm ("6") = (unsigned long)(arg5);
8d2e6a03
RM
262#define DECLARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
263 DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
264 register unsigned long gpr7 asm ("7") = (unsigned long)(arg6);
847b055c
AJ
265
266#define ASMFMT_0
d5b6c817
UD
267#define ASMFMT_1 , "0" (gpr2)
268#define ASMFMT_2 , "0" (gpr2), "d" (gpr3)
269#define ASMFMT_3 , "0" (gpr2), "d" (gpr3), "d" (gpr4)
270#define ASMFMT_4 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5)
271#define ASMFMT_5 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6)
8d2e6a03 272#define ASMFMT_6 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6), "d" (gpr7)
847b055c 273
0480c901
UD
274#define CLOBBER_0 , "3", "4", "5"
275#define CLOBBER_1 , "3", "4", "5"
276#define CLOBBER_2 , "4", "5"
277#define CLOBBER_3 , "5"
278#define CLOBBER_4
279#define CLOBBER_5
280#define CLOBBER_6
281
282/* List of system calls which are supported as vsyscalls. */
283#define HAVE_CLOCK_GETRES_VSYSCALL 1
284#define HAVE_CLOCK_GETTIME_VSYSCALL 1
285
286/* This version is for kernels that implement system calls that
287 behave like function calls as far as register saving.
288 It falls back to the syscall in the case that the vDSO doesn't
289 exist or fails for ENOSYS */
290#ifdef SHARED
291# define INLINE_VSYSCALL(name, nr, args...) \
292 ({ \
293 __label__ out; \
294 __label__ iserr; \
295 long int _ret; \
296 \
297 if (__vdso_##name != NULL) \
298 { \
299 _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, , nr, ##args); \
300 if (!INTERNAL_SYSCALL_ERROR_P (_ret, )) \
301 goto out; \
302 if (INTERNAL_SYSCALL_ERRNO (_ret, ) != ENOSYS) \
303 goto iserr; \
304 } \
305 \
306 _ret = INTERNAL_SYSCALL (name, , nr, ##args); \
307 if (INTERNAL_SYSCALL_ERROR_P (_ret, )) \
308 { \
309 iserr: \
d063d164
UD
310 __set_errno (INTERNAL_SYSCALL_ERRNO (_ret, )); \
311 _ret = -1L; \
0480c901
UD
312 } \
313 out: \
314 (int) _ret; \
315 })
316#else
317# define INLINE_VSYSCALL(name, nr, args...) \
318 INLINE_SYSCALL (name, nr, ##args)
319#endif
320
321#ifdef SHARED
322# define INTERNAL_VSYSCALL(name, err, nr, args...) \
323 ({ \
324 __label__ out; \
325 long int _ret; \
326 \
327 if (__vdso_##name != NULL) \
328 { \
329 _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \
330 if (!INTERNAL_SYSCALL_ERROR_P (_ret, err) \
331 || INTERNAL_SYSCALL_ERRNO (_ret, err) != ENOSYS) \
332 goto out; \
333 } \
334 _ret = INTERNAL_SYSCALL (name, err, nr, ##args); \
335 out: \
336 _ret; \
337 })
338#else
339# define INTERNAL_VSYSCALL(name, err, nr, args...) \
340 INTERNAL_SYSCALL (name, err, nr, ##args)
341#endif
342
343/* This version is for internal uses when there is no desire
344 to set errno */
345#define INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK(name, err, nr, args...) \
346 ({ \
347 long int _ret = ENOSYS; \
348 \
349 if (__vdso_##name != NULL) \
350 _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \
351 else \
352 err = 1 << 28; \
353 _ret; \
354 })
355
356#define INTERNAL_VSYSCALL_NCS(fn, err, nr, args...) \
357 ({ \
358 DECLARGS_##nr(args) \
359 register long _ret asm("2"); \
360 asm volatile ( \
19df733e 361 "lr 10,14\n\t" \
0480c901 362 "basr 14,%1\n\t" \
19df733e 363 "lr 14,10\n\t" \
0480c901
UD
364 : "=d" (_ret) \
365 : "d" (fn) ASMFMT_##nr \
19df733e 366 : "cc", "memory", "0", "1", "10" CLOBBER_##nr); \
0480c901 367 _ret; })
00c2b3b9
UD
368
369/* Pointer mangling support. */
370#if defined NOT_IN_libc && defined IS_IN_rtld
371/* We cannot use the thread descriptor because in ld.so we use setjmp
372 earlier than the descriptor is initialized. */
373#else
374/* For the time being just use stack_guard rather than a separate
375 pointer_guard. */
376# ifdef __ASSEMBLER__
377# define PTR_MANGLE(reg, tmpreg) \
378 ear tmpreg,%a0; \
379 x reg,STACK_GUARD(tmpreg)
305bb37e
UD
380# define PTR_MANGLE2(reg, tmpreg) \
381 x reg,STACK_GUARD(tmpreg)
00c2b3b9
UD
382# define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg)
383# else
384# define PTR_MANGLE(var) \
385 (var) = (void *) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ())
386# define PTR_DEMANGLE(var) PTR_MANGLE (var)
387# endif
388#endif
389
847b055c 390#endif /* _LINUX_S390_SYSDEP_H */