master
  1/* Copyright (C) 1992-2025 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#define HAVE_CLONE3_WRAPPER		1
366
367#define LOAD_ARGS_0()
368#define ASM_ARGS_0
369#define LOAD_ARGS_1(a1)				\
370  int _a1tmp = (int) (a1);			\
371  LOAD_ARGS_0 ()				\
372  _a1 = _a1tmp;
373#define ASM_ARGS_1	ASM_ARGS_0, "r" (_a1)
374#define LOAD_ARGS_2(a1, a2)			\
375  int _a2tmp = (int) (a2);			\
376  LOAD_ARGS_1 (a1)				\
377  register int _a2 asm ("a2") = _a2tmp;
378#define ASM_ARGS_2	ASM_ARGS_1, "r" (_a2)
379#define LOAD_ARGS_3(a1, a2, a3)			\
380  int _a3tmp = (int) (a3);			\
381  LOAD_ARGS_2 (a1, a2)				\
382  register int _a3 asm ("a3") = _a3tmp;
383#define ASM_ARGS_3	ASM_ARGS_2, "r" (_a3)
384#define LOAD_ARGS_4(a1, a2, a3, a4)		\
385  int _a4tmp = (int) (a4);			\
386  LOAD_ARGS_3 (a1, a2, a3)			\
387  register int _a4 asm ("a4") = _a4tmp;
388#define ASM_ARGS_4	ASM_ARGS_3, "r" (_a4)
389#define LOAD_ARGS_5(a1, a2, a3, a4, a5)		\
390  int _v1tmp = (int) (a5);			\
391  LOAD_ARGS_4 (a1, a2, a3, a4)			\
392  register int _v1 asm ("v1") = _v1tmp;
393#define ASM_ARGS_5	ASM_ARGS_4, "r" (_v1)
394#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6)	\
395  int _v2tmp = (int) (a6);			\
396  LOAD_ARGS_5 (a1, a2, a3, a4, a5)		\
397  register int _v2 asm ("v2") = _v2tmp;
398#define ASM_ARGS_6	ASM_ARGS_5, "r" (_v2)
399#ifndef __thumb__
400# define LOAD_ARGS_7(a1, a2, a3, a4, a5, a6, a7)	\
401  int _v3tmp = (int) (a7);				\
402  LOAD_ARGS_6 (a1, a2, a3, a4, a5, a6)			\
403  register int _v3 asm ("v3") = _v3tmp;
404# define ASM_ARGS_7	ASM_ARGS_6, "r" (_v3)
405#endif
406
407/* For EABI, non-constant syscalls are actually pretty easy...  */
408#undef INTERNAL_SYSCALL_NCS
409#define INTERNAL_SYSCALL_NCS(number, nr, args...)              \
410  INTERNAL_SYSCALL_RAW (number, nr, args)
411
412#endif	/* __ASSEMBLER__ */
413
414#endif /* linux/arm/sysdep.h */