github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/libcontainer/dmz/nolibc/arch-s390.h (about)

     1  /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
     2  /*
     3   * s390 specific definitions for NOLIBC
     4   */
     5  
     6  #ifndef _NOLIBC_ARCH_S390_H
     7  #define _NOLIBC_ARCH_S390_H
     8  #include <asm/signal.h>
     9  #include <asm/unistd.h>
    10  
    11  #include "compiler.h"
    12  #include "crt.h"
    13  
    14  /* Syscalls for s390:
    15   *   - registers are 64-bit
    16   *   - syscall number is passed in r1
    17   *   - arguments are in r2-r7
    18   *   - the system call is performed by calling the svc instruction
    19   *   - syscall return value is in r2
    20   *   - r1 and r2 are clobbered, others are preserved.
    21   *
    22   * Link s390 ABI: https://github.com/IBM/s390x-abi
    23   *
    24   */
    25  
    26  #define my_syscall0(num)						\
    27  ({									\
    28  	register long _num __asm__ ("1") = (num);			\
    29  	register long _rc __asm__ ("2");				\
    30  									\
    31  	__asm__ volatile (						\
    32  		"svc 0\n"						\
    33  		: "=d"(_rc)						\
    34  		: "d"(_num)						\
    35  		: "memory", "cc"					\
    36  		);							\
    37  	_rc;								\
    38  })
    39  
    40  #define my_syscall1(num, arg1)						\
    41  ({									\
    42  	register long _num __asm__ ("1") = (num);			\
    43  	register long _arg1 __asm__ ("2") = (long)(arg1);		\
    44  									\
    45  	__asm__ volatile (						\
    46  		"svc 0\n"						\
    47  		: "+d"(_arg1)						\
    48  		: "d"(_num)						\
    49  		: "memory", "cc"					\
    50  		);							\
    51  	_arg1;								\
    52  })
    53  
    54  #define my_syscall2(num, arg1, arg2)					\
    55  ({									\
    56  	register long _num __asm__ ("1") = (num);			\
    57  	register long _arg1 __asm__ ("2") = (long)(arg1);		\
    58  	register long _arg2 __asm__ ("3") = (long)(arg2);		\
    59  									\
    60  	__asm__ volatile (						\
    61  		"svc 0\n"						\
    62  		: "+d"(_arg1)						\
    63  		: "d"(_arg2), "d"(_num)					\
    64  		: "memory", "cc"					\
    65  		);							\
    66  	_arg1;								\
    67  })
    68  
    69  #define my_syscall3(num, arg1, arg2, arg3)				\
    70  ({									\
    71  	register long _num __asm__ ("1") = (num);			\
    72  	register long _arg1 __asm__ ("2") = (long)(arg1);		\
    73  	register long _arg2 __asm__ ("3") = (long)(arg2);		\
    74  	register long _arg3 __asm__ ("4") = (long)(arg3);		\
    75  									\
    76  	__asm__ volatile (						\
    77  		"svc 0\n"						\
    78  		: "+d"(_arg1)						\
    79  		: "d"(_arg2), "d"(_arg3), "d"(_num)			\
    80  		: "memory", "cc"					\
    81  		);							\
    82  	_arg1;								\
    83  })
    84  
    85  #define my_syscall4(num, arg1, arg2, arg3, arg4)			\
    86  ({									\
    87  	register long _num __asm__ ("1") = (num);			\
    88  	register long _arg1 __asm__ ("2") = (long)(arg1);		\
    89  	register long _arg2 __asm__ ("3") = (long)(arg2);		\
    90  	register long _arg3 __asm__ ("4") = (long)(arg3);		\
    91  	register long _arg4 __asm__ ("5") = (long)(arg4);		\
    92  									\
    93  	__asm__ volatile (						\
    94  		"svc 0\n"						\
    95  		: "+d"(_arg1)						\
    96  		: "d"(_arg2), "d"(_arg3), "d"(_arg4), "d"(_num)		\
    97  		: "memory", "cc"					\
    98  		);							\
    99  	_arg1;								\
   100  })
   101  
   102  #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)			\
   103  ({									\
   104  	register long _num __asm__ ("1") = (num);			\
   105  	register long _arg1 __asm__ ("2") = (long)(arg1);		\
   106  	register long _arg2 __asm__ ("3") = (long)(arg2);		\
   107  	register long _arg3 __asm__ ("4") = (long)(arg3);		\
   108  	register long _arg4 __asm__ ("5") = (long)(arg4);		\
   109  	register long _arg5 __asm__ ("6") = (long)(arg5);		\
   110  									\
   111  	__asm__ volatile (						\
   112  		"svc 0\n"						\
   113  		: "+d"(_arg1)						\
   114  		: "d"(_arg2), "d"(_arg3), "d"(_arg4), "d"(_arg5),	\
   115  		  "d"(_num)						\
   116  		: "memory", "cc"					\
   117  		);							\
   118  	_arg1;								\
   119  })
   120  
   121  #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)		\
   122  ({									\
   123  	register long _num __asm__ ("1") = (num);			\
   124  	register long _arg1 __asm__ ("2") = (long)(arg1);		\
   125  	register long _arg2 __asm__ ("3") = (long)(arg2);		\
   126  	register long _arg3 __asm__ ("4") = (long)(arg3);		\
   127  	register long _arg4 __asm__ ("5") = (long)(arg4);		\
   128  	register long _arg5 __asm__ ("6") = (long)(arg5);		\
   129  	register long _arg6 __asm__ ("7") = (long)(arg6);		\
   130  									\
   131  	__asm__ volatile (						\
   132  		"svc 0\n"						\
   133  		: "+d"(_arg1)						\
   134  		: "d"(_arg2), "d"(_arg3), "d"(_arg4), "d"(_arg5),	\
   135  		  "d"(_arg6), "d"(_num)					\
   136  		: "memory", "cc"					\
   137  		);							\
   138  	_arg1;								\
   139  })
   140  
   141  /* startup code */
   142  void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_stack_protector _start(void)
   143  {
   144  	__asm__ volatile (
   145  		"lgr	%r2, %r15\n"          /* save stack pointer to %r2, as arg1 of _start_c */
   146  		"aghi	%r15, -160\n"         /* allocate new stackframe                        */
   147  		"xc	0(8,%r15), 0(%r15)\n" /* clear backchain                                */
   148  		"brasl	%r14, _start_c\n"     /* transfer to c runtime                          */
   149  	);
   150  	__builtin_unreachable();
   151  }
   152  
   153  struct s390_mmap_arg_struct {
   154  	unsigned long addr;
   155  	unsigned long len;
   156  	unsigned long prot;
   157  	unsigned long flags;
   158  	unsigned long fd;
   159  	unsigned long offset;
   160  };
   161  
   162  static __attribute__((unused))
   163  void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd,
   164  	       off_t offset)
   165  {
   166  	struct s390_mmap_arg_struct args = {
   167  		.addr = (unsigned long)addr,
   168  		.len = (unsigned long)length,
   169  		.prot = prot,
   170  		.flags = flags,
   171  		.fd = fd,
   172  		.offset = (unsigned long)offset
   173  	};
   174  
   175  	return (void *)my_syscall1(__NR_mmap, &args);
   176  }
   177  #define sys_mmap sys_mmap
   178  
   179  static __attribute__((unused))
   180  pid_t sys_fork(void)
   181  {
   182  	return my_syscall5(__NR_clone, 0, SIGCHLD, 0, 0, 0);
   183  }
   184  #define sys_fork sys_fork
   185  
   186  #endif /* _NOLIBC_ARCH_S390_H */