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