020cd9ad4514b892d7cd17f75e81db16d1d82bf5
[jlayton/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 (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_ret, ), 0))              \
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 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.  */
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 */