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, see
19 <http://www.gnu.org/licenses/>. */
21 #ifndef _LINUX_S390_SYSDEP_H
22 #define _LINUX_S390_SYSDEP_H
24 #include <sysdeps/s390/s390-64/sysdep.h>
25 #include <sysdeps/unix/sysdep.h>
26 #include <dl-sysdep.h> /* For RTLD_PRIVATE_ERRNO. */
29 /* Define __set_errno() for INLINE_SYSCALL macro below. */
34 /* For Linux we can use the system call table in the header file
35 /usr/include/asm/unistd.h
36 of the kernel. But these symbols do not follow the SYS_* syntax
37 so we have to redefine the `SYS_ify' macro here. */
38 /* In newer 2.1 kernels __NR_syscall is missing so we define it here. */
39 #define __NR_syscall 0
42 * Newer kernel versions redefined __NR_pread and __NR_pwrite to
43 * __NR_pread64 and __NR_pwrite64.
46 # define __NR_pread __NR_pread64
49 # define __NR_pwrite __NR_pwrite64
53 #define SYS_ify(syscall_name) __NR_##syscall_name
57 /* Linux uses a negative return value to indicate syscall errors, unlike
58 most Unices, which use the condition codes' carry flag.
60 Since version 2.1 the return value of a system call might be negative
61 even if the call succeeded. E.g., the `lseek' system call might return
62 a large offset. Therefore we must not anymore test for < 0, but test
63 for a real error by making sure the value in gpr2 is a real error
64 number. Linus said he will make sure that no syscall returns a value
65 in -1 .. -4095 as a valid result so we can savely test with -4095. */
68 #define PSEUDO(name, syscall_name, args) \
71 DO_CALL (syscall_name, args); \
74 jgnl SYSCALL_ERROR_LABEL
77 #define PSEUDO_END(name) \
78 SYSCALL_ERROR_HANDLER; \
82 #define PSEUDO_NOERRNO(name, syscall_name, args) \
85 DO_CALL (syscall_name, args)
87 #undef PSEUDO_END_NOERRNO
88 #define PSEUDO_END_NOERRNO(name) \
89 SYSCALL_ERROR_HANDLER; \
93 #define PSEUDO_ERRVAL(name, syscall_name, args) \
96 DO_CALL (syscall_name, args); \
99 #undef PSEUDO_END_ERRVAL
100 #define PSEUDO_END_ERRVAL(name) \
101 SYSCALL_ERROR_HANDLER; \
105 # define SYSCALL_ERROR_LABEL syscall_error
106 # define SYSCALL_ERROR_HANDLER
108 # if RTLD_PRIVATE_ERRNO
109 # define SYSCALL_ERROR_LABEL 0f
110 # define SYSCALL_ERROR_HANDLER \
111 0: larl %r1,rtld_errno; \
116 # elif defined _LIBC_REENTRANT
118 # define SYSCALL_ERROR_ERRNO __libc_errno
120 # define SYSCALL_ERROR_ERRNO errno
122 # define SYSCALL_ERROR_LABEL 0f
123 # define SYSCALL_ERROR_HANDLER \
125 larl %r1,SYSCALL_ERROR_ERRNO@indntpoff; \
134 # define SYSCALL_ERROR_LABEL 0f
135 # define SYSCALL_ERROR_HANDLER \
136 0: larl %r1,_GLOBAL_OFFSET_TABLE_; \
137 lg %r1,errno@GOT(%r1); \
142 # endif /* _LIBC_REENTRANT */
145 /* Linux takes system call arguments in registers:
147 syscall number 1 call-clobbered
148 arg 1 2 call-clobbered
149 arg 2 3 call-clobbered
150 arg 3 4 call-clobbered
151 arg 4 5 call-clobbered
155 (Of course a function with say 3 arguments does not have entries for
157 For system calls with 6 parameters a stack operation is required
158 to load the 6th parameter to register 7. Call saved register 7 is
159 moved to register 0 and back to avoid an additional stack frame.
162 #define DO_CALL(syscall, args) \
167 .if SYS_ify (syscall) < 256; \
168 svc SYS_ify (syscall); \
170 lghi %r1,SYS_ify (syscall); \
180 #define ret_NOERRNO \
186 #endif /* __ASSEMBLER__ */
188 #undef INLINE_SYSCALL
189 #define INLINE_SYSCALL(name, nr, args...) \
191 long _ret = INTERNAL_SYSCALL (name, , nr, args); \
192 if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_ret, ), 0)) \
194 __set_errno (INTERNAL_SYSCALL_ERRNO (_ret, )); \
199 #undef INTERNAL_SYSCALL_DECL
200 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
202 #undef INTERNAL_SYSCALL_DIRECT
203 #define INTERNAL_SYSCALL_DIRECT(name, err, nr, args...) \
205 DECLARGS_##nr(args) \
206 register long _ret asm("2"); \
210 : "i" (__NR_##name) ASMFMT_##nr \
214 #undef INTERNAL_SYSCALL_SVC0
215 #define INTERNAL_SYSCALL_SVC0(name, err, nr, args...) \
217 DECLARGS_##nr(args) \
218 register unsigned long _nr asm("1") = (unsigned long)(__NR_##name); \
219 register long _ret asm("2"); \
223 : "d" (_nr) ASMFMT_##nr \
227 #undef INTERNAL_SYSCALL_NCS
228 #define INTERNAL_SYSCALL_NCS(no, err, nr, args...) \
230 DECLARGS_##nr(args) \
231 register unsigned long _nr asm("1") = (unsigned long)(no); \
232 register long _ret asm("2"); \
236 : "d" (_nr) ASMFMT_##nr \
240 #undef INTERNAL_SYSCALL
241 #define INTERNAL_SYSCALL(name, err, nr, args...) \
242 (((__NR_##name) < 256) ? \
243 INTERNAL_SYSCALL_DIRECT(name, err, nr, args) : \
244 INTERNAL_SYSCALL_SVC0(name, err,nr, args))
246 #undef INTERNAL_SYSCALL_ERROR_P
247 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
248 ((unsigned long) (val) >= -4095UL)
250 #undef INTERNAL_SYSCALL_ERRNO
251 #define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
254 #define DECLARGS_1(arg1) \
255 register unsigned long gpr2 asm ("2") = (unsigned long)(arg1);
256 #define DECLARGS_2(arg1, arg2) \
258 register unsigned long gpr3 asm ("3") = (unsigned long)(arg2);
259 #define DECLARGS_3(arg1, arg2, arg3) \
260 DECLARGS_2(arg1, arg2) \
261 register unsigned long gpr4 asm ("4") = (unsigned long)(arg3);
262 #define DECLARGS_4(arg1, arg2, arg3, arg4) \
263 DECLARGS_3(arg1, arg2, arg3) \
264 register unsigned long gpr5 asm ("5") = (unsigned long)(arg4);
265 #define DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
266 DECLARGS_4(arg1, arg2, arg3, arg4) \
267 register unsigned long gpr6 asm ("6") = (unsigned long)(arg5);
268 #define DECLARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
269 DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
270 register unsigned long gpr7 asm ("7") = (unsigned long)(arg6);
273 #define ASMFMT_1 , "0" (gpr2)
274 #define ASMFMT_2 , "0" (gpr2), "d" (gpr3)
275 #define ASMFMT_3 , "0" (gpr2), "d" (gpr3), "d" (gpr4)
276 #define ASMFMT_4 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5)
277 #define ASMFMT_5 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6)
278 #define ASMFMT_6 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6), "d" (gpr7)
280 #define CLOBBER_0 , "3", "4", "5"
281 #define CLOBBER_1 , "3", "4", "5"
282 #define CLOBBER_2 , "4", "5"
283 #define CLOBBER_3 , "5"
288 /* List of system calls which are supported as vsyscalls. */
289 #define HAVE_CLOCK_GETRES_VSYSCALL 1
290 #define HAVE_CLOCK_GETTIME_VSYSCALL 1
292 /* This version is for kernels that implement system calls that
293 behave like function calls as far as register saving.
294 It falls back to the syscall in the case that the vDSO doesn't
295 exist or fails for ENOSYS */
297 # define INLINE_VSYSCALL(name, nr, args...) \
303 if (__vdso_##name != NULL) \
305 _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, , nr, ##args); \
306 if (!INTERNAL_SYSCALL_ERROR_P (_ret, )) \
308 if (INTERNAL_SYSCALL_ERRNO (_ret, ) != ENOSYS) \
312 _ret = INTERNAL_SYSCALL (name, , nr, ##args); \
313 if (INTERNAL_SYSCALL_ERROR_P (_ret, )) \
316 __set_errno (INTERNAL_SYSCALL_ERRNO (_ret, )); \
323 # define INLINE_VSYSCALL(name, nr, args...) \
324 INLINE_SYSCALL (name, nr, ##args)
328 # define INTERNAL_VSYSCALL(name, err, nr, args...) \
333 if (__vdso_##name != NULL) \
335 _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \
336 if (!INTERNAL_SYSCALL_ERROR_P (_ret, err) \
337 || INTERNAL_SYSCALL_ERRNO (_ret, err) != ENOSYS) \
340 _ret = INTERNAL_SYSCALL (name, err, nr, ##args); \
345 # define INTERNAL_VSYSCALL(name, err, nr, args...) \
346 INTERNAL_SYSCALL (name, err, nr, ##args)
349 /* This version is for internal uses when there is no desire
351 #define INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK(name, err, nr, args...) \
353 long int _ret = ENOSYS; \
355 if (__vdso_##name != NULL) \
356 _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \
362 #define INTERNAL_VSYSCALL_NCS(fn, err, nr, args...) \
364 DECLARGS_##nr(args) \
365 register long _ret asm("2"); \
371 : "a" (fn) ASMFMT_##nr \
372 : "cc", "memory", "0", "1", "10" CLOBBER_##nr); \
375 /* Pointer mangling support. */
376 #if defined NOT_IN_libc && defined IS_IN_rtld
377 /* We cannot use the thread descriptor because in ld.so we use setjmp
378 earlier than the descriptor is initialized. */
380 /* For the time being just use stack_guard rather than a separate
382 # ifdef __ASSEMBLER__
383 # define PTR_MANGLE(reg, tmpreg) \
385 sllg tmpreg,tmpreg,32; \
387 xg reg,STACK_GUARD(tmpreg)
388 # define PTR_MANGLE2(reg, tmpreg) \
389 xg reg,STACK_GUARD(tmpreg)
390 # define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg)
392 # define PTR_MANGLE(var) \
393 (var) = (void *) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ())
394 # define PTR_DEMANGLE(var) PTR_MANGLE (var)
398 #endif /* _LINUX_S390_SYSDEP_H */