]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
Remove IS_IN_rtld
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / s390 / s390-64 / sysdep.h
1 /* Assembler macros for 64 bit S/390.
2 Copyright (C) 2001-2014 Free Software Foundation, Inc.
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
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.
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
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
19
20 #ifndef _LINUX_S390_SYSDEP_H
21 #define _LINUX_S390_SYSDEP_H
22
23 #include <sysdeps/s390/s390-64/sysdep.h>
24 #include <sysdeps/unix/sysdep.h>
25 #include <dl-sysdep.h> /* For RTLD_PRIVATE_ERRNO. */
26 #include <tls.h>
27
28 /* Define __set_errno() for INLINE_SYSCALL macro below. */
29 #ifndef __ASSEMBLER__
30 #include <errno.h>
31 #endif
32
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 /*
41 * Newer kernel versions redefined __NR_pread and __NR_pwrite to
42 * __NR_pread64 and __NR_pwrite64.
43 */
44 #ifndef __NR_pread
45 # define __NR_pread __NR_pread64
46 #endif
47 #ifndef __NR_pwrite
48 # define __NR_pwrite __NR_pwrite64
49 #endif
50
51 #undef SYS_ify
52 #define SYS_ify(syscall_name) __NR_##syscall_name
53
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
63 number. Linus said he will make sure that no syscall returns a value
64 in -1 .. -4095 as a valid result so we can savely test with -4095. */
65
66 #undef PSEUDO
67 #define PSEUDO(name, syscall_name, args) \
68 .text; \
69 ENTRY (name) \
70 DO_CALL (syscall_name, args); \
71 lghi %r4,-4095 ; \
72 clgr %r2,%r4 ; \
73 jgnl SYSCALL_ERROR_LABEL
74
75 #undef PSEUDO_END
76 #define PSEUDO_END(name) \
77 SYSCALL_ERROR_HANDLER; \
78 END (name)
79
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
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
103 #ifndef PIC
104 # define SYSCALL_ERROR_LABEL syscall_error
105 # define SYSCALL_ERROR_HANDLER
106 #else
107 # if RTLD_PRIVATE_ERRNO
108 # define SYSCALL_ERROR_LABEL 0f
109 # define SYSCALL_ERROR_HANDLER \
110 0: larl %r1,rtld_errno; \
111 lcr %r2,%r2; \
112 st %r2,0(%r1); \
113 lghi %r2,-1; \
114 br %r14
115 # elif defined _LIBC_REENTRANT
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 \
123 0: 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
132 # else
133 # define SYSCALL_ERROR_LABEL 0f
134 # define SYSCALL_ERROR_HANDLER \
135 0: 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 */
142 #endif /* PIC */
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
152 arg 6 7 call-saved
153
154 (Of course a function with say 3 arguments does not have entries for
155 arguments 4 and 5.)
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.
159 */
160
161 #define DO_CALL(syscall, args) \
162 .if args > 5; \
163 lgr %r0,%r7; \
164 lg %r7,160(%r15); \
165 .endif; \
166 .if SYS_ify (syscall) < 256; \
167 svc SYS_ify (syscall); \
168 .else; \
169 lghi %r1,SYS_ify (syscall); \
170 svc 0; \
171 .endif; \
172 .if args > 5; \
173 lgr %r7,%r0; \
174 .endif
175
176 #define ret \
177 br 14
178
179 #define ret_NOERRNO \
180 br 14
181
182 #define ret_ERRVAL \
183 br 14
184
185 #endif /* __ASSEMBLER__ */
186
187 #undef INLINE_SYSCALL
188 #define INLINE_SYSCALL(name, nr, args...) \
189 ({ \
190 long _ret = INTERNAL_SYSCALL (name, , nr, args); \
191 if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (_ret, ))) \
192 { \
193 __set_errno (INTERNAL_SYSCALL_ERRNO (_ret, )); \
194 _ret = -1; \
195 } \
196 _ret; })
197
198 #undef INTERNAL_SYSCALL_DECL
199 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
200
201 #undef INTERNAL_SYSCALL_DIRECT
202 #define INTERNAL_SYSCALL_DIRECT(name, err, nr, args...) \
203 ({ \
204 DECLARGS_##nr(args) \
205 register long _ret asm("2"); \
206 asm volatile ( \
207 "svc %b1\n\t" \
208 : "=d" (_ret) \
209 : "i" (__NR_##name) ASMFMT_##nr \
210 : "memory" ); \
211 _ret; })
212
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); \
218 register long _ret asm("2"); \
219 asm volatile ( \
220 "svc 0\n\t" \
221 : "=d" (_ret) \
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 \
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
245 #undef INTERNAL_SYSCALL_ERROR_P
246 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
247 ((unsigned long) (val) >= -4095UL)
248
249 #undef INTERNAL_SYSCALL_ERRNO
250 #define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
251
252 #define DECLARGS_0()
253 #define DECLARGS_1(arg1) \
254 register unsigned long gpr2 asm ("2") = (unsigned long)(arg1);
255 #define DECLARGS_2(arg1, arg2) \
256 DECLARGS_1(arg1) \
257 register unsigned long gpr3 asm ("3") = (unsigned long)(arg2);
258 #define DECLARGS_3(arg1, arg2, arg3) \
259 DECLARGS_2(arg1, arg2) \
260 register unsigned long gpr4 asm ("4") = (unsigned long)(arg3);
261 #define DECLARGS_4(arg1, arg2, arg3, arg4) \
262 DECLARGS_3(arg1, arg2, arg3) \
263 register unsigned long gpr5 asm ("5") = (unsigned long)(arg4);
264 #define DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
265 DECLARGS_4(arg1, arg2, arg3, arg4) \
266 register unsigned long gpr6 asm ("6") = (unsigned long)(arg5);
267 #define DECLARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
268 DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
269 register unsigned long gpr7 asm ("7") = (unsigned long)(arg6);
270
271 #define ASMFMT_0
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)
277 #define ASMFMT_6 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6), "d" (gpr7)
278
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: \
315 __set_errno (INTERNAL_SYSCALL_ERRNO (_ret, )); \
316 _ret = -1L; \
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 ( \
366 "lgr 10,14\n\t" \
367 "basr 14,%1\n\t" \
368 "lgr 14,10\n\t" \
369 : "=d" (_ret) \
370 : "a" (fn) ASMFMT_##nr \
371 : "cc", "memory", "0", "1", "10" CLOBBER_##nr); \
372 _ret; })
373
374 /* Pointer mangling support. */
375 #if 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)
387 # define PTR_MANGLE2(reg, tmpreg) \
388 xg reg,STACK_GUARD(tmpreg)
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
397 #endif /* _LINUX_S390_SYSDEP_H */