1 /* Copyright (C) 2011-2018 Free Software Foundation, Inc.
2 
3    The GNU C Library is free software; you can redistribute it and/or
4    modify it under the terms of the GNU Lesser General Public
5    License as published by the Free Software Foundation; either
6    version 2.1 of the License, or (at your option) any later version.
7 
8    The GNU C Library is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11    Lesser General Public License for more details.
12 
13    You should have received a copy of the GNU Lesser General Public
14    License along with the GNU C Library.  If not, see
15    <http://www.gnu.org/licenses/>.  */
16 
17 #ifndef _BITS_SYSCALLS_H
18 #define _BITS_SYSCALLS_H
19 #ifndef _SYSCALL_H
20 # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
21 #endif
22 
23 /* Define a macro which expands inline into the wrapper code for a system
24    call.  */
25 # undef INLINE_SYSCALL
26 # define INLINE_SYSCALL(name, nr, args...)                              \
27   ({                                                                    \
28     INTERNAL_SYSCALL_DECL (_sc_err);                                    \
29     unsigned long _sc_val = INTERNAL_SYSCALL (name, _sc_err, nr, args); \
30     if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sc_val, _sc_err), 0)) \
31     {                                                                   \
32       __set_errno (INTERNAL_SYSCALL_ERRNO (_sc_val, _sc_err));          \
33       _sc_val = -1;                                                     \
34     }                                                                   \
35     (long) _sc_val;                                                     \
36   })
37 
38 #undef INTERNAL_SYSCALL
39 #define INTERNAL_SYSCALL(name, err, nr, args...)        \
40   internal_syscall##nr (SYS_ify (name), err, args)
41 
42 #undef INTERNAL_SYSCALL_NCS
43 #define INTERNAL_SYSCALL_NCS(number, err, nr, args...)  \
44   internal_syscall##nr (number, err, args)
45 
46 #undef INTERNAL_SYSCALL_DECL
47 #define INTERNAL_SYSCALL_DECL(err) int err
48 
49 #undef INTERNAL_SYSCALL_ERROR_P
50 #define INTERNAL_SYSCALL_ERROR_P(val, err) ({ (void) (val); (err) != 0; })
51 
52 #undef INTERNAL_SYSCALL_ERRNO
53 #define INTERNAL_SYSCALL_ERRNO(val, err) ({ (void) (val); (err); })
54 
55 #define internal_syscall0(num, err, dummy...)                           \
56   ({                                                                    \
57     long _sys_result, __SYSCALL_CLOBBER_DECLS;                          \
58     __asm__ __volatile__ (                                              \
59       "swint1"                                                          \
60       : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS   \
61       : "R10" (num)                                                     \
62       : __SYSCALL_CLOBBERS);                                            \
63     _sys_result;                                                        \
64   })
65 
66 #define internal_syscall1(num, err, arg0)                               \
67   ({                                                                    \
68     long _sys_result, __SYSCALL_CLOBBER_DECLS;                          \
69     __asm__ __volatile__ (                                              \
70       "swint1"                                                          \
71       : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS   \
72       : "R10" (num), "R00" (arg0)                                       \
73       : __SYSCALL_CLOBBERS);                                            \
74     _sys_result;                                                        \
75   })
76 
77 #define internal_syscall2(num, err, arg0, arg1)                         \
78   ({                                                                    \
79     long _sys_result, __SYSCALL_CLOBBER_DECLS;                          \
80     __asm__ __volatile__ (                                              \
81       "swint1"                                                          \
82       : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS   \
83       : "R10" (num), "R00" (arg0), "R01" (arg1)                         \
84       : __SYSCALL_CLOBBERS);                                            \
85     _sys_result;                                                        \
86   })
87 
88 #define internal_syscall3(num, err, arg0, arg1, arg2)                   \
89   ({                                                                    \
90     long _sys_result, __SYSCALL_CLOBBER_DECLS;                          \
91     __asm__ __volatile__ (                                              \
92       "swint1"                                                          \
93       : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS   \
94       : "R10" (num), "R00" (arg0), "R01" (arg1), "R02" (arg2)           \
95       : __SYSCALL_CLOBBERS);                                            \
96     _sys_result;                                                        \
97   })
98 
99 #define internal_syscall4(num, err, arg0, arg1, arg2, arg3)             \
100   ({                                                                    \
101     long _sys_result, __SYSCALL_CLOBBER_DECLS;                          \
102     __asm__ __volatile__ (                                              \
103       "swint1"                                                          \
104       : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS   \
105       : "R10" (num), "R00" (arg0), "R01" (arg1), "R02" (arg2),          \
106         "R03" (arg3)                                                    \
107       : __SYSCALL_CLOBBERS);                                            \
108     _sys_result;                                                        \
109   })
110 
111 #define internal_syscall5(num, err, arg0, arg1, arg2, arg3, arg4)       \
112   ({                                                                    \
113     long _sys_result, __SYSCALL_CLOBBER_DECLS;                          \
114     __asm__ __volatile__ (                                              \
115       "swint1"                                                          \
116       : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS   \
117       : "R10" (num), "R00" (arg0), "R01" (arg1), "R02" (arg2),          \
118         "R03" (arg3), "R04" (arg4)                                      \
119       : __SYSCALL_CLOBBERS);                                            \
120     _sys_result;                                                        \
121   })
122 
123 #define internal_syscall6(num, err, arg0, arg1, arg2, arg3, arg4, arg5) \
124   ({                                                                    \
125     long _sys_result, __SYSCALL_CLOBBER_DECLS;                          \
126     __asm__ __volatile__ (                                              \
127       "swint1"                                                          \
128       : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS   \
129       : "R10" (num), "R00" (arg0), "R01" (arg1), "R02" (arg2),          \
130         "R03" (arg3), "R04" (arg4), "R05" (arg5)                        \
131       : __SYSCALL_CLOBBERS);                                            \
132     _sys_result;                                                        \
133   })
134 
135 #undef __SYSCALL_CLOBBERS
136 #define __SYSCALL_CLOBBERS                                      \
137   "r6",  "r7",                                                  \
138     "r8",  "r9",        "r11", "r12", "r13", "r14", "r15",      \
139     "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",     \
140     "r24", "r25", "r26", "r27", "r28", "r29", "memory"
141 
142 /* gcc doesn't seem to allow an input operand to be clobbered, so we
143    fake it with dummy outputs. */
144 #define __SYSCALL_CLOBBER_DECLS                                         \
145   _clobber_r2, _clobber_r3, _clobber_r4, _clobber_r5, _clobber_r10
146 
147 #define __SYSCALL_CLOBBER_OUTPUTS                                       \
148   "=R02" (_clobber_r2), "=R03" (_clobber_r3), "=R04" (_clobber_r4),     \
149     "=R05" (_clobber_r5), "=R10" (_clobber_r10)
150 
151 #endif
152