1 /* Copyright (C) 1992-2022 Free Software Foundation, Inc. 2 This file is part of the GNU C Library. 3 4 The GNU C Library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Lesser General Public 6 License as published by the Free Software Foundation; either 7 version 2.1 of the License, or (at your option) any later version. 8 9 The GNU C Library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public 15 License along with the GNU C Library. If not, see 16 <https://www.gnu.org/licenses/>. */ 17 18 #ifndef _LINUX_ARM_SYSDEP_H 19 #define _LINUX_ARM_SYSDEP_H 1 20 21 /* There is some commonality. */ 22 #include <sysdeps/unix/sysv/linux/sysdep.h> 23 #include <sysdeps/unix/arm/sysdep.h> 24 25 /* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO. */ 26 #include <dl-sysdep.h> 27 28 #include <tls.h> 29 30 /* For Linux we can use the system call table in the header file 31 /usr/include/asm/unistd.h 32 of the kernel. But these symbols do not follow the SYS_* syntax 33 so we have to redefine the `SYS_ify' macro here. */ 34 #undef SYS_ify 35 #define SYS_ify(syscall_name) (__NR_##syscall_name) 36 37 #include <bits/hwcap.h> 38 39 #ifdef __ASSEMBLER__ 40 41 #ifndef ARCH_HAS_HARD_TP 42 /* Internal macro calling the linux kernel kuser_get_tls helper. 43 Note that in thumb mode, a constant pool break is often out of range, so 44 we always expand the constant inline. */ 45 # ifdef __thumb2__ 46 # define GET_TLS_BODY \ 47 movw r0, #0x0fe0; \ 48 movt r0, #0xffff; \ 49 blx r0 50 # else 51 # define GET_TLS_BODY \ 52 mov r0, #0xffff0fff; /* Point to the high page. */ \ 53 mov lr, pc; /* Save our return address. */ \ 54 sub pc, r0, #31 /* Jump to the TLS entry. */ 55 # endif 56 57 /* Helper to get the TLS base pointer. Save LR in TMP, return in R0, 58 and no other registers clobbered. TMP may be LR itself to indicate 59 that no save is necessary. */ 60 # undef GET_TLS 61 # define GET_TLS(TMP) \ 62 .ifnc TMP, lr; \ 63 mov TMP, lr; \ 64 cfi_register (lr, TMP); \ 65 GET_TLS_BODY; \ 66 mov lr, TMP; \ 67 cfi_restore (lr); \ 68 .else; \ 69 GET_TLS_BODY; \ 70 .endif 71 #endif /* ARCH_HAS_HARD_TP */ 72 73 /* Linux uses a negative return value to indicate syscall errors, 74 unlike most Unices, which use the condition codes' carry flag. 75 76 Since version 2.1 the return value of a system call might be 77 negative even if the call succeeded. E.g., the `lseek' system call 78 might return a large offset. Therefore we must not anymore test 79 for < 0, but test for a real error by making sure the value in R0 80 is a real error number. Linus said he will make sure the no syscall 81 returns a value in -1 .. -4095 as a valid result so we can safely 82 test with -4095. */ 83 84 #undef PSEUDO 85 #define PSEUDO(name, syscall_name, args) \ 86 .text; \ 87 ENTRY (name); \ 88 DO_CALL (syscall_name, args); \ 89 cmn r0, $4096; 90 91 #define PSEUDO_RET \ 92 it cc; \ 93 RETINSTR(cc, lr); \ 94 b PLTJMP(SYSCALL_ERROR) 95 #undef ret 96 #define ret PSEUDO_RET 97 98 #undef PSEUDO_END 99 #define PSEUDO_END(name) \ 100 SYSCALL_ERROR_HANDLER; \ 101 END (name) 102 103 #undef PSEUDO_NOERRNO 104 #define PSEUDO_NOERRNO(name, syscall_name, args) \ 105 .text; \ 106 ENTRY (name); \ 107 DO_CALL (syscall_name, args); 108 109 #define PSEUDO_RET_NOERRNO \ 110 DO_RET (lr); 111 112 #undef ret_NOERRNO 113 #define ret_NOERRNO PSEUDO_RET_NOERRNO 114 115 #undef PSEUDO_END_NOERRNO 116 #define PSEUDO_END_NOERRNO(name) \ 117 END (name) 118 119 /* The function has to return the error code. */ 120 #undef PSEUDO_ERRVAL 121 #define PSEUDO_ERRVAL(name, syscall_name, args) \ 122 .text; \ 123 ENTRY (name) \ 124 DO_CALL (syscall_name, args); \ 125 rsb r0, r0, #0 126 127 #undef PSEUDO_END_ERRVAL 128 #define PSEUDO_END_ERRVAL(name) \ 129 END (name) 130 131 #define ret_ERRVAL PSEUDO_RET_NOERRNO 132 133 #if !IS_IN (libc) 134 # define SYSCALL_ERROR __local_syscall_error 135 # if RTLD_PRIVATE_ERRNO 136 # define SYSCALL_ERROR_HANDLER \ 137 __local_syscall_error: \ 138 rsb r0, r0, #0; \ 139 LDST_PCREL(str, r0, r1, C_SYMBOL_NAME(rtld_errno)); \ 140 mvn r0, #0; \ 141 DO_RET(lr) 142 # else 143 # if defined(__ARM_ARCH_4T__) && defined(__THUMB_INTERWORK__) 144 # define POP_PC \ 145 pop { lr }; \ 146 cfi_adjust_cfa_offset (-4); \ 147 cfi_restore (lr); \ 148 bx lr 149 # else 150 # define POP_PC pop { pc } 151 # endif 152 # define SYSCALL_ERROR_HANDLER \ 153 __local_syscall_error: \ 154 push { lr }; \ 155 cfi_adjust_cfa_offset (4); \ 156 cfi_rel_offset (lr, 0); \ 157 push { r0 }; \ 158 cfi_adjust_cfa_offset (4); \ 159 bl PLTJMP(C_SYMBOL_NAME(__errno_location)); \ 160 pop { r1 }; \ 161 cfi_adjust_cfa_offset (-4); \ 162 rsb r1, r1, #0; \ 163 str r1, [r0]; \ 164 mvn r0, #0; \ 165 POP_PC; 166 # endif 167 #else 168 # define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ 169 # define SYSCALL_ERROR __syscall_error 170 #endif 171 172 /* The ARM EABI user interface passes the syscall number in r7, instead 173 of in the swi. This is more efficient, because the kernel does not need 174 to fetch the swi from memory to find out the number; which can be painful 175 with separate I-cache and D-cache. Make sure to use 0 for the SWI 176 argument; otherwise the (optional) compatibility code for APCS binaries 177 may be invoked. */ 178 179 /* Linux takes system call args in registers: 180 arg 1 r0 181 arg 2 r1 182 arg 3 r2 183 arg 4 r3 184 arg 5 r4 (this is different from the APCS convention) 185 arg 6 r5 186 arg 7 r6 187 188 The compiler is going to form a call by coming here, through PSEUDO, with 189 arguments 190 syscall number in the DO_CALL macro 191 arg 1 r0 192 arg 2 r1 193 arg 3 r2 194 arg 4 r3 195 arg 5 [sp] 196 arg 6 [sp+4] 197 arg 7 [sp+8] 198 199 We need to shuffle values between R4..R6 and the stack so that the 200 caller's v1..v3 and stack frame are not corrupted, and the kernel 201 sees the right arguments. 202 203 */ 204 205 /* We must save and restore r7 (call-saved) for the syscall number. 206 We never make function calls from inside here (only potentially 207 signal handlers), so we do not bother with doubleword alignment. 208 209 Just like the APCS syscall convention, the EABI syscall convention uses 210 r0 through r6 for up to seven syscall arguments. None are ever passed to 211 the kernel on the stack, although incoming arguments are on the stack for 212 syscalls with five or more arguments. 213 214 The assembler will convert the literal pool load to a move for most 215 syscalls. */ 216 217 #undef DO_CALL 218 #define DO_CALL(syscall_name, args) \ 219 DOARGS_##args; \ 220 ldr r7, =SYS_ify (syscall_name); \ 221 swi 0x0; \ 222 UNDOARGS_##args 223 224 #undef DOARGS_0 225 #define DOARGS_0 \ 226 .fnstart; \ 227 push { r7 }; \ 228 cfi_adjust_cfa_offset (4); \ 229 cfi_rel_offset (r7, 0); \ 230 .save { r7 } 231 #undef DOARGS_1 232 #define DOARGS_1 DOARGS_0 233 #undef DOARGS_2 234 #define DOARGS_2 DOARGS_0 235 #undef DOARGS_3 236 #define DOARGS_3 DOARGS_0 237 #undef DOARGS_4 238 #define DOARGS_4 DOARGS_0 239 #undef DOARGS_5 240 #define DOARGS_5 \ 241 .fnstart; \ 242 push {r4, r7}; \ 243 cfi_adjust_cfa_offset (8); \ 244 cfi_rel_offset (r4, 0); \ 245 cfi_rel_offset (r7, 4); \ 246 .save { r4, r7 }; \ 247 ldr r4, [sp, #8] 248 #undef DOARGS_6 249 #define DOARGS_6 \ 250 .fnstart; \ 251 mov ip, sp; \ 252 push {r4, r5, r7}; \ 253 cfi_adjust_cfa_offset (12); \ 254 cfi_rel_offset (r4, 0); \ 255 cfi_rel_offset (r5, 4); \ 256 cfi_rel_offset (r7, 8); \ 257 .save { r4, r5, r7 }; \ 258 ldmia ip, {r4, r5} 259 #undef DOARGS_7 260 #define DOARGS_7 \ 261 .fnstart; \ 262 mov ip, sp; \ 263 push {r4, r5, r6, r7}; \ 264 cfi_adjust_cfa_offset (16); \ 265 cfi_rel_offset (r4, 0); \ 266 cfi_rel_offset (r5, 4); \ 267 cfi_rel_offset (r6, 8); \ 268 cfi_rel_offset (r7, 12); \ 269 .save { r4, r5, r6, r7 }; \ 270 ldmia ip, {r4, r5, r6} 271 272 #undef UNDOARGS_0 273 #define UNDOARGS_0 \ 274 pop {r7}; \ 275 cfi_adjust_cfa_offset (-4); \ 276 cfi_restore (r7); \ 277 .fnend 278 #undef UNDOARGS_1 279 #define UNDOARGS_1 UNDOARGS_0 280 #undef UNDOARGS_2 281 #define UNDOARGS_2 UNDOARGS_0 282 #undef UNDOARGS_3 283 #define UNDOARGS_3 UNDOARGS_0 284 #undef UNDOARGS_4 285 #define UNDOARGS_4 UNDOARGS_0 286 #undef UNDOARGS_5 287 #define UNDOARGS_5 \ 288 pop {r4, r7}; \ 289 cfi_adjust_cfa_offset (-8); \ 290 cfi_restore (r4); \ 291 cfi_restore (r7); \ 292 .fnend 293 #undef UNDOARGS_6 294 #define UNDOARGS_6 \ 295 pop {r4, r5, r7}; \ 296 cfi_adjust_cfa_offset (-12); \ 297 cfi_restore (r4); \ 298 cfi_restore (r5); \ 299 cfi_restore (r7); \ 300 .fnend 301 #undef UNDOARGS_7 302 #define UNDOARGS_7 \ 303 pop {r4, r5, r6, r7}; \ 304 cfi_adjust_cfa_offset (-16); \ 305 cfi_restore (r4); \ 306 cfi_restore (r5); \ 307 cfi_restore (r6); \ 308 cfi_restore (r7); \ 309 .fnend 310 311 #else /* not __ASSEMBLER__ */ 312 313 #if defined(__thumb__) 314 /* We can not expose the use of r7 to the compiler. GCC (as 315 of 4.5) uses r7 as the hard frame pointer for Thumb - although 316 for Thumb-2 it isn't obviously a better choice than r11. 317 And GCC does not support asms that conflict with the frame 318 pointer. 319 320 This would be easier if syscall numbers never exceeded 255, 321 but they do. For the moment the LOAD_ARGS_7 is sacrificed. 322 We can't use push/pop inside the asm because that breaks 323 unwinding (i.e. thread cancellation) for this frame. We can't 324 locally save and restore r7, because we do not know if this 325 function uses r7 or if it is our caller's r7; if it is our caller's, 326 then unwinding will fail higher up the stack. So we move the 327 syscall out of line and provide its own unwind information. */ 328 # undef INTERNAL_SYSCALL_RAW 329 # define INTERNAL_SYSCALL_RAW(name, nr, args...) \ 330 ({ \ 331 register int _a1 asm ("a1"); \ 332 int _nametmp = name; \ 333 LOAD_ARGS_##nr (args) \ 334 register int _name asm ("ip") = _nametmp; \ 335 asm volatile ("bl __libc_do_syscall" \ 336 : "=r" (_a1) \ 337 : "r" (_name) ASM_ARGS_##nr \ 338 : "memory", "lr"); \ 339 _a1; }) 340 #else /* ARM */ 341 # undef INTERNAL_SYSCALL_RAW 342 # define INTERNAL_SYSCALL_RAW(name, nr, args...) \ 343 ({ \ 344 register int _a1 asm ("r0"), _nr asm ("r7"); \ 345 LOAD_ARGS_##nr (args) \ 346 _nr = name; \ 347 asm volatile ("swi 0x0 @ syscall " #name \ 348 : "=r" (_a1) \ 349 : "r" (_nr) ASM_ARGS_##nr \ 350 : "memory"); \ 351 _a1; }) 352 #endif 353 354 #undef INTERNAL_SYSCALL 355 #define INTERNAL_SYSCALL(name, nr, args...) \ 356 INTERNAL_SYSCALL_RAW(SYS_ify(name), nr, args) 357 358 #define VDSO_NAME "LINUX_2.6" 359 #define VDSO_HASH 61765110 360 361 /* List of system calls which are supported as vsyscalls. */ 362 #define HAVE_CLOCK_GETTIME_VSYSCALL "__vdso_clock_gettime" 363 #define HAVE_CLOCK_GETTIME64_VSYSCALL "__vdso_clock_gettime64" 364 #define HAVE_GETTIMEOFDAY_VSYSCALL "__vdso_gettimeofday" 365 366 #define LOAD_ARGS_0() 367 #define ASM_ARGS_0 368 #define LOAD_ARGS_1(a1) \ 369 int _a1tmp = (int) (a1); \ 370 LOAD_ARGS_0 () \ 371 _a1 = _a1tmp; 372 #define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1) 373 #define LOAD_ARGS_2(a1, a2) \ 374 int _a2tmp = (int) (a2); \ 375 LOAD_ARGS_1 (a1) \ 376 register int _a2 asm ("a2") = _a2tmp; 377 #define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2) 378 #define LOAD_ARGS_3(a1, a2, a3) \ 379 int _a3tmp = (int) (a3); \ 380 LOAD_ARGS_2 (a1, a2) \ 381 register int _a3 asm ("a3") = _a3tmp; 382 #define ASM_ARGS_3 ASM_ARGS_2, "r" (_a3) 383 #define LOAD_ARGS_4(a1, a2, a3, a4) \ 384 int _a4tmp = (int) (a4); \ 385 LOAD_ARGS_3 (a1, a2, a3) \ 386 register int _a4 asm ("a4") = _a4tmp; 387 #define ASM_ARGS_4 ASM_ARGS_3, "r" (_a4) 388 #define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ 389 int _v1tmp = (int) (a5); \ 390 LOAD_ARGS_4 (a1, a2, a3, a4) \ 391 register int _v1 asm ("v1") = _v1tmp; 392 #define ASM_ARGS_5 ASM_ARGS_4, "r" (_v1) 393 #define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ 394 int _v2tmp = (int) (a6); \ 395 LOAD_ARGS_5 (a1, a2, a3, a4, a5) \ 396 register int _v2 asm ("v2") = _v2tmp; 397 #define ASM_ARGS_6 ASM_ARGS_5, "r" (_v2) 398 #ifndef __thumb__ 399 # define LOAD_ARGS_7(a1, a2, a3, a4, a5, a6, a7) \ 400 int _v3tmp = (int) (a7); \ 401 LOAD_ARGS_6 (a1, a2, a3, a4, a5, a6) \ 402 register int _v3 asm ("v3") = _v3tmp; 403 # define ASM_ARGS_7 ASM_ARGS_6, "r" (_v3) 404 #endif 405 406 /* For EABI, non-constant syscalls are actually pretty easy... */ 407 #undef INTERNAL_SYSCALL_NCS 408 #define INTERNAL_SYSCALL_NCS(number, nr, args...) \ 409 INTERNAL_SYSCALL_RAW (number, nr, args) 410 411 #endif /* __ASSEMBLER__ */ 412 413 #endif /* linux/arm/sysdep.h */ 414