1 /*
2  * Copyright (C) 2016 by Waldemar Brodkorb <wbx@uclibc-ng.org>
3  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
4  * ported from GNU libc
5  */
6 
7 /* Copyright (C) 2005-2016 Free Software Foundation, Inc.
8 
9 This file is part of the GNU C Library.
10 
11 The GNU C Library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public License as
13 published by the Free Software Foundation; either version 2.1 of the
14 License, or (at your option) any later version.
15 
16 The GNU C Library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 Lesser General Public License for more details.
20 
21 You should have received a copy of the GNU Lesser General Public
22 License along with the GNU C Library; if not, see
23 <http://www.gnu.org/licenses/>.  */
24 
25 #ifndef _BITS_SYSCALLS_H
26 #define _BITS_SYSCALLS_H
27 #ifndef _SYSCALL_H
28 # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
29 #endif
30 
31 #ifndef __ASSEMBLER__
32 #include <errno.h>
33 
34 /* For Linux we can use the system call table in the header file
35  * 	/usr/include/asm/unistd.h
36  * 	   of the kernel.  But these symbols do not follow the SYS_* syntax
37  * 	      so we have to redefine the `SYS_ify' macro here.  */
38 #undef SYS_ify
39 #define SYS_ify(syscall_name)	(__NR_##syscall_name)
40 
41 /* Define a macro which expands into the inline wrapper code for a system
42    call.  */
43 # undef INLINE_SYSCALL
44 # define INLINE_SYSCALL(name, nr, args...)				\
45   ({ unsigned long _sys_result = INTERNAL_SYSCALL (name, , nr, args);	\
46      if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result, ), 0))\
47        {								\
48 	 __set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, ));		\
49 	 _sys_result = (unsigned long) -1;				\
50        }								\
51      (long) _sys_result; })
52 
53 # undef INTERNAL_SYSCALL_DECL
54 # define INTERNAL_SYSCALL_DECL(err) do { } while (0)
55 
56 #define INTERNAL_SYSCALL_RAW(name, err, nr, args...)	\
57   ({ long _sys_result;					\
58      {							\
59 	LOAD_ARGS_##nr (args)				\
60 	register long _x8 __asm__ ("x8") = (name);	\
61         __asm__ volatile (				\
62 		"svc       0       // syscall " # name  \
63 		: "=r" (_x0) : "r"(_x8) ASM_ARGS_##nr : "memory"); \
64 	_sys_result = _x0;				\
65      } 							\
66      _sys_result; })
67 
68 # undef INTERNAL_SYSCALL
69 # define INTERNAL_SYSCALL(name, err, nr, args...)		\
70 	INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args)
71 
72 # undef INTERNAL_SYSCALL_AARCH64
73 # define INTERNAL_SYSCALL_AARCH64(name, err, nr, args...)	\
74 	INTERNAL_SYSCALL_RAW(__ARM_NR_##name, err, nr, args)
75 
76 # undef INTERNAL_SYSCALL_ERROR_P
77 # define INTERNAL_SYSCALL_ERROR_P(val, err) \
78    ((unsigned long) (val) >= (unsigned long) -4095)
79 
80 # undef INTERNAL_SYSCALL_ERRNO
81 # define INTERNAL_SYSCALL_ERRNO(val, err)       (-(val))
82 
83 /* Macros for setting up inline __asm__ input regs */
84 # define ASM_ARGS_0
85 # define ASM_ARGS_1	, "r" (_x0)
86 # define ASM_ARGS_2	ASM_ARGS_1, "r" (_x1)
87 # define ASM_ARGS_3	ASM_ARGS_2, "r" (_x2)
88 # define ASM_ARGS_4	ASM_ARGS_3, "r" (_x3)
89 # define ASM_ARGS_5	ASM_ARGS_4, "r" (_x4)
90 # define ASM_ARGS_6	ASM_ARGS_5, "r" (_x5)
91 # define ASM_ARGS_7	ASM_ARGS_6, "r" (_x6)
92 
93 /* Macros for converting sys-call wrapper args into sys call args */
94 # define LOAD_ARGS_0()				\
95   register long _x0 __asm__ ("x0");
96 # define LOAD_ARGS_1(x0)			\
97   long _x0tmp;					\
98   LOAD_ARGS_0 ()				\
99   _x0tmp = (long) (x0);				\
100   _x0 = _x0tmp;
101 # define LOAD_ARGS_2(x0, x1)			\
102   register long _x1 __asm__ ("x1");		\
103   long _x1tmp;					\
104   LOAD_ARGS_1 (x0)				\
105   _x1tmp = (long) (x1);				\
106   _x1 = _x1tmp;
107 # define LOAD_ARGS_3(x0, x1, x2)		\
108   register long _x2 __asm__ ("x2");		\
109   long _x2tmp;					\
110   LOAD_ARGS_2 (x0, x1)				\
111   _x2tmp = (long) (x2);				\
112   _x2 = _x2tmp;
113 # define LOAD_ARGS_4(x0, x1, x2, x3)		\
114   register long _x3 __asm__ ("x3");		\
115   long _x3tmp;					\
116   LOAD_ARGS_3 (x0, x1, x2)			\
117   _x3tmp = (long) (x3);				\
118   _x3 = _x3tmp;
119 # define LOAD_ARGS_5(x0, x1, x2, x3, x4)	\
120   register long _x4 __asm__ ("x4");		\
121   long _x4tmp;					\
122   LOAD_ARGS_4 (x0, x1, x2, x3)			\
123   _x4tmp = (long) (x4);				\
124   _x4 = _x4tmp;
125 # define LOAD_ARGS_6(x0, x1, x2, x3, x4, x5)	\
126   register long _x5 __asm__ ("x5");		\
127   long _x5tmp;					\
128   LOAD_ARGS_5 (x0, x1, x2, x3, x4)		\
129   _x5tmp = (long) (x5);				\
130   _x5 = _x5tmp;
131 # define LOAD_ARGS_7(x0, x1, x2, x3, x4, x5, x6)\
132   register long _x6 __asm__ ("x6");		\
133   long _x6tmp;					\
134   LOAD_ARGS_6 (x0, x1, x2, x3, x4, x5)		\
135   _x6tmp = (long) (x6);				\
136   _x6 = _x6tmp;
137 
138 # undef INTERNAL_SYSCALL_NCS
139 # define INTERNAL_SYSCALL_NCS(number, err, nr, args...)	\
140 		INTERNAL_SYSCALL_RAW (number, err, nr, args)
141 
142 #endif /* ! __ASSEMBLER__  */
143 #endif /* _BITS_SYSCALLS_H */
144