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.
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.
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.
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/>. */
20 #ifndef _LINUX_S390_SYSDEP_H
21 #define _LINUX_S390_SYSDEP_H
23 #include <sysdeps/s390/s390-64/sysdep.h>
24 #include <sysdeps/unix/sysdep.h>
25 #include <dl-sysdep.h> /* For RTLD_PRIVATE_ERRNO. */
28 /* Define __set_errno() for INLINE_SYSCALL macro below. */
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
41 * Newer kernel versions redefined __NR_pread and __NR_pwrite to
42 * __NR_pread64 and __NR_pwrite64.
45 # define __NR_pread __NR_pread64
48 # define __NR_pwrite __NR_pwrite64
52 #define SYS_ify(syscall_name) __NR_##syscall_name
56 /* Linux uses a negative return value to indicate syscall errors, unlike
57 most Unices, which use the condition codes' carry flag.
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. */
67 #define PSEUDO(name, syscall_name, args) \
70 DO_CALL (syscall_name, args); \
73 jgnl SYSCALL_ERROR_LABEL
76 #define PSEUDO_END(name) \
77 SYSCALL_ERROR_HANDLER; \
81 #define PSEUDO_NOERRNO(name, syscall_name, args) \
84 DO_CALL (syscall_name, args)
86 #undef PSEUDO_END_NOERRNO
87 #define PSEUDO_END_NOERRNO(name) \
88 SYSCALL_ERROR_HANDLER; \
92 #define PSEUDO_ERRVAL(name, syscall_name, args) \
95 DO_CALL (syscall_name, args); \
98 #undef PSEUDO_END_ERRVAL
99 #define PSEUDO_END_ERRVAL(name) \
100 SYSCALL_ERROR_HANDLER; \
104 # define SYSCALL_ERROR_LABEL syscall_error
105 # define SYSCALL_ERROR_HANDLER
107 # if RTLD_PRIVATE_ERRNO
108 # define SYSCALL_ERROR_LABEL 0f
109 # define SYSCALL_ERROR_HANDLER \
110 0: larl %r1,rtld_errno; \
115 # elif defined _LIBC_REENTRANT
117 # define SYSCALL_ERROR_ERRNO __libc_errno
119 # define SYSCALL_ERROR_ERRNO errno
121 # define SYSCALL_ERROR_LABEL 0f
122 # define SYSCALL_ERROR_HANDLER \
124 larl %r1,SYSCALL_ERROR_ERRNO@indntpoff; \
133 # define SYSCALL_ERROR_LABEL 0f
134 # define SYSCALL_ERROR_HANDLER \
135 0: larl %r1,_GLOBAL_OFFSET_TABLE_; \
136 lg %r1,errno@GOT(%r1); \
141 # endif /* _LIBC_REENTRANT */
144 /* Linux takes system call arguments in registers:
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
154 (Of course a function with say 3 arguments does not have entries for
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.
161 #define DO_CALL(syscall, args) \
166 .if SYS_ify (syscall) < 256; \
167 svc SYS_ify (syscall); \
169 lghi %r1,SYS_ify (syscall); \
179 #define ret_NOERRNO \
185 #endif /* __ASSEMBLER__ */
187 #undef INLINE_SYSCALL
188 #define INLINE_SYSCALL(name, nr, args...) \
190 long _ret = INTERNAL_SYSCALL (name, , nr, args); \
191 if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_ret, ), 0)) \
193 __set_errno (INTERNAL_SYSCALL_ERRNO (_ret, )); \
198 #undef INTERNAL_SYSCALL_DECL
199 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
201 #undef INTERNAL_SYSCALL_DIRECT
202 #define INTERNAL_SYSCALL_DIRECT(name, err, nr, args...) \
204 DECLARGS_##nr(args) \
205 register long _ret asm("2"); \
209 : "i" (__NR_##name) ASMFMT_##nr \
213 #undef INTERNAL_SYSCALL_SVC0
214 #define INTERNAL_SYSCALL_SVC0(name, err, nr, args...) \
216 DECLARGS_##nr(args) \
217 register unsigned long _nr asm("1") = (unsigned long)(__NR_##name); \
218 register long _ret asm("2"); \
222 : "d" (_nr) ASMFMT_##nr \
226 #undef INTERNAL_SYSCALL_NCS
227 #define INTERNAL_SYSCALL_NCS(no, err, nr, args...) \
229 DECLARGS_##nr(args) \
230 register unsigned long _nr asm("1") = (unsigned long)(no); \
231 register long _ret asm("2"); \
235 : "d" (_nr) ASMFMT_##nr \
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))
245 #undef INTERNAL_SYSCALL_ERROR_P
246 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
247 ((unsigned long) (val) >= -4095UL)
249 #undef INTERNAL_SYSCALL_ERRNO
250 #define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
253 #define DECLARGS_1(arg1) \
254 register unsigned long gpr2 asm ("2") = (unsigned long)(arg1);
255 #define DECLARGS_2(arg1, arg2) \
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);
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)
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"
287 /* List of system calls which are supported as vsyscalls. */
288 #define HAVE_CLOCK_GETRES_VSYSCALL 1
289 #define HAVE_CLOCK_GETTIME_VSYSCALL 1
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 */
296 # define INLINE_VSYSCALL(name, nr, args...) \
302 if (__vdso_##name != NULL) \
304 _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, , nr, ##args); \
305 if (!INTERNAL_SYSCALL_ERROR_P (_ret, )) \
307 if (INTERNAL_SYSCALL_ERRNO (_ret, ) != ENOSYS) \
311 _ret = INTERNAL_SYSCALL (name, , nr, ##args); \
312 if (INTERNAL_SYSCALL_ERROR_P (_ret, )) \
315 __set_errno (INTERNAL_SYSCALL_ERRNO (_ret, )); \
322 # define INLINE_VSYSCALL(name, nr, args...) \
323 INLINE_SYSCALL (name, nr, ##args)
327 # define INTERNAL_VSYSCALL(name, err, nr, args...) \
332 if (__vdso_##name != NULL) \
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) \
339 _ret = INTERNAL_SYSCALL (name, err, nr, ##args); \
344 # define INTERNAL_VSYSCALL(name, err, nr, args...) \
345 INTERNAL_SYSCALL (name, err, nr, ##args)
348 /* This version is for internal uses when there is no desire
350 #define INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK(name, err, nr, args...) \
352 long int _ret = ENOSYS; \
354 if (__vdso_##name != NULL) \
355 _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \
361 #define INTERNAL_VSYSCALL_NCS(fn, err, nr, args...) \
363 DECLARGS_##nr(args) \
364 register long _ret asm("2"); \
370 : "a" (fn) ASMFMT_##nr \
371 : "cc", "memory", "0", "1", "10" CLOBBER_##nr); \
374 /* Pointer mangling support. */
375 #if defined NOT_IN_libc && defined IS_IN_rtld
376 /* We cannot use the thread descriptor because in ld.so we use setjmp
377 earlier than the descriptor is initialized. */
379 /* For the time being just use stack_guard rather than a separate
381 # ifdef __ASSEMBLER__
382 # define PTR_MANGLE(reg, tmpreg) \
384 sllg tmpreg,tmpreg,32; \
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)
391 # define PTR_MANGLE(var) \
392 (var) = (void *) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ())
393 # define PTR_DEMANGLE(var) PTR_MANGLE (var)
397 #endif /* _LINUX_S390_SYSDEP_H */