]>
git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
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, write to the Free
19 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22 #ifndef _LINUX_S390_SYSDEP_H
23 #define _LINUX_S390_SYSDEP_H
25 #include <sysdeps/s390/s390-64/sysdep.h>
26 #include <sysdeps/unix/sysdep.h>
27 #include <dl-sysdep.h> /* For RTLD_PRIVATE_ERRNO. */
30 /* Define __set_errno() for INLINE_SYSCALL macro below. */
35 /* For Linux we can use the system call table in the header file
36 /usr/include/asm/unistd.h
37 of the kernel. But these symbols do not follow the SYS_* syntax
38 so we have to redefine the `SYS_ify' macro here. */
39 /* In newer 2.1 kernels __NR_syscall is missing so we define it here. */
40 #define __NR_syscall 0
43 * Newer kernel versions redefined __NR_pread and __NR_pwrite to
44 * __NR_pread64 and __NR_pwrite64.
47 # define __NR_pread __NR_pread64
50 # define __NR_pwrite __NR_pwrite64
54 #define SYS_ify(syscall_name) __NR_##syscall_name
58 /* Linux uses a negative return value to indicate syscall errors, unlike
59 most Unices, which use the condition codes' carry flag.
61 Since version 2.1 the return value of a system call might be negative
62 even if the call succeeded. E.g., the `lseek' system call might return
63 a large offset. Therefore we must not anymore test for < 0, but test
64 for a real error by making sure the value in gpr2 is a real error
65 number. Linus said he will make sure that no syscall returns a value
66 in -1 .. -4095 as a valid result so we can savely test with -4095. */
69 #define PSEUDO(name, syscall_name, args) \
72 DO_CALL (syscall_name, args); \
75 jgnl SYSCALL_ERROR_LABEL
78 #define PSEUDO_END(name) \
79 SYSCALL_ERROR_HANDLER; \
83 #define PSEUDO_NOERRNO(name, syscall_name, args) \
86 DO_CALL (syscall_name, args)
88 #undef PSEUDO_END_NOERRNO
89 #define PSEUDO_END_NOERRNO(name) \
90 SYSCALL_ERROR_HANDLER; \
94 #define PSEUDO_ERRVAL(name, syscall_name, args) \
97 DO_CALL (syscall_name, args); \
100 #undef PSEUDO_END_ERRVAL
101 #define PSEUDO_END_ERRVAL(name) \
102 SYSCALL_ERROR_HANDLER; \
106 # define SYSCALL_ERROR_LABEL syscall_error
107 # define SYSCALL_ERROR_HANDLER
109 # if RTLD_PRIVATE_ERRNO
110 # define SYSCALL_ERROR_LABEL 0f
111 # define SYSCALL_ERROR_HANDLER \
112 0: larl %r1,rtld_errno; \
117 # elif defined _LIBC_REENTRANT
119 # define SYSCALL_ERROR_ERRNO __libc_errno
121 # define SYSCALL_ERROR_ERRNO errno
123 # define SYSCALL_ERROR_LABEL 0f
124 # define SYSCALL_ERROR_HANDLER \
126 larl %r1,SYSCALL_ERROR_ERRNO@indntpoff; \
135 # define SYSCALL_ERROR_LABEL 0f
136 # define SYSCALL_ERROR_HANDLER \
137 0: larl %r1,_GLOBAL_OFFSET_TABLE_; \
138 lg %r1,errno@GOT(%r1); \
143 # endif /* _LIBC_REENTRANT */
146 /* Linux takes system call arguments in registers:
148 syscall number 1 call-clobbered
149 arg 1 2 call-clobbered
150 arg 2 3 call-clobbered
151 arg 3 4 call-clobbered
152 arg 4 5 call-clobbered
156 (Of course a function with say 3 arguments does not have entries for
158 For system calls with 6 parameters a stack operation is required
159 to load the 6th parameter to register 7. Call saved register 7 is
160 moved to register 0 and back to avoid an additional stack frame.
163 #define DO_CALL(syscall, args) \
168 .if SYS_ify (syscall) < 256; \
169 svc SYS_ify (syscall); \
171 lghi %r1,SYS_ify (syscall); \
181 #define ret_NOERRNO \
187 #endif /* __ASSEMBLER__ */
189 #undef INLINE_SYSCALL
190 #define INLINE_SYSCALL(name, nr, args...) \
192 long _ret = INTERNAL_SYSCALL (name, , nr, args); \
193 if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_ret, ), 0)) \
195 __set_errno (INTERNAL_SYSCALL_ERRNO (_ret, )); \
200 #undef INTERNAL_SYSCALL_DECL
201 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
203 #undef INTERNAL_SYSCALL_DIRECT
204 #define INTERNAL_SYSCALL_DIRECT(name, err, nr, args...) \
206 DECLARGS_##nr(args) \
207 register long _ret asm("2"); \
211 : "i" (__NR_##name) ASMFMT_##nr \
215 #undef INTERNAL_SYSCALL_SVC0
216 #define INTERNAL_SYSCALL_SVC0(name, err, nr, args...) \
218 DECLARGS_##nr(args) \
219 register unsigned long _nr asm("1") = (unsigned long)(__NR_##name); \
220 register long _ret asm("2"); \
224 : "d" (_nr) ASMFMT_##nr \
228 #undef INTERNAL_SYSCALL_NCS
229 #define INTERNAL_SYSCALL_NCS(no, err, nr, args...) \
231 DECLARGS_##nr(args) \
232 register unsigned long _nr asm("1") = (unsigned long)(no); \
233 register long _ret asm("2"); \
237 : "d" (_nr) ASMFMT_##nr \
241 #undef INTERNAL_SYSCALL
242 #define INTERNAL_SYSCALL(name, err, nr, args...) \
243 (((__NR_##name) < 256) ? \
244 INTERNAL_SYSCALL_DIRECT(name, err, nr, args) : \
245 INTERNAL_SYSCALL_SVC0(name, err,nr, args))
247 #undef INTERNAL_SYSCALL_ERROR_P
248 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
249 ((unsigned long) (val) >= -4095UL)
251 #undef INTERNAL_SYSCALL_ERRNO
252 #define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
255 #define DECLARGS_1(arg1) \
256 register unsigned long gpr2 asm ("2") = (unsigned long)(arg1);
257 #define DECLARGS_2(arg1, arg2) \
259 register unsigned long gpr3 asm ("3") = (unsigned long)(arg2);
260 #define DECLARGS_3(arg1, arg2, arg3) \
261 DECLARGS_2(arg1, arg2) \
262 register unsigned long gpr4 asm ("4") = (unsigned long)(arg3);
263 #define DECLARGS_4(arg1, arg2, arg3, arg4) \
264 DECLARGS_3(arg1, arg2, arg3) \
265 register unsigned long gpr5 asm ("5") = (unsigned long)(arg4);
266 #define DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
267 DECLARGS_4(arg1, arg2, arg3, arg4) \
268 register unsigned long gpr6 asm ("6") = (unsigned long)(arg5);
269 #define DECLARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
270 DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
271 register unsigned long gpr7 asm ("7") = (unsigned long)(arg6);
274 #define ASMFMT_1 , "0" (gpr2)
275 #define ASMFMT_2 , "0" (gpr2), "d" (gpr3)
276 #define ASMFMT_3 , "0" (gpr2), "d" (gpr3), "d" (gpr4)
277 #define ASMFMT_4 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5)
278 #define ASMFMT_5 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6)
279 #define ASMFMT_6 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6), "d" (gpr7)
281 #define CLOBBER_0 , "3", "4", "5"
282 #define CLOBBER_1 , "3", "4", "5"
283 #define CLOBBER_2 , "4", "5"
284 #define CLOBBER_3 , "5"
289 /* List of system calls which are supported as vsyscalls. */
290 #define HAVE_CLOCK_GETRES_VSYSCALL 1
291 #define HAVE_CLOCK_GETTIME_VSYSCALL 1
293 /* This version is for kernels that implement system calls that
294 behave like function calls as far as register saving.
295 It falls back to the syscall in the case that the vDSO doesn't
296 exist or fails for ENOSYS */
298 # define INLINE_VSYSCALL(name, nr, args...) \
304 if (__vdso_##name != NULL) \
306 _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, , nr, ##args); \
307 if (!INTERNAL_SYSCALL_ERROR_P (_ret, )) \
309 if (INTERNAL_SYSCALL_ERRNO (_ret, ) != ENOSYS) \
313 _ret = INTERNAL_SYSCALL (name, , nr, ##args); \
314 if (INTERNAL_SYSCALL_ERROR_P (_ret, )) \
317 __set_errno (INTERNAL_SYSCALL_ERRNO (_ret, )); \
324 # define INLINE_VSYSCALL(name, nr, args...) \
325 INLINE_SYSCALL (name, nr, ##args)
329 # define INTERNAL_VSYSCALL(name, err, nr, args...) \
334 if (__vdso_##name != NULL) \
336 _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \
337 if (!INTERNAL_SYSCALL_ERROR_P (_ret, err) \
338 || INTERNAL_SYSCALL_ERRNO (_ret, err) != ENOSYS) \
341 _ret = INTERNAL_SYSCALL (name, err, nr, ##args); \
346 # define INTERNAL_VSYSCALL(name, err, nr, args...) \
347 INTERNAL_SYSCALL (name, err, nr, ##args)
350 /* This version is for internal uses when there is no desire
352 #define INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK(name, err, nr, args...) \
354 long int _ret = ENOSYS; \
356 if (__vdso_##name != NULL) \
357 _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \
363 #define INTERNAL_VSYSCALL_NCS(fn, err, nr, args...) \
365 DECLARGS_##nr(args) \
366 register long _ret asm("2"); \
372 : "a" (fn) ASMFMT_##nr \
373 : "cc", "memory", "0", "1", "10" CLOBBER_##nr); \
376 /* Pointer mangling support. */
377 #if defined NOT_IN_libc && defined IS_IN_rtld
378 /* We cannot use the thread descriptor because in ld.so we use setjmp
379 earlier than the descriptor is initialized. */
381 /* For the time being just use stack_guard rather than a separate
383 # ifdef __ASSEMBLER__
384 # define PTR_MANGLE(reg, tmpreg) \
386 sllg tmpreg,tmpreg,32; \
388 xg reg,STACK_GUARD(tmpreg)
389 # define PTR_MANGLE2(reg, tmpreg) \
390 xg reg,STACK_GUARD(tmpreg)
391 # define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg)
393 # define PTR_MANGLE(var) \
394 (var) = (void *) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ())
395 # define PTR_DEMANGLE(var) PTR_MANGLE (var)
399 #endif /* _LINUX_S390_SYSDEP_H */