blob f0e8d64e (6993B) - Raw
1 /* Copyright (C) 2005-2025 Free Software Foundation, Inc. 2 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 License as 7 published by the Free Software Foundation; either version 2.1 of the 8 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 <https://www.gnu.org/licenses/>. */ 18 19 #ifndef _LINUX_AARCH64_SYSDEP_H 20 #define _LINUX_AARCH64_SYSDEP_H 1 21 22 #include <sysdeps/unix/sysdep.h> 23 #include <sysdeps/aarch64/sysdep.h> 24 #include <sysdeps/unix/sysdep.h> 25 #include <sysdeps/unix/sysv/linux/sysdep.h> 26 27 /* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO. */ 28 #include <dl-sysdep.h> 29 30 #include <tls.h> 31 32 /* In order to get __set_errno() definition in INLINE_SYSCALL. */ 33 #ifndef __ASSEMBLER__ 34 #include <errno.h> 35 #endif 36 37 /* For Linux we can use the system call table in the header file 38 /usr/include/asm/unistd.h 39 of the kernel. But these symbols do not follow the SYS_* syntax 40 so we have to redefine the `SYS_ify' macro here. */ 41 #undef SYS_ify 42 #define SYS_ify(syscall_name) (__NR_##syscall_name) 43 44 #ifdef __ASSEMBLER__ 45 46 /* Linux uses a negative return value to indicate syscall errors, 47 unlike most Unices, which use the condition codes' carry flag. 48 49 Since version 2.1 the return value of a system call might be 50 negative even if the call succeeded. E.g., the `lseek' system call 51 might return a large offset. Therefore we must not anymore test 52 for < 0, but test for a real error by making sure the value in R0 53 is a real error number. Linus said he will make sure the no syscall 54 returns a value in -1 .. -4095 as a valid result so we can safely 55 test with -4095. */ 56 57 # undef PSEUDO 58 # define PSEUDO(name, syscall_name, args) \ 59 .text; \ 60 ENTRY (name); \ 61 DO_CALL (syscall_name, args); \ 62 cmn x0, #4095; \ 63 b.cs .Lsyscall_error; 64 65 # undef PSEUDO_END 66 # define PSEUDO_END(name) \ 67 SYSCALL_ERROR_HANDLER \ 68 END (name) 69 70 # undef PSEUDO_NOERRNO 71 # define PSEUDO_NOERRNO(name, syscall_name, args) \ 72 .text; \ 73 ENTRY (name); \ 74 DO_CALL (syscall_name, args); 75 76 # undef PSEUDO_END_NOERRNO 77 # define PSEUDO_END_NOERRNO(name) \ 78 END (name) 79 80 # define ret_NOERRNO ret 81 82 /* The function has to return the error code. */ 83 # undef PSEUDO_ERRVAL 84 # define PSEUDO_ERRVAL(name, syscall_name, args) \ 85 .text; \ 86 ENTRY (name) \ 87 DO_CALL (syscall_name, args); \ 88 neg x0, x0 89 90 # undef PSEUDO_END_ERRVAL 91 # define PSEUDO_END_ERRVAL(name) \ 92 END (name) 93 94 # define ret_ERRVAL ret 95 96 # if !IS_IN (libc) 97 # define SYSCALL_ERROR .Lsyscall_error 98 # if RTLD_PRIVATE_ERRNO 99 # define SYSCALL_ERROR_HANDLER \ 100 .Lsyscall_error: \ 101 adrp x1, C_SYMBOL_NAME(rtld_errno); \ 102 neg w0, w0; \ 103 str w0, [x1, :lo12:C_SYMBOL_NAME(rtld_errno)]; \ 104 mov x0, -1; \ 105 RET; 106 # else 107 108 # define SYSCALL_ERROR_HANDLER \ 109 .Lsyscall_error: \ 110 adrp x1, :gottprel:errno; \ 111 neg w2, w0; \ 112 ldr PTR_REG(1), [x1, :gottprel_lo12:errno]; \ 113 mrs x3, tpidr_el0; \ 114 mov x0, -1; \ 115 str w2, [x1, x3]; \ 116 RET; 117 # endif 118 # else 119 # define SYSCALL_ERROR __syscall_error 120 # define SYSCALL_ERROR_HANDLER \ 121 .Lsyscall_error: \ 122 b __syscall_error; 123 # endif 124 125 /* Linux takes system call args in registers: 126 syscall number x8 127 arg 1 x0 128 arg 2 x1 129 arg 3 x2 130 arg 4 x3 131 arg 5 x4 132 arg 6 x5 133 arg 7 x6 134 135 The compiler is going to form a call by coming here, through PSEUDO, with 136 arguments 137 syscall number in the DO_CALL macro 138 arg 1 x0 139 arg 2 x1 140 arg 3 x2 141 arg 4 x3 142 arg 5 x4 143 arg 6 x5 144 arg 7 x6 145 146 */ 147 148 # undef DO_CALL 149 # define DO_CALL(syscall_name, args) \ 150 mov x8, SYS_ify (syscall_name); \ 151 svc 0 152 153 #else /* not __ASSEMBLER__ */ 154 155 # define VDSO_NAME "LINUX_2.6.39" 156 # define VDSO_HASH 123718537 157 158 /* List of system calls which are supported as vsyscalls. */ 159 # define HAVE_CLOCK_GETRES64_VSYSCALL "__kernel_clock_getres" 160 # define HAVE_CLOCK_GETTIME64_VSYSCALL "__kernel_clock_gettime" 161 # define HAVE_GETTIMEOFDAY_VSYSCALL "__kernel_gettimeofday" 162 # define HAVE_GETRANDOM_VSYSCALL "__kernel_getrandom" 163 164 # define HAVE_CLONE3_WRAPPER 1 165 166 # undef INTERNAL_SYSCALL_RAW 167 # define INTERNAL_SYSCALL_RAW(name, nr, args...) \ 168 ({ long _sys_result; \ 169 { \ 170 LOAD_ARGS_##nr (args) \ 171 register long _x8 asm ("x8") = (name); \ 172 asm volatile ("svc 0 // syscall " # name \ 173 : "=r" (_x0) : "r"(_x8) ASM_ARGS_##nr : "memory"); \ 174 _sys_result = _x0; \ 175 } \ 176 _sys_result; }) 177 178 # undef INTERNAL_SYSCALL 179 # define INTERNAL_SYSCALL(name, nr, args...) \ 180 INTERNAL_SYSCALL_RAW(SYS_ify(name), nr, args) 181 182 # undef INTERNAL_SYSCALL_AARCH64 183 # define INTERNAL_SYSCALL_AARCH64(name, nr, args...) \ 184 INTERNAL_SYSCALL_RAW(__ARM_NR_##name, nr, args) 185 186 # define LOAD_ARGS_0() \ 187 register long _x0 asm ("x0"); 188 # define LOAD_ARGS_1(x0) \ 189 long _x0tmp = (long) (x0); \ 190 LOAD_ARGS_0 () \ 191 _x0 = _x0tmp; 192 # define LOAD_ARGS_2(x0, x1) \ 193 long _x1tmp = (long) (x1); \ 194 LOAD_ARGS_1 (x0) \ 195 register long _x1 asm ("x1") = _x1tmp; 196 # define LOAD_ARGS_3(x0, x1, x2) \ 197 long _x2tmp = (long) (x2); \ 198 LOAD_ARGS_2 (x0, x1) \ 199 register long _x2 asm ("x2") = _x2tmp; 200 # define LOAD_ARGS_4(x0, x1, x2, x3) \ 201 long _x3tmp = (long) (x3); \ 202 LOAD_ARGS_3 (x0, x1, x2) \ 203 register long _x3 asm ("x3") = _x3tmp; 204 # define LOAD_ARGS_5(x0, x1, x2, x3, x4) \ 205 long _x4tmp = (long) (x4); \ 206 LOAD_ARGS_4 (x0, x1, x2, x3) \ 207 register long _x4 asm ("x4") = _x4tmp; 208 # define LOAD_ARGS_6(x0, x1, x2, x3, x4, x5) \ 209 long _x5tmp = (long) (x5); \ 210 LOAD_ARGS_5 (x0, x1, x2, x3, x4) \ 211 register long _x5 asm ("x5") = _x5tmp; 212 # define LOAD_ARGS_7(x0, x1, x2, x3, x4, x5, x6)\ 213 long _x6tmp = (long) (x6); \ 214 LOAD_ARGS_6 (x0, x1, x2, x3, x4, x5) \ 215 register long _x6 asm ("x6") = _x6tmp; 216 217 # define ASM_ARGS_0 218 # define ASM_ARGS_1 , "r" (_x0) 219 # define ASM_ARGS_2 ASM_ARGS_1, "r" (_x1) 220 # define ASM_ARGS_3 ASM_ARGS_2, "r" (_x2) 221 # define ASM_ARGS_4 ASM_ARGS_3, "r" (_x3) 222 # define ASM_ARGS_5 ASM_ARGS_4, "r" (_x4) 223 # define ASM_ARGS_6 ASM_ARGS_5, "r" (_x5) 224 # define ASM_ARGS_7 ASM_ARGS_6, "r" (_x6) 225 226 # undef INTERNAL_SYSCALL_NCS 227 # define INTERNAL_SYSCALL_NCS(number, nr, args...) \ 228 INTERNAL_SYSCALL_RAW (number, nr, args) 229 230 #undef HAVE_INTERNAL_BRK_ADDR_SYMBOL 231 #define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1 232 233 #endif /* __ASSEMBLER__ */ 234 235 #endif /* linux/aarch64/sysdep.h */