Update copyright notices with scripts/update-copyrights
[jlayton/glibc.git] / sysdeps / unix / sysv / linux / s390 / s390-32 / sysdep.h
1 /* Copyright (C) 2000-2014 Free Software Foundation, Inc.
2    Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #ifndef _LINUX_S390_SYSDEP_H
20 #define _LINUX_S390_SYSDEP_H
21
22 #include <sysdeps/s390/s390-32/sysdep.h>
23 #include <sysdeps/unix/sysdep.h>
24 #include <dl-sysdep.h>  /* For RTLD_PRIVATE_ERRNO.  */
25 #include <tls.h>
26
27 /* Define __set_errno() for INLINE_SYSCALL macro below.  */
28 #ifndef __ASSEMBLER__
29 #include <errno.h>
30 #endif
31
32 /* For Linux we can use the system call table in the header file
33         /usr/include/asm/unistd.h
34    of the kernel.  But these symbols do not follow the SYS_* syntax
35    so we have to redefine the `SYS_ify' macro here.  */
36 /* in newer 2.1 kernels __NR_syscall is missing so we define it here */
37 #define __NR_syscall 0
38
39 #undef SYS_ify
40 #define SYS_ify(syscall_name)   __NR_##syscall_name
41
42 #ifdef __ASSEMBLER__
43
44 /* Linux uses a negative return value to indicate syscall errors, unlike
45    most Unices, which use the condition codes' carry flag.
46
47    Since version 2.1 the return value of a system call might be negative
48    even if the call succeeded.  E.g., the `lseek' system call might return
49    a large offset.  Therefore we must not anymore test for < 0, but test
50    for a real error by making sure the value in gpr2 is a real error
51    number.  Linus said he will make sure that no syscall returns a value
52    in -1 .. -4095 as a valid result so we can savely test with -4095.  */
53
54 #undef PSEUDO
55 #define PSEUDO(name, syscall_name, args)                                      \
56   .text;                                                                      \
57   ENTRY (name)                                                                \
58     DO_CALL (syscall_name, args);                                             \
59     lhi  %r4,-4095 ;                                                          \
60     clr  %r2,%r4 ;                                                            \
61     jnl  SYSCALL_ERROR_LABEL
62
63 #undef PSEUDO_END
64 #define PSEUDO_END(name)                                                      \
65   SYSCALL_ERROR_HANDLER;                                                      \
66   END (name)
67
68 #undef PSEUDO_NOERRNO
69 #define PSEUDO_NOERRNO(name, syscall_name, args)                              \
70   .text;                                                                      \
71   ENTRY (name)                                                                \
72     DO_CALL (syscall_name, args)
73
74 #undef PSEUDO_END_NOERRNO
75 #define PSEUDO_END_NOERRNO(name)                                              \
76   END (name)
77
78 #undef PSEUDO_ERRVAL
79 #define PSEUDO_ERRVAL(name, syscall_name, args)                               \
80   .text;                                                                      \
81   ENTRY (name)                                                                \
82     DO_CALL (syscall_name, args);                                             \
83     lcr %r2,%r2
84
85 #undef PSEUDO_END_ERRVAL
86 #define PSEUDO_END_ERRVAL(name)                                               \
87   END (name)
88
89 #ifndef PIC
90 # define SYSCALL_ERROR_LABEL 0f
91 # define SYSCALL_ERROR_HANDLER \
92 0:  basr  %r1,0;                                                              \
93 1:  l     %r1,2f-1b(%r1);                                                     \
94     br    %r1;                                                                \
95 2:  .long syscall_error
96 #else
97 # if RTLD_PRIVATE_ERRNO
98 #  define SYSCALL_ERROR_LABEL 0f
99 #  define SYSCALL_ERROR_HANDLER \
100 0:  basr  %r1,0;                                                              \
101 1:  al    %r1,2f-1b(%r1);                                                     \
102     lcr   %r2,%r2;                                                            \
103     st    %r2,0(%r1);                                                         \
104     lhi   %r2,-1;                                                             \
105     br    %r14;                                                               \
106 2:  .long rtld_errno-1b
107 # elif defined _LIBC_REENTRANT
108 #  ifndef NOT_IN_libc
109 #   define SYSCALL_ERROR_ERRNO __libc_errno
110 #  else
111 #   define SYSCALL_ERROR_ERRNO errno
112 #  endif
113 #  define SYSCALL_ERROR_LABEL 0f
114 #  define SYSCALL_ERROR_HANDLER \
115 0:  lcr   %r0,%r2;                                                            \
116     basr  %r1,0;                                                              \
117 1:  al    %r1,2f-1b(%r1);                                                     \
118     l     %r1,SYSCALL_ERROR_ERRNO@gotntpoff(%r1);                             \
119     ear   %r2,%a0;                                                            \
120     st    %r0,0(%r1,%r2);                                                     \
121     lhi   %r2,-1;                                                             \
122     br    %r14;                                                               \
123 2:  .long _GLOBAL_OFFSET_TABLE_-1b
124 # else
125 #  define SYSCALL_ERROR_LABEL 0f
126 #  define SYSCALL_ERROR_HANDLER \
127 0:  basr  %r1,0;                                                              \
128 1:  al    %r1,2f-1b(%r1);                                                     \
129     l     %r1,errno@GOT(%r1);                                                 \
130     lcr   %r2,%r2;                                                            \
131     st    %r2,0(%r1);                                                         \
132     lhi   %r2,-1;                                                             \
133     br    %r14;                                                               \
134 2:  .long _GLOBAL_OFFSET_TABLE_-1b
135 # endif /* _LIBC_REENTRANT */
136 #endif /* PIC */
137
138 /* Linux takes system call arguments in registers:
139
140         syscall number  1            call-clobbered
141         arg 1           2            call-clobbered
142         arg 2           3            call-clobbered
143         arg 3           4            call-clobbered
144         arg 4           5            call-clobbered
145         arg 5           6            call-saved
146         arg 6           7            call-saved
147
148    (Of course a function with say 3 arguments does not have entries for
149    arguments 4 and 5.)
150    For system calls with 6 parameters a stack operation is required
151    to load the 6th parameter to register 7. Call saved register 7 is
152    moved to register 0 and back to avoid an additional stack frame.
153  */
154
155 #define DO_CALL(syscall, args)                                                \
156   .if args > 5;                                                               \
157     lr %r0,%r7;                                                               \
158     l %r7,96(%r15);                                                           \
159   .endif;                                                                     \
160   .if SYS_ify (syscall) < 256;                                                \
161     svc SYS_ify (syscall);                                                    \
162   .else;                                                                      \
163     lhi %r1,SYS_ify (syscall);                                                \
164     svc 0;                                                                    \
165   .endif;                                                                     \
166   .if args > 5;                                                               \
167     lr %r7,%r0;                                                               \
168   .endif
169
170 #define ret                                                                   \
171     br      14
172
173 #define ret_NOERRNO                                                           \
174     br      14
175
176 #define ret_ERRVAL                                                            \
177     br      14
178
179 #endif /* __ASSEMBLER__ */
180
181 #undef INLINE_SYSCALL
182 #define INLINE_SYSCALL(name, nr, args...)                                     \
183   ({                                                                          \
184     unsigned int _ret = INTERNAL_SYSCALL (name, , nr, args);                  \
185     if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_ret, ), 0))              \
186      {                                                                        \
187        __set_errno (INTERNAL_SYSCALL_ERRNO (_ret, ));                         \
188        _ret = 0xffffffff;                                                     \
189      }                                                                        \
190     (int) _ret; })
191
192 #undef INTERNAL_SYSCALL_DECL
193 #define INTERNAL_SYSCALL_DECL(err) do { } while (0)
194
195 #undef INTERNAL_SYSCALL_DIRECT
196 #define INTERNAL_SYSCALL_DIRECT(name, err, nr, args...)                       \
197   ({                                                                          \
198     DECLARGS_##nr(args)                                                       \
199     register int _ret asm("2");                                               \
200     asm volatile (                                                            \
201     "svc    %b1\n\t"                                                          \
202     : "=d" (_ret)                                                             \
203     : "i" (__NR_##name) ASMFMT_##nr                                           \
204     : "memory" );                                                             \
205     _ret; })
206
207 #undef INTERNAL_SYSCALL_SVC0
208 #define INTERNAL_SYSCALL_SVC0(name, err, nr, args...)                         \
209   ({                                                                          \
210     DECLARGS_##nr(args)                                                       \
211     register unsigned long _nr asm("1") = (unsigned long)(__NR_##name);       \
212     register int _ret asm("2");                                               \
213     asm volatile (                                                            \
214     "svc    0\n\t"                                                            \
215     : "=d" (_ret)                                                             \
216     : "d" (_nr) ASMFMT_##nr                                                   \
217     : "memory" );                                                             \
218     _ret; })
219
220 #undef INTERNAL_SYSCALL_NCS
221 #define INTERNAL_SYSCALL_NCS(no, err, nr, args...)                            \
222   ({                                                                          \
223     DECLARGS_##nr(args)                                                       \
224     register unsigned long _nr asm("1") = (unsigned long)(no);                \
225     register int _ret asm("2");                                               \
226     asm volatile (                                                            \
227     "svc    0\n\t"                                                            \
228     : "=d" (_ret)                                                             \
229     : "d" (_nr) ASMFMT_##nr                                                   \
230     : "memory" );                                                             \
231     _ret; })
232
233 #undef INTERNAL_SYSCALL
234 #define INTERNAL_SYSCALL(name, err, nr, args...)                              \
235   (((__NR_##name) < 256) ?                                                    \
236     INTERNAL_SYSCALL_DIRECT(name, err, nr, args) :                            \
237     INTERNAL_SYSCALL_SVC0(name, err,nr, args))
238
239 #undef INTERNAL_SYSCALL_ERROR_P
240 #define INTERNAL_SYSCALL_ERROR_P(val, err)                                    \
241   ((unsigned int) (val) >= 0xfffff001u)
242
243 #undef INTERNAL_SYSCALL_ERRNO
244 #define INTERNAL_SYSCALL_ERRNO(val, err)        (-(val))
245
246 #define DECLARGS_0()
247 #define DECLARGS_1(arg1) \
248         register unsigned long gpr2 asm ("2") = (unsigned long)(arg1);
249 #define DECLARGS_2(arg1, arg2) \
250         DECLARGS_1(arg1) \
251         register unsigned long gpr3 asm ("3") = (unsigned long)(arg2);
252 #define DECLARGS_3(arg1, arg2, arg3) \
253         DECLARGS_2(arg1, arg2) \
254         register unsigned long gpr4 asm ("4") = (unsigned long)(arg3);
255 #define DECLARGS_4(arg1, arg2, arg3, arg4) \
256         DECLARGS_3(arg1, arg2, arg3) \
257         register unsigned long gpr5 asm ("5") = (unsigned long)(arg4);
258 #define DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
259         DECLARGS_4(arg1, arg2, arg3, arg4) \
260         register unsigned long gpr6 asm ("6") = (unsigned long)(arg5);
261 #define DECLARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
262         DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \
263         register unsigned long gpr7 asm ("7") = (unsigned long)(arg6);
264
265 #define ASMFMT_0
266 #define ASMFMT_1 , "0" (gpr2)
267 #define ASMFMT_2 , "0" (gpr2), "d" (gpr3)
268 #define ASMFMT_3 , "0" (gpr2), "d" (gpr3), "d" (gpr4)
269 #define ASMFMT_4 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5)
270 #define ASMFMT_5 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6)
271 #define ASMFMT_6 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6), "d" (gpr7)
272
273 #define CLOBBER_0 , "3", "4", "5"
274 #define CLOBBER_1 , "3", "4", "5"
275 #define CLOBBER_2 , "4", "5"
276 #define CLOBBER_3 , "5"
277 #define CLOBBER_4
278 #define CLOBBER_5
279 #define CLOBBER_6
280
281 /* List of system calls which are supported as vsyscalls.  */
282 #define HAVE_CLOCK_GETRES_VSYSCALL      1
283 #define HAVE_CLOCK_GETTIME_VSYSCALL     1
284
285 /* This version is for kernels that implement system calls that
286    behave like function calls as far as register saving.
287    It falls back to the syscall in the case that the vDSO doesn't
288    exist or fails for ENOSYS */
289 #ifdef SHARED
290 # define INLINE_VSYSCALL(name, nr, args...) \
291   ({                                                                          \
292     __label__ out;                                                            \
293     __label__ iserr;                                                          \
294     long int _ret;                                                            \
295                                                                               \
296     if (__vdso_##name != NULL)                                                \
297       {                                                                       \
298         _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, , nr, ##args);           \
299         if (!INTERNAL_SYSCALL_ERROR_P (_ret, ))                               \
300           goto out;                                                           \
301         if (INTERNAL_SYSCALL_ERRNO (_ret, ) != ENOSYS)                        \
302           goto iserr;                                                         \
303       }                                                                       \
304                                                                               \
305     _ret = INTERNAL_SYSCALL (name, , nr, ##args);                             \
306     if (INTERNAL_SYSCALL_ERROR_P (_ret, ))                                    \
307       {                                                                       \
308       iserr:                                                                  \
309         __set_errno (INTERNAL_SYSCALL_ERRNO (_ret, ));                        \
310         _ret = -1L;                                                           \
311       }                                                                       \
312   out:                                                                        \
313     (int) _ret;                                                               \
314   })
315 #else
316 # define INLINE_VSYSCALL(name, nr, args...) \
317   INLINE_SYSCALL (name, nr, ##args)
318 #endif
319
320 #ifdef SHARED
321 # define INTERNAL_VSYSCALL(name, err, nr, args...) \
322   ({                                                                          \
323     __label__ out;                                                            \
324     long int _ret;                                                            \
325                                                                               \
326     if (__vdso_##name != NULL)                                                \
327       {                                                                       \
328         _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args);        \
329         if (!INTERNAL_SYSCALL_ERROR_P (_ret, err)                             \
330             || INTERNAL_SYSCALL_ERRNO (_ret, err) != ENOSYS)                  \
331           goto out;                                                           \
332       }                                                                       \
333     _ret = INTERNAL_SYSCALL (name, err, nr, ##args);                          \
334   out:                                                                        \
335     _ret;                                                                     \
336   })
337 #else
338 # define INTERNAL_VSYSCALL(name, err, nr, args...) \
339   INTERNAL_SYSCALL (name, err, nr, ##args)
340 #endif
341
342 /* This version is for internal uses when there is no desire
343    to set errno */
344 #define INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK(name, err, nr, args...)         \
345   ({                                                                          \
346     long int _ret = ENOSYS;                                                   \
347                                                                               \
348     if (__vdso_##name != NULL)                                                \
349       _ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args);          \
350     else                                                                      \
351       err = 1 << 28;                                                          \
352     _ret;                                                                     \
353   })
354
355 #define INTERNAL_VSYSCALL_NCS(fn, err, nr, args...)                           \
356   ({                                                                          \
357     DECLARGS_##nr(args)                                                       \
358     register long _ret asm("2");                                                      \
359     asm volatile (                                                            \
360     "lr 10,14\n\t"                                                           \
361     "basr 14,%1\n\t"                                                          \
362     "lr 14,10\n\t"                                                           \
363     : "=d" (_ret)                                                             \
364     : "d" (fn) ASMFMT_##nr                                                    \
365     : "cc", "memory", "0", "1", "10" CLOBBER_##nr);                          \
366     _ret; })
367
368 /* Pointer mangling support.  */
369 #if defined NOT_IN_libc && defined IS_IN_rtld
370 /* We cannot use the thread descriptor because in ld.so we use setjmp
371    earlier than the descriptor is initialized.  */
372 #else
373 /* For the time being just use stack_guard rather than a separate
374    pointer_guard.  */
375 # ifdef __ASSEMBLER__
376 #  define PTR_MANGLE(reg, tmpreg) \
377   ear     tmpreg,%a0;                   \
378   x       reg,STACK_GUARD(tmpreg)
379 #  define PTR_MANGLE2(reg, tmpreg) \
380   x       reg,STACK_GUARD(tmpreg)
381 #  define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg)
382 # else
383 #  define PTR_MANGLE(var) \
384   (var) = (void *) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ())
385 #  define PTR_DEMANGLE(var)     PTR_MANGLE (var)
386 # endif
387 #endif
388
389 #endif /* _LINUX_S390_SYSDEP_H */