1 #ifndef _BITS_SYSCALLS_H
2 #define _BITS_SYSCALLS_H
3 #ifndef _SYSCALL_H
4 # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
5 #endif
6 
7 /*
8    Some of the sneaky macros in the code were taken from
9    glibc-2.3.2/sysdeps/unix/sysv/linux/arm/sysdep.h
10 */
11 
12 #ifdef __ASSEMBLER__
13 
14 /* Call a given syscall, with arguments loaded.  For EABI, we must
15    save and restore r7 for the syscall number.  Unlike the DO_CALL
16    macro in glibc, this macro does not load syscall arguments.  */
17 #undef DO_CALL
18 #if defined(__ARM_EABI__)
19 #define DO_CALL(syscall_name)			\
20     mov ip, r7;					\
21     ldr r7, =SYS_ify (syscall_name);		\
22     swi 0x0;					\
23     mov r7, ip;
24 #else
25 #define DO_CALL(syscall_name)			\
26     swi SYS_ify (syscall_name);
27 #endif
28 
29 #else
30 
31 #include <errno.h>
32 
33 #define INLINE_SYSCALL_NCS(name, nr, args...)				\
34 (__extension__								\
35   ({									\
36      unsigned int _inline_sys_result = INTERNAL_SYSCALL_NCS (name, , nr, args);\
37      if (unlikely (INTERNAL_SYSCALL_ERROR_P (_inline_sys_result, )))	\
38        {								\
39 	 __set_errno (INTERNAL_SYSCALL_ERRNO (_inline_sys_result, ));	\
40 	 _inline_sys_result = (unsigned int) -1;			\
41        }								\
42      (int) _inline_sys_result;						\
43    })									\
44 )
45 
46 #define INTERNAL_SYSCALL_ARM(name, err, nr, args...)           \
47 	INTERNAL_SYSCALL_NCS(__ARM_NR_##name, err, nr, args)
48 
49 #if defined(__thumb__)
50 /* We can't use push/pop inside the asm because that breaks
51    unwinding (ie. thread cancellation).
52  */
53 #define INTERNAL_SYSCALL_NCS(name, err, nr, args...)			\
54 (__extension__ \
55   ({ unsigned int __internal_sys_result;				\
56     {									\
57       int _sys_buf[2];							\
58       register int __a1 __asm__ ("a1");					\
59       register int *__v3 __asm__ ("v3") = _sys_buf;			\
60       *__v3 = (int) (name);						\
61       LOAD_ARGS_##nr (args)						\
62       __asm__ __volatile__ ("str	r7, [v3, #4]\n"			\
63 		    "\tldr	r7, [v3]\n"				\
64 		    "\tswi	0	@ syscall " #name "\n"		\
65 		    "\tldr	r7, [v3, #4]"				\
66 		    : "=r" (__a1)					\
67 		    : "r" (__v3) ASM_ARGS_##nr				\
68                     : "memory");					\
69 	__internal_sys_result = __a1;					\
70     }									\
71     (int) __internal_sys_result; }) \
72 )
73 #else /* ARM */
74 #define INTERNAL_SYSCALL_NCS(name, err, nr, args...)			\
75 (__extension__ \
76   ({unsigned int __internal_sys_result;					\
77      {									\
78        register int __a1 __asm__ ("r0"), _nr __asm__ ("r7");		\
79        LOAD_ARGS_##nr (args)						\
80        _nr = (name);							\
81        __asm__ __volatile__ ("swi	0x0	@ syscall " #name	\
82 			     : "=r" (__a1)				\
83 			     : "r" (_nr) ASM_ARGS_##nr			\
84 			     : "memory");				\
85 	       __internal_sys_result = __a1;				\
86      }									\
87      (int) __internal_sys_result; }) \
88 )
89 #endif
90 
91 #define INTERNAL_SYSCALL_ERROR_P(val, err) \
92   ((unsigned int) (val) >= 0xfffff001u)
93 
94 #define LOAD_ARGS_0()
95 #define ASM_ARGS_0
96 #define LOAD_ARGS_1(a1)				\
97   int __a1tmp = (int) (a1);			\
98   LOAD_ARGS_0 ()				\
99   __a1 = __a1tmp;
100 #define ASM_ARGS_1	ASM_ARGS_0, "r" (__a1)
101 #define LOAD_ARGS_2(a1, a2)			\
102   int __a2tmp = (int) (a2);			\
103   LOAD_ARGS_1 (a1)				\
104   register int __a2 __asm__ ("a2") = __a2tmp;
105 #define ASM_ARGS_2	ASM_ARGS_1, "r" (__a2)
106 #define LOAD_ARGS_3(a1, a2, a3)			\
107   int __a3tmp = (int) (a3);			\
108   LOAD_ARGS_2 (a1, a2)				\
109   register int __a3 __asm__ ("a3") = __a3tmp;
110 #define ASM_ARGS_3	ASM_ARGS_2, "r" (__a3)
111 #define LOAD_ARGS_4(a1, a2, a3, a4)		\
112   int __a4tmp = (int) (a4);			\
113   LOAD_ARGS_3 (a1, a2, a3)			\
114   register int __a4 __asm__ ("a4") = __a4tmp;
115 #define ASM_ARGS_4	ASM_ARGS_3, "r" (__a4)
116 #define LOAD_ARGS_5(a1, a2, a3, a4, a5)		\
117   int __v1tmp = (int) (a5);			\
118   LOAD_ARGS_4 (a1, a2, a3, a4)			\
119   register int __v1 __asm__ ("v1") = __v1tmp;
120 #define ASM_ARGS_5	ASM_ARGS_4, "r" (__v1)
121 #define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6)	\
122   int __v2tmp = (int) (a6);			\
123   LOAD_ARGS_5 (a1, a2, a3, a4, a5)		\
124   register int __v2 __asm__ ("v2") = __v2tmp;
125 #define ASM_ARGS_6	ASM_ARGS_5, "r" (__v2)
126 #ifndef __thumb__
127 #define LOAD_ARGS_7(a1, a2, a3, a4, a5, a6, a7)	\
128   int __v3tmp = (int) (a7);			\
129   LOAD_ARGS_6 (a1, a2, a3, a4, a5, a6)		\
130   register int __v3 __asm__ ("v3") = __v3tmp;
131 #define ASM_ARGS_7	ASM_ARGS_6, "r" (__v3)
132 #endif
133 
134 #endif /* __ASSEMBLER__ */
135 #endif /* _BITS_SYSCALLS_H */
136