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/unistd.h> 9 10 /* The struct returned by the stat() syscall, equivalent to stat64(). The 11 * syscall returns 116 bytes and stops in the middle of __unused. 12 */ 13 14 struct sys_stat_struct { 15 unsigned long st_dev; 16 unsigned long st_ino; 17 unsigned long st_nlink; 18 unsigned int st_mode; 19 unsigned int st_uid; 20 unsigned int st_gid; 21 unsigned int __pad1; 22 unsigned long st_rdev; 23 unsigned long st_size; 24 unsigned long st_atime; 25 unsigned long st_atime_nsec; 26 unsigned long st_mtime; 27 unsigned long st_mtime_nsec; 28 unsigned long st_ctime; 29 unsigned long st_ctime_nsec; 30 unsigned long st_blksize; 31 long st_blocks; 32 unsigned long __unused[3]; 33 }; 34 35 /* Syscalls for s390: 36 * - registers are 64-bit 37 * - syscall number is passed in r1 38 * - arguments are in r2-r7 39 * - the system call is performed by calling the svc instruction 40 * - syscall return value is in r2 41 * - r1 and r2 are clobbered, others are preserved. 42 * 43 * Link s390 ABI: https://github.com/IBM/s390x-abi 44 * 45 */ 46 47 #define my_syscall0(num) \ 48 ({ \ 49 register long _num __asm__ ("1") = (num); \ 50 register long _rc __asm__ ("2"); \ 51 \ 52 __asm__ volatile ( \ 53 "svc 0\n" \ 54 : "=d"(_rc) \ 55 : "d"(_num) \ 56 : "memory", "cc" \ 57 ); \ 58 _rc; \ 59 }) 60 61 #define my_syscall1(num, arg1) \ 62 ({ \ 63 register long _num __asm__ ("1") = (num); \ 64 register long _arg1 __asm__ ("2") = (long)(arg1); \ 65 \ 66 __asm__ volatile ( \ 67 "svc 0\n" \ 68 : "+d"(_arg1) \ 69 : "d"(_num) \ 70 : "memory", "cc" \ 71 ); \ 72 _arg1; \ 73 }) 74 75 #define my_syscall2(num, arg1, arg2) \ 76 ({ \ 77 register long _num __asm__ ("1") = (num); \ 78 register long _arg1 __asm__ ("2") = (long)(arg1); \ 79 register long _arg2 __asm__ ("3") = (long)(arg2); \ 80 \ 81 __asm__ volatile ( \ 82 "svc 0\n" \ 83 : "+d"(_arg1) \ 84 : "d"(_arg2), "d"(_num) \ 85 : "memory", "cc" \ 86 ); \ 87 _arg1; \ 88 }) 89 90 #define my_syscall3(num, arg1, arg2, arg3) \ 91 ({ \ 92 register long _num __asm__ ("1") = (num); \ 93 register long _arg1 __asm__ ("2") = (long)(arg1); \ 94 register long _arg2 __asm__ ("3") = (long)(arg2); \ 95 register long _arg3 __asm__ ("4") = (long)(arg3); \ 96 \ 97 __asm__ volatile ( \ 98 "svc 0\n" \ 99 : "+d"(_arg1) \ 100 : "d"(_arg2), "d"(_arg3), "d"(_num) \ 101 : "memory", "cc" \ 102 ); \ 103 _arg1; \ 104 }) 105 106 #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 107 ({ \ 108 register long _num __asm__ ("1") = (num); \ 109 register long _arg1 __asm__ ("2") = (long)(arg1); \ 110 register long _arg2 __asm__ ("3") = (long)(arg2); \ 111 register long _arg3 __asm__ ("4") = (long)(arg3); \ 112 register long _arg4 __asm__ ("5") = (long)(arg4); \ 113 \ 114 __asm__ volatile ( \ 115 "svc 0\n" \ 116 : "+d"(_arg1) \ 117 : "d"(_arg2), "d"(_arg3), "d"(_arg4), "d"(_num) \ 118 : "memory", "cc" \ 119 ); \ 120 _arg1; \ 121 }) 122 123 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 124 ({ \ 125 register long _num __asm__ ("1") = (num); \ 126 register long _arg1 __asm__ ("2") = (long)(arg1); \ 127 register long _arg2 __asm__ ("3") = (long)(arg2); \ 128 register long _arg3 __asm__ ("4") = (long)(arg3); \ 129 register long _arg4 __asm__ ("5") = (long)(arg4); \ 130 register long _arg5 __asm__ ("6") = (long)(arg5); \ 131 \ 132 __asm__ volatile ( \ 133 "svc 0\n" \ 134 : "+d"(_arg1) \ 135 : "d"(_arg2), "d"(_arg3), "d"(_arg4), "d"(_arg5), \ 136 "d"(_num) \ 137 : "memory", "cc" \ 138 ); \ 139 _arg1; \ 140 }) 141 142 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 143 ({ \ 144 register long _num __asm__ ("1") = (num); \ 145 register long _arg1 __asm__ ("2") = (long)(arg1); \ 146 register long _arg2 __asm__ ("3") = (long)(arg2); \ 147 register long _arg3 __asm__ ("4") = (long)(arg3); \ 148 register long _arg4 __asm__ ("5") = (long)(arg4); \ 149 register long _arg5 __asm__ ("6") = (long)(arg5); \ 150 register long _arg6 __asm__ ("7") = (long)(arg6); \ 151 \ 152 __asm__ volatile ( \ 153 "svc 0\n" \ 154 : "+d"(_arg1) \ 155 : "d"(_arg2), "d"(_arg3), "d"(_arg4), "d"(_arg5), \ 156 "d"(_arg6), "d"(_num) \ 157 : "memory", "cc" \ 158 ); \ 159 _arg1; \ 160 }) 161 162 char **environ __attribute__((weak)); 163 const unsigned long *_auxv __attribute__((weak)); 164 165 /* startup code */ 166 void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void) 167 { 168 __asm__ volatile ( 169 "lg %r2,0(%r15)\n" /* argument count */ 170 "la %r3,8(%r15)\n" /* argument pointers */ 171 172 "xgr %r0,%r0\n" /* r0 will be our NULL value */ 173 /* search for envp */ 174 "lgr %r4,%r3\n" /* start at argv */ 175 "0:\n" 176 "clg %r0,0(%r4)\n" /* entry zero? */ 177 "la %r4,8(%r4)\n" /* advance pointer */ 178 "jnz 0b\n" /* no -> test next pointer */ 179 /* yes -> r4 now contains start of envp */ 180 "larl %r1,environ\n" 181 "stg %r4,0(%r1)\n" 182 183 /* search for auxv */ 184 "lgr %r5,%r4\n" /* start at envp */ 185 "1:\n" 186 "clg %r0,0(%r5)\n" /* entry zero? */ 187 "la %r5,8(%r5)\n" /* advance pointer */ 188 "jnz 1b\n" /* no -> test next pointer */ 189 "larl %r1,_auxv\n" /* yes -> store value in _auxv */ 190 "stg %r5,0(%r1)\n" 191 192 "aghi %r15,-160\n" /* allocate new stackframe */ 193 "xc 0(8,%r15),0(%r15)\n" /* clear backchain */ 194 "brasl %r14,main\n" /* ret value of main is arg to exit */ 195 "lghi %r1,1\n" /* __NR_exit */ 196 "svc 0\n" 197 ); 198 __builtin_unreachable(); 199 } 200 201 struct s390_mmap_arg_struct { 202 unsigned long addr; 203 unsigned long len; 204 unsigned long prot; 205 unsigned long flags; 206 unsigned long fd; 207 unsigned long offset; 208 }; 209 210 static __attribute__((unused)) 211 void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd, 212 off_t offset) 213 { 214 struct s390_mmap_arg_struct args = { 215 .addr = (unsigned long)addr, 216 .len = (unsigned long)length, 217 .prot = prot, 218 .flags = flags, 219 .fd = fd, 220 .offset = (unsigned long)offset 221 }; 222 223 return (void *)my_syscall1(__NR_mmap, &args); 224 } 225 #define sys_mmap sys_mmap 226 #endif // _NOLIBC_ARCH_S390_H 227