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