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