1  /* Copyright (C) 2001-2023 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_X86_64_SYSDEP_H
      19  #define _LINUX_X86_64_SYSDEP_H 1
      20  
      21  /* There is some commonality.  */
      22  #include <sysdeps/unix/sysv/linux/sysdep.h>
      23  #include <sysdeps/unix/x86_64/sysdep.h>
      24  #include <tls.h>
      25  
      26  /* Defines RTLD_PRIVATE_ERRNO.  */
      27  #include <dl-sysdep.h>
      28  
      29  /* For Linux we can use the system call table in the header file
      30  	/usr/include/asm/unistd.h
      31     of the kernel.  But these symbols do not follow the SYS_* syntax
      32     so we have to redefine the `SYS_ify' macro here.  */
      33  #undef SYS_ify
      34  #define SYS_ify(syscall_name)	__NR_##syscall_name
      35  
      36  #ifdef __ASSEMBLER__
      37  
      38  /* Linux uses a negative return value to indicate syscall errors,
      39     unlike most Unices, which use the condition codes' carry flag.
      40  
      41     Since version 2.1 the return value of a system call might be
      42     negative even if the call succeeded.	 E.g., the `lseek' system call
      43     might return a large offset.	 Therefore we must not anymore test
      44     for < 0, but test for a real error by making sure the value in %eax
      45     is a real error number.  Linus said he will make sure the no syscall
      46     returns a value in -1 .. -4095 as a valid result so we can safely
      47     test with -4095.  */
      48  
      49  /* We don't want the label for the error handle to be global when we define
      50     it here.  */
      51  # undef SYSCALL_ERROR_LABEL
      52  # ifdef PIC
      53  #  undef SYSCALL_ERROR_LABEL
      54  #  define SYSCALL_ERROR_LABEL 0f
      55  # else
      56  #  undef SYSCALL_ERROR_LABEL
      57  #  define SYSCALL_ERROR_LABEL syscall_error
      58  # endif
      59  
      60  /* PSEUDO and T_PSEUDO macros have 2 extra arguments for unsigned long
      61     int arguments.  */
      62  # define PSEUDOS_HAVE_ULONG_INDICES 1
      63  
      64  # ifndef SYSCALL_ULONG_ARG_1
      65  #  define SYSCALL_ULONG_ARG_1 0
      66  #  define SYSCALL_ULONG_ARG_2 0
      67  # endif
      68  
      69  # undef	PSEUDO
      70  # if SYSCALL_ULONG_ARG_1
      71  #  define PSEUDO(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
      72    .text;							      \
      73    ENTRY (name)							      \
      74      DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2);	      \
      75      cmpq $-4095, %rax;						      \
      76      jae SYSCALL_ERROR_LABEL
      77  # else
      78  #  define PSEUDO(name, syscall_name, args) \
      79    .text;							      \
      80    ENTRY (name)							      \
      81      DO_CALL (syscall_name, args, 0, 0);				      \
      82      cmpq $-4095, %rax;						      \
      83      jae SYSCALL_ERROR_LABEL
      84  # endif
      85  
      86  # undef	PSEUDO_END
      87  # define PSEUDO_END(name)						      \
      88    SYSCALL_ERROR_HANDLER							      \
      89    END (name)
      90  
      91  # undef	PSEUDO_NOERRNO
      92  # if SYSCALL_ULONG_ARG_1
      93  #  define PSEUDO_NOERRNO(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
      94    .text;							      \
      95    ENTRY (name)							      \
      96      DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2)
      97  # else
      98  #  define PSEUDO_NOERRNO(name, syscall_name, args) \
      99    .text;							      \
     100    ENTRY (name)							      \
     101      DO_CALL (syscall_name, args, 0, 0)
     102  # endif
     103  
     104  # undef	PSEUDO_END_NOERRNO
     105  # define PSEUDO_END_NOERRNO(name) \
     106    END (name)
     107  
     108  # define ret_NOERRNO ret
     109  
     110  # undef	PSEUDO_ERRVAL
     111  # if SYSCALL_ULONG_ARG_1
     112  #  define PSEUDO_ERRVAL(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
     113    .text;							\
     114    ENTRY (name)							\
     115      DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2);	\
     116      negq %rax
     117  # else
     118  #  define PSEUDO_ERRVAL(name, syscall_name, args) \
     119    .text;							\
     120    ENTRY (name)							\
     121      DO_CALL (syscall_name, args, 0, 0);				\
     122      negq %rax
     123  # endif
     124  
     125  # undef	PSEUDO_END_ERRVAL
     126  # define PSEUDO_END_ERRVAL(name) \
     127    END (name)
     128  
     129  # define ret_ERRVAL ret
     130  
     131  # if defined PIC && RTLD_PRIVATE_ERRNO
     132  #  define SYSCALL_SET_ERRNO			\
     133    lea rtld_errno(%rip), %RCX_LP;		\
     134    neg %eax;					\
     135    movl %eax, (%rcx)
     136  # else
     137  #  if IS_IN (libc)
     138  #   define SYSCALL_ERROR_ERRNO __libc_errno
     139  #  else
     140  #   define SYSCALL_ERROR_ERRNO errno
     141  #  endif
     142  #  define SYSCALL_SET_ERRNO			\
     143    movq SYSCALL_ERROR_ERRNO@GOTTPOFF(%rip), %rcx;\
     144    neg %eax;					\
     145    movl %eax, %fs:(%rcx);
     146  # endif
     147  
     148  # ifndef PIC
     149  #  define SYSCALL_ERROR_HANDLER	/* Nothing here; code in sysdep.S is used.  */
     150  # else
     151  #  define SYSCALL_ERROR_HANDLER			\
     152  0:						\
     153    SYSCALL_SET_ERRNO;				\
     154    or $-1, %RAX_LP;				\
     155    ret;
     156  # endif	/* PIC */
     157  
     158  /* The Linux/x86-64 kernel expects the system call parameters in
     159     registers according to the following table:
     160  
     161      syscall number	rax
     162      arg 1		rdi
     163      arg 2		rsi
     164      arg 3		rdx
     165      arg 4		r10
     166      arg 5		r8
     167      arg 6		r9
     168  
     169      The Linux kernel uses and destroys internally these registers:
     170      return address from
     171      syscall		rcx
     172      eflags from syscall	r11
     173  
     174      Normal function call, including calls to the system call stub
     175      functions in the libc, get the first six parameters passed in
     176      registers and the seventh parameter and later on the stack.  The
     177      register use is as follows:
     178  
     179       system call number	in the DO_CALL macro
     180       arg 1		rdi
     181       arg 2		rsi
     182       arg 3		rdx
     183       arg 4		rcx
     184       arg 5		r8
     185       arg 6		r9
     186  
     187      We have to take care that the stack is aligned to 16 bytes.  When
     188      called the stack is not aligned since the return address has just
     189      been pushed.
     190  
     191  
     192      Syscalls of more than 6 arguments are not supported.  */
     193  
     194  # undef	DO_CALL
     195  # define DO_CALL(syscall_name, args, ulong_arg_1, ulong_arg_2) \
     196      DOARGS_##args				\
     197      ZERO_EXTEND_##ulong_arg_1			\
     198      ZERO_EXTEND_##ulong_arg_2			\
     199      movl $SYS_ify (syscall_name), %eax;		\
     200      syscall;
     201  
     202  # define DOARGS_0 /* nothing */
     203  # define DOARGS_1 /* nothing */
     204  # define DOARGS_2 /* nothing */
     205  # define DOARGS_3 /* nothing */
     206  # define DOARGS_4 movq %rcx, %r10;
     207  # define DOARGS_5 DOARGS_4
     208  # define DOARGS_6 DOARGS_5
     209  
     210  # define ZERO_EXTEND_0 /* nothing */
     211  # define ZERO_EXTEND_1 /* nothing */
     212  # define ZERO_EXTEND_2 /* nothing */
     213  # define ZERO_EXTEND_3 /* nothing */
     214  # define ZERO_EXTEND_4 /* nothing */
     215  # define ZERO_EXTEND_5 /* nothing */
     216  # define ZERO_EXTEND_6 /* nothing */
     217  
     218  #else	/* !__ASSEMBLER__ */
     219  
     220  /* Registers clobbered by syscall.  */
     221  # define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"
     222  
     223  /* NB: This also works when X is an array.  For an array X,  type of
     224     (X) - (X) is ptrdiff_t, which is signed, since size of ptrdiff_t
     225     == size of pointer, cast is a NOP.   */
     226  #define TYPEFY1(X) __typeof__ ((X) - (X))
     227  /* Explicit cast the argument.  */
     228  #define ARGIFY(X) ((TYPEFY1 (X)) (X))
     229  /* Create a variable 'name' based on type of variable 'X' to avoid
     230     explicit types.  */
     231  #define TYPEFY(X, name) __typeof__ (ARGIFY (X)) name
     232  
     233  #undef INTERNAL_SYSCALL
     234  #define INTERNAL_SYSCALL(name, nr, args...)				\
     235  	internal_syscall##nr (SYS_ify (name), args)
     236  
     237  #undef INTERNAL_SYSCALL_NCS
     238  #define INTERNAL_SYSCALL_NCS(number, nr, args...)			\
     239  	internal_syscall##nr (number, args)
     240  
     241  #undef internal_syscall0
     242  #define internal_syscall0(number, dummy...)				\
     243  ({									\
     244      unsigned long int resultvar;					\
     245      asm volatile (							\
     246      "syscall\n\t"							\
     247      : "=a" (resultvar)							\
     248      : "0" (number)							\
     249      : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
     250      (long int) resultvar;						\
     251  })
     252  
     253  #undef internal_syscall1
     254  #define internal_syscall1(number, arg1)					\
     255  ({									\
     256      unsigned long int resultvar;					\
     257      TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
     258      register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
     259      asm volatile (							\
     260      "syscall\n\t"							\
     261      : "=a" (resultvar)							\
     262      : "0" (number), "r" (_a1)						\
     263      : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
     264      (long int) resultvar;						\
     265  })
     266  
     267  #undef internal_syscall2
     268  #define internal_syscall2(number, arg1, arg2)				\
     269  ({									\
     270      unsigned long int resultvar;					\
     271      TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\
     272      TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
     273      register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\
     274      register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
     275      asm volatile (							\
     276      "syscall\n\t"							\
     277      : "=a" (resultvar)							\
     278      : "0" (number), "r" (_a1), "r" (_a2)				\
     279      : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
     280      (long int) resultvar;						\
     281  })
     282  
     283  #undef internal_syscall3
     284  #define internal_syscall3(number, arg1, arg2, arg3)			\
     285  ({									\
     286      unsigned long int resultvar;					\
     287      TYPEFY (arg3, __arg3) = ARGIFY (arg3);			 	\
     288      TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\
     289      TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
     290      register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;			\
     291      register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\
     292      register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
     293      asm volatile (							\
     294      "syscall\n\t"							\
     295      : "=a" (resultvar)							\
     296      : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3)			\
     297      : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
     298      (long int) resultvar;						\
     299  })
     300  
     301  #undef internal_syscall4
     302  #define internal_syscall4(number, arg1, arg2, arg3, arg4)		\
     303  ({									\
     304      unsigned long int resultvar;					\
     305      TYPEFY (arg4, __arg4) = ARGIFY (arg4);			 	\
     306      TYPEFY (arg3, __arg3) = ARGIFY (arg3);			 	\
     307      TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\
     308      TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
     309      register TYPEFY (arg4, _a4) asm ("r10") = __arg4;			\
     310      register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;			\
     311      register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\
     312      register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
     313      asm volatile (							\
     314      "syscall\n\t"							\
     315      : "=a" (resultvar)							\
     316      : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4)		\
     317      : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
     318      (long int) resultvar;						\
     319  })
     320  
     321  #undef internal_syscall5
     322  #define internal_syscall5(number, arg1, arg2, arg3, arg4, arg5)	\
     323  ({									\
     324      unsigned long int resultvar;					\
     325      TYPEFY (arg5, __arg5) = ARGIFY (arg5);			 	\
     326      TYPEFY (arg4, __arg4) = ARGIFY (arg4);			 	\
     327      TYPEFY (arg3, __arg3) = ARGIFY (arg3);			 	\
     328      TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\
     329      TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
     330      register TYPEFY (arg5, _a5) asm ("r8") = __arg5;			\
     331      register TYPEFY (arg4, _a4) asm ("r10") = __arg4;			\
     332      register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;			\
     333      register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\
     334      register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
     335      asm volatile (							\
     336      "syscall\n\t"							\
     337      : "=a" (resultvar)							\
     338      : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4),		\
     339        "r" (_a5)								\
     340      : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
     341      (long int) resultvar;						\
     342  })
     343  
     344  #undef internal_syscall6
     345  #define internal_syscall6(number, arg1, arg2, arg3, arg4, arg5, arg6) \
     346  ({									\
     347      unsigned long int resultvar;					\
     348      TYPEFY (arg6, __arg6) = ARGIFY (arg6);			 	\
     349      TYPEFY (arg5, __arg5) = ARGIFY (arg5);			 	\
     350      TYPEFY (arg4, __arg4) = ARGIFY (arg4);			 	\
     351      TYPEFY (arg3, __arg3) = ARGIFY (arg3);			 	\
     352      TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\
     353      TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
     354      register TYPEFY (arg6, _a6) asm ("r9") = __arg6;			\
     355      register TYPEFY (arg5, _a5) asm ("r8") = __arg5;			\
     356      register TYPEFY (arg4, _a4) asm ("r10") = __arg4;			\
     357      register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;			\
     358      register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\
     359      register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
     360      asm volatile (							\
     361      "syscall\n\t"							\
     362      : "=a" (resultvar)							\
     363      : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4),		\
     364        "r" (_a5), "r" (_a6)						\
     365      : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
     366      (long int) resultvar;						\
     367  })
     368  
     369  
     370  # define VDSO_NAME  "LINUX_2.6"
     371  # define VDSO_HASH  61765110
     372  
     373  /* List of system calls which are supported as vsyscalls.  */
     374  # define HAVE_CLOCK_GETTIME64_VSYSCALL  "__vdso_clock_gettime"
     375  # define HAVE_GETTIMEOFDAY_VSYSCALL     "__vdso_gettimeofday"
     376  # define HAVE_TIME_VSYSCALL             "__vdso_time"
     377  # define HAVE_GETCPU_VSYSCALL		"__vdso_getcpu"
     378  # define HAVE_CLOCK_GETRES64_VSYSCALL   "__vdso_clock_getres"
     379  
     380  # define HAVE_CLONE3_WRAPPER			1
     381  
     382  #endif	/* __ASSEMBLER__ */
     383  
     384  /* How to pass the off{64}_t argument on p{readv,writev}{64}.  */
     385  #undef LO_HI_LONG
     386  #define LO_HI_LONG(val) (val), 0
     387  
     388  /* Each shadow stack slot takes 8 bytes.  Assuming that each stack
     389     frame takes 256 bytes, this is used to compute shadow stack size
     390     from stack size.  */
     391  #define STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT 5
     392  
     393  #endif /* linux/x86_64/sysdep.h */