(root)/
glibc-2.38/
sysdeps/
unix/
sysv/
linux/
aarch64/
sysdep.h
       1  /* Copyright (C) 2005-2023 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  # ifdef __LP64__
     156  #  define VDSO_NAME  "LINUX_2.6.39"
     157  #  define VDSO_HASH  123718537
     158  # else
     159  #  define VDSO_NAME  "LINUX_4.9"
     160  #  define VDSO_HASH  61765625
     161  # endif
     162  
     163  /* List of system calls which are supported as vsyscalls.  */
     164  # define HAVE_CLOCK_GETRES64_VSYSCALL	"__kernel_clock_getres"
     165  # define HAVE_CLOCK_GETTIME64_VSYSCALL	"__kernel_clock_gettime"
     166  # define HAVE_GETTIMEOFDAY_VSYSCALL	"__kernel_gettimeofday"
     167  
     168  # define HAVE_CLONE3_WRAPPER		1
     169  
     170  # undef INTERNAL_SYSCALL_RAW
     171  # define INTERNAL_SYSCALL_RAW(name, nr, args...)		\
     172    ({ long _sys_result;						\
     173       {								\
     174         LOAD_ARGS_##nr (args)					\
     175         register long _x8 asm ("x8") = (name);			\
     176         asm volatile ("svc	0	// syscall " # name     \
     177  		     : "=r" (_x0) : "r"(_x8) ASM_ARGS_##nr : "memory");	\
     178         _sys_result = _x0;					\
     179       }								\
     180       _sys_result; })
     181  
     182  # undef INTERNAL_SYSCALL
     183  # define INTERNAL_SYSCALL(name, nr, args...)			\
     184  	INTERNAL_SYSCALL_RAW(SYS_ify(name), nr, args)
     185  
     186  # undef INTERNAL_SYSCALL_AARCH64
     187  # define INTERNAL_SYSCALL_AARCH64(name, nr, args...)		\
     188  	INTERNAL_SYSCALL_RAW(__ARM_NR_##name, nr, args)
     189  
     190  # define LOAD_ARGS_0()				\
     191    register long _x0 asm ("x0");
     192  # define LOAD_ARGS_1(x0)			\
     193    long _x0tmp = (long) (x0);			\
     194    LOAD_ARGS_0 ()				\
     195    _x0 = _x0tmp;
     196  # define LOAD_ARGS_2(x0, x1)			\
     197    long _x1tmp = (long) (x1);			\
     198    LOAD_ARGS_1 (x0)				\
     199    register long _x1 asm ("x1") = _x1tmp;
     200  # define LOAD_ARGS_3(x0, x1, x2)		\
     201    long _x2tmp = (long) (x2);			\
     202    LOAD_ARGS_2 (x0, x1)				\
     203    register long _x2 asm ("x2") = _x2tmp;
     204  # define LOAD_ARGS_4(x0, x1, x2, x3)		\
     205    long _x3tmp = (long) (x3);			\
     206    LOAD_ARGS_3 (x0, x1, x2)			\
     207    register long _x3 asm ("x3") = _x3tmp;
     208  # define LOAD_ARGS_5(x0, x1, x2, x3, x4)	\
     209    long _x4tmp = (long) (x4);			\
     210    LOAD_ARGS_4 (x0, x1, x2, x3)			\
     211    register long _x4 asm ("x4") = _x4tmp;
     212  # define LOAD_ARGS_6(x0, x1, x2, x3, x4, x5)	\
     213    long _x5tmp = (long) (x5);			\
     214    LOAD_ARGS_5 (x0, x1, x2, x3, x4)		\
     215    register long _x5 asm ("x5") = _x5tmp;
     216  # define LOAD_ARGS_7(x0, x1, x2, x3, x4, x5, x6)\
     217    long _x6tmp = (long) (x6);			\
     218    LOAD_ARGS_6 (x0, x1, x2, x3, x4, x5)		\
     219    register long _x6 asm ("x6") = _x6tmp;
     220  
     221  # define ASM_ARGS_0
     222  # define ASM_ARGS_1	, "r" (_x0)
     223  # define ASM_ARGS_2	ASM_ARGS_1, "r" (_x1)
     224  # define ASM_ARGS_3	ASM_ARGS_2, "r" (_x2)
     225  # define ASM_ARGS_4	ASM_ARGS_3, "r" (_x3)
     226  # define ASM_ARGS_5	ASM_ARGS_4, "r" (_x4)
     227  # define ASM_ARGS_6	ASM_ARGS_5, "r" (_x5)
     228  # define ASM_ARGS_7	ASM_ARGS_6, "r" (_x6)
     229  
     230  # undef INTERNAL_SYSCALL_NCS
     231  # define INTERNAL_SYSCALL_NCS(number, nr, args...)	\
     232  	INTERNAL_SYSCALL_RAW (number, nr, args)
     233  
     234  #undef HAVE_INTERNAL_BRK_ADDR_SYMBOL
     235  #define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1
     236  
     237  #endif	/* __ASSEMBLER__ */
     238  
     239  #endif /* linux/aarch64/sysdep.h */