(root)/
glibc-2.38/
sysdeps/
unix/
sysv/
linux/
s390/
s390-32/
sysdep.h
       1  /* Copyright (C) 2000-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_S390_SYSDEP_H
      19  #define _LINUX_S390_SYSDEP_H
      20  
      21  #include <sysdeps/s390/s390-32/sysdep.h>
      22  #include <sysdeps/unix/sysdep.h>
      23  #include <sysdeps/unix/sysv/linux/s390/sysdep.h>
      24  #include <sysdeps/unix/sysv/linux/sysdep.h>
      25  #include <dl-sysdep.h>	/* For RTLD_PRIVATE_ERRNO.  */
      26  #include <tls.h>
      27  
      28  /* For Linux we can use the system call table in the header file
      29  	/usr/include/asm/unistd.h
      30     of the kernel.  But these symbols do not follow the SYS_* syntax
      31     so we have to redefine the `SYS_ify' macro here.  */
      32  /* in newer 2.1 kernels __NR_syscall is missing so we define it here */
      33  #define __NR_syscall 0
      34  
      35  #ifdef __ASSEMBLER__
      36  
      37  /* Linux uses a negative return value to indicate syscall errors, unlike
      38     most Unices, which use the condition codes' carry flag.
      39  
      40     Since version 2.1 the return value of a system call might be negative
      41     even if the call succeeded.  E.g., the `lseek' system call might return
      42     a large offset.  Therefore we must not anymore test for < 0, but test
      43     for a real error by making sure the value in gpr2 is a real error
      44     number.  Linus said he will make sure that no syscall returns a value
      45     in -1 .. -4095 as a valid result so we can safely test with -4095.  */
      46  
      47  #undef PSEUDO
      48  #define	PSEUDO(name, syscall_name, args)				      \
      49    .text;                                                                      \
      50    ENTRY (name)								      \
      51      DO_CALL (syscall_name, args);                                             \
      52      lhi  %r4,-4095 ;                                                          \
      53      clr  %r2,%r4 ;							      \
      54      jnl  SYSCALL_ERROR_LABEL
      55  
      56  #undef PSEUDO_END
      57  #define PSEUDO_END(name)						      \
      58    SYSCALL_ERROR_HANDLER;						      \
      59    END (name)
      60  
      61  #undef PSEUDO_NOERRNO
      62  #define	PSEUDO_NOERRNO(name, syscall_name, args)			      \
      63    .text;                                                                      \
      64    ENTRY (name)								      \
      65      DO_CALL (syscall_name, args)
      66  
      67  #undef PSEUDO_END_NOERRNO
      68  #define PSEUDO_END_NOERRNO(name)					      \
      69    END (name)
      70  
      71  #undef PSEUDO_ERRVAL
      72  #define	PSEUDO_ERRVAL(name, syscall_name, args)				      \
      73    .text;                                                                      \
      74    ENTRY (name)								      \
      75      DO_CALL (syscall_name, args);					      \
      76      lcr %r2,%r2
      77  
      78  #undef PSEUDO_END_ERRVAL
      79  #define PSEUDO_END_ERRVAL(name)						      \
      80    END (name)
      81  
      82  #undef SYSCALL_ERROR_LABEL
      83  #ifndef PIC
      84  # undef SYSCALL_ERROR_LABEL
      85  # define SYSCALL_ERROR_LABEL 0f
      86  # define SYSCALL_ERROR_HANDLER \
      87  0:  basr  %r1,0;							      \
      88  1:  l     %r1,2f-1b(%r1);						      \
      89      br    %r1;								      \
      90  2:  .long syscall_error
      91  #else
      92  # if RTLD_PRIVATE_ERRNO
      93  #  undef SYSCALL_ERROR_LABEL
      94  #  define SYSCALL_ERROR_LABEL 0f
      95  #  define SYSCALL_ERROR_HANDLER \
      96  0:  basr  %r1,0;							      \
      97  1:  al    %r1,2f-1b(%r1);						      \
      98      lcr   %r2,%r2;							      \
      99      st    %r2,0(%r1);							      \
     100      lhi   %r2,-1;							      \
     101      br    %r14;								      \
     102  2:  .long rtld_errno-1b
     103  # elif defined _LIBC_REENTRANT
     104  #  if IS_IN (libc)
     105  #   define SYSCALL_ERROR_ERRNO __libc_errno
     106  #  else
     107  #   define SYSCALL_ERROR_ERRNO errno
     108  #  endif
     109  #  undef SYSCALL_ERROR_LABEL
     110  #  define SYSCALL_ERROR_LABEL 0f
     111  #  define SYSCALL_ERROR_HANDLER \
     112  0:  lcr   %r0,%r2;							      \
     113      basr  %r1,0;							      \
     114  1:  al    %r1,2f-1b(%r1);						      \
     115      l     %r1,SYSCALL_ERROR_ERRNO@gotntpoff(%r1);			      \
     116      ear   %r2,%a0;							      \
     117      st    %r0,0(%r1,%r2);						      \
     118      lhi   %r2,-1;							      \
     119      br    %r14;								      \
     120  2:  .long _GLOBAL_OFFSET_TABLE_-1b
     121  # else
     122  #  undef SYSCALL_ERROR_LABEL
     123  #  define SYSCALL_ERROR_LABEL 0f
     124  #  define SYSCALL_ERROR_HANDLER \
     125  0:  basr  %r1,0;							      \
     126  1:  al    %r1,2f-1b(%r1);						      \
     127      l     %r1,errno@GOT(%r1);						      \
     128      lcr   %r2,%r2;							      \
     129      st    %r2,0(%r1);							      \
     130      lhi   %r2,-1;							      \
     131      br    %r14;								      \
     132  2:  .long _GLOBAL_OFFSET_TABLE_-1b
     133  # endif /* _LIBC_REENTRANT */
     134  #endif /* PIC */
     135  
     136  /* Linux takes system call arguments in registers:
     137  
     138  	syscall number	1	     call-clobbered
     139  	arg 1		2	     call-clobbered
     140  	arg 2		3	     call-clobbered
     141  	arg 3		4	     call-clobbered
     142  	arg 4		5	     call-clobbered
     143  	arg 5		6	     call-saved
     144  	arg 6		7	     call-saved
     145  
     146     (Of course a function with say 3 arguments does not have entries for
     147     arguments 4 and 5.)
     148     For system calls with 6 parameters a stack operation is required
     149     to load the 6th parameter to register 7. Call saved register 7 is
     150     moved to register 0 and back to avoid an additional stack frame.
     151   */
     152  
     153  #define DO_CALL(syscall, args)						      \
     154    .if args > 5;								      \
     155      lr %r0,%r7;								      \
     156      l %r7,96(%r15);							      \
     157    .endif;								      \
     158      lhi %r1,SYS_ify (syscall);						      \
     159      svc 0;								      \
     160    .if args > 5;								      \
     161      lr %r7,%r0;								      \
     162    .endif
     163  
     164  #define ret                                                                   \
     165      br      14
     166  
     167  #define ret_NOERRNO							      \
     168      br      14
     169  
     170  #define ret_ERRVAL							      \
     171      br      14
     172  
     173  #else
     174  
     175  # undef HAVE_INTERNAL_BRK_ADDR_SYMBOL
     176  # define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1
     177  
     178  #endif /* __ASSEMBLER__ */
     179  
     180  #endif /* _LINUX_S390_SYSDEP_H */