Warning: That file was not part of the compilation database. It may have many parsing errors.
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 | #define SINGLE_THREAD_BY_GLOBAL 1 |
412 | |
413 | #endif /* __ASSEMBLER__ */ |
414 | |
415 | #endif /* linux/arm/sysdep.h */ |
416 |
Warning: That file was not part of the compilation database. It may have many parsing errors.