1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 /* 2 /* 3 * s390 specific definitions for NOLIBC 3 * s390 specific definitions for NOLIBC 4 */ 4 */ 5 5 6 #ifndef _NOLIBC_ARCH_S390_H 6 #ifndef _NOLIBC_ARCH_S390_H 7 #define _NOLIBC_ARCH_S390_H 7 #define _NOLIBC_ARCH_S390_H 8 #include <asm/signal.h> << 9 #include <asm/unistd.h> 8 #include <asm/unistd.h> 10 9 11 #include "compiler.h" !! 10 /* The struct returned by the stat() syscall, equivalent to stat64(). The 12 #include "crt.h" !! 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 }; 13 34 14 /* Syscalls for s390: 35 /* Syscalls for s390: 15 * - registers are 64-bit 36 * - registers are 64-bit 16 * - syscall number is passed in r1 37 * - syscall number is passed in r1 17 * - arguments are in r2-r7 38 * - arguments are in r2-r7 18 * - the system call is performed by calling 39 * - the system call is performed by calling the svc instruction 19 * - syscall return value is in r2 40 * - syscall return value is in r2 20 * - r1 and r2 are clobbered, others are pre 41 * - r1 and r2 are clobbered, others are preserved. 21 * 42 * 22 * Link s390 ABI: https://github.com/IBM/s390x 43 * Link s390 ABI: https://github.com/IBM/s390x-abi 23 * 44 * 24 */ 45 */ 25 46 26 #define my_syscall0(num) 47 #define my_syscall0(num) \ 27 ({ 48 ({ \ 28 register long _num __asm__ ("1") = (nu 49 register long _num __asm__ ("1") = (num); \ 29 register long _rc __asm__ ("2"); 50 register long _rc __asm__ ("2"); \ 30 51 \ 31 __asm__ volatile ( !! 52 __asm__ volatile ( \ 32 "svc 0\n" 53 "svc 0\n" \ 33 : "=d"(_rc) 54 : "=d"(_rc) \ 34 : "d"(_num) 55 : "d"(_num) \ 35 : "memory", "cc" 56 : "memory", "cc" \ 36 ); 57 ); \ 37 _rc; 58 _rc; \ 38 }) 59 }) 39 60 40 #define my_syscall1(num, arg1) 61 #define my_syscall1(num, arg1) \ 41 ({ 62 ({ \ 42 register long _num __asm__ ("1") = (nu 63 register long _num __asm__ ("1") = (num); \ 43 register long _arg1 __asm__ ("2") = (l 64 register long _arg1 __asm__ ("2") = (long)(arg1); \ 44 65 \ 45 __asm__ volatile ( !! 66 __asm__ volatile ( \ 46 "svc 0\n" 67 "svc 0\n" \ 47 : "+d"(_arg1) 68 : "+d"(_arg1) \ 48 : "d"(_num) 69 : "d"(_num) \ 49 : "memory", "cc" 70 : "memory", "cc" \ 50 ); 71 ); \ 51 _arg1; 72 _arg1; \ 52 }) 73 }) 53 74 54 #define my_syscall2(num, arg1, arg2) 75 #define my_syscall2(num, arg1, arg2) \ 55 ({ 76 ({ \ 56 register long _num __asm__ ("1") = (nu 77 register long _num __asm__ ("1") = (num); \ 57 register long _arg1 __asm__ ("2") = (l 78 register long _arg1 __asm__ ("2") = (long)(arg1); \ 58 register long _arg2 __asm__ ("3") = (l 79 register long _arg2 __asm__ ("3") = (long)(arg2); \ 59 80 \ 60 __asm__ volatile ( !! 81 __asm__ volatile ( \ 61 "svc 0\n" 82 "svc 0\n" \ 62 : "+d"(_arg1) 83 : "+d"(_arg1) \ 63 : "d"(_arg2), "d"(_num) 84 : "d"(_arg2), "d"(_num) \ 64 : "memory", "cc" 85 : "memory", "cc" \ 65 ); 86 ); \ 66 _arg1; 87 _arg1; \ 67 }) 88 }) 68 89 69 #define my_syscall3(num, arg1, arg2, arg3) 90 #define my_syscall3(num, arg1, arg2, arg3) \ 70 ({ 91 ({ \ 71 register long _num __asm__ ("1") = (nu 92 register long _num __asm__ ("1") = (num); \ 72 register long _arg1 __asm__ ("2") = (l 93 register long _arg1 __asm__ ("2") = (long)(arg1); \ 73 register long _arg2 __asm__ ("3") = (l 94 register long _arg2 __asm__ ("3") = (long)(arg2); \ 74 register long _arg3 __asm__ ("4") = (l 95 register long _arg3 __asm__ ("4") = (long)(arg3); \ 75 96 \ 76 __asm__ volatile ( !! 97 __asm__ volatile ( \ 77 "svc 0\n" 98 "svc 0\n" \ 78 : "+d"(_arg1) 99 : "+d"(_arg1) \ 79 : "d"(_arg2), "d"(_arg3), "d"( 100 : "d"(_arg2), "d"(_arg3), "d"(_num) \ 80 : "memory", "cc" 101 : "memory", "cc" \ 81 ); 102 ); \ 82 _arg1; 103 _arg1; \ 83 }) 104 }) 84 105 85 #define my_syscall4(num, arg1, arg2, arg3, arg 106 #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 86 ({ 107 ({ \ 87 register long _num __asm__ ("1") = (nu 108 register long _num __asm__ ("1") = (num); \ 88 register long _arg1 __asm__ ("2") = (l 109 register long _arg1 __asm__ ("2") = (long)(arg1); \ 89 register long _arg2 __asm__ ("3") = (l 110 register long _arg2 __asm__ ("3") = (long)(arg2); \ 90 register long _arg3 __asm__ ("4") = (l 111 register long _arg3 __asm__ ("4") = (long)(arg3); \ 91 register long _arg4 __asm__ ("5") = (l 112 register long _arg4 __asm__ ("5") = (long)(arg4); \ 92 113 \ 93 __asm__ volatile ( !! 114 __asm__ volatile ( \ 94 "svc 0\n" 115 "svc 0\n" \ 95 : "+d"(_arg1) 116 : "+d"(_arg1) \ 96 : "d"(_arg2), "d"(_arg3), "d"( 117 : "d"(_arg2), "d"(_arg3), "d"(_arg4), "d"(_num) \ 97 : "memory", "cc" 118 : "memory", "cc" \ 98 ); 119 ); \ 99 _arg1; 120 _arg1; \ 100 }) 121 }) 101 122 102 #define my_syscall5(num, arg1, arg2, arg3, arg 123 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 103 ({ 124 ({ \ 104 register long _num __asm__ ("1") = (nu 125 register long _num __asm__ ("1") = (num); \ 105 register long _arg1 __asm__ ("2") = (l 126 register long _arg1 __asm__ ("2") = (long)(arg1); \ 106 register long _arg2 __asm__ ("3") = (l 127 register long _arg2 __asm__ ("3") = (long)(arg2); \ 107 register long _arg3 __asm__ ("4") = (l 128 register long _arg3 __asm__ ("4") = (long)(arg3); \ 108 register long _arg4 __asm__ ("5") = (l 129 register long _arg4 __asm__ ("5") = (long)(arg4); \ 109 register long _arg5 __asm__ ("6") = (l 130 register long _arg5 __asm__ ("6") = (long)(arg5); \ 110 131 \ 111 __asm__ volatile ( !! 132 __asm__ volatile ( \ 112 "svc 0\n" 133 "svc 0\n" \ 113 : "+d"(_arg1) 134 : "+d"(_arg1) \ 114 : "d"(_arg2), "d"(_arg3), "d"( 135 : "d"(_arg2), "d"(_arg3), "d"(_arg4), "d"(_arg5), \ 115 "d"(_num) 136 "d"(_num) \ 116 : "memory", "cc" 137 : "memory", "cc" \ 117 ); 138 ); \ 118 _arg1; 139 _arg1; \ 119 }) 140 }) 120 141 121 #define my_syscall6(num, arg1, arg2, arg3, arg 142 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 122 ({ 143 ({ \ 123 register long _num __asm__ ("1") = (nu 144 register long _num __asm__ ("1") = (num); \ 124 register long _arg1 __asm__ ("2") = (l 145 register long _arg1 __asm__ ("2") = (long)(arg1); \ 125 register long _arg2 __asm__ ("3") = (l 146 register long _arg2 __asm__ ("3") = (long)(arg2); \ 126 register long _arg3 __asm__ ("4") = (l 147 register long _arg3 __asm__ ("4") = (long)(arg3); \ 127 register long _arg4 __asm__ ("5") = (l 148 register long _arg4 __asm__ ("5") = (long)(arg4); \ 128 register long _arg5 __asm__ ("6") = (l 149 register long _arg5 __asm__ ("6") = (long)(arg5); \ 129 register long _arg6 __asm__ ("7") = (l 150 register long _arg6 __asm__ ("7") = (long)(arg6); \ 130 151 \ 131 __asm__ volatile ( !! 152 __asm__ volatile ( \ 132 "svc 0\n" 153 "svc 0\n" \ 133 : "+d"(_arg1) 154 : "+d"(_arg1) \ 134 : "d"(_arg2), "d"(_arg3), "d"( 155 : "d"(_arg2), "d"(_arg3), "d"(_arg4), "d"(_arg5), \ 135 "d"(_arg6), "d"(_num) 156 "d"(_arg6), "d"(_num) \ 136 : "memory", "cc" 157 : "memory", "cc" \ 137 ); 158 ); \ 138 _arg1; 159 _arg1; \ 139 }) 160 }) 140 161 >> 162 char **environ __attribute__((weak)); >> 163 const unsigned long *_auxv __attribute__((weak)); >> 164 141 /* startup code */ 165 /* startup code */ 142 void __attribute__((weak, noreturn)) __nolibc_ !! 166 void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void) 143 { 167 { 144 __asm__ volatile ( 168 __asm__ volatile ( 145 "lgr %r2, %r15\n" !! 169 "lg %r2,0(%r15)\n" /* argument count */ 146 "aghi %r15, -160\n" !! 170 "la %r3,8(%r15)\n" /* argument pointers */ 147 "xc 0(8,%r15), 0(%r15)\n" !! 171 148 "brasl %r14, _start_c\n" !! 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" 149 ); 197 ); 150 __nolibc_entrypoint_epilogue(); !! 198 __builtin_unreachable(); 151 } 199 } 152 200 153 struct s390_mmap_arg_struct { 201 struct s390_mmap_arg_struct { 154 unsigned long addr; 202 unsigned long addr; 155 unsigned long len; 203 unsigned long len; 156 unsigned long prot; 204 unsigned long prot; 157 unsigned long flags; 205 unsigned long flags; 158 unsigned long fd; 206 unsigned long fd; 159 unsigned long offset; 207 unsigned long offset; 160 }; 208 }; 161 209 162 static __attribute__((unused)) 210 static __attribute__((unused)) 163 void *sys_mmap(void *addr, size_t length, int 211 void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd, 164 off_t offset) 212 off_t offset) 165 { 213 { 166 struct s390_mmap_arg_struct args = { 214 struct s390_mmap_arg_struct args = { 167 .addr = (unsigned long)addr, 215 .addr = (unsigned long)addr, 168 .len = (unsigned long)length, 216 .len = (unsigned long)length, 169 .prot = prot, 217 .prot = prot, 170 .flags = flags, 218 .flags = flags, 171 .fd = fd, 219 .fd = fd, 172 .offset = (unsigned long)offse 220 .offset = (unsigned long)offset 173 }; 221 }; 174 222 175 return (void *)my_syscall1(__NR_mmap, 223 return (void *)my_syscall1(__NR_mmap, &args); 176 } 224 } 177 #define sys_mmap sys_mmap 225 #define sys_mmap sys_mmap 178 !! 226 #endif // _NOLIBC_ARCH_S390_H 179 static __attribute__((unused)) << 180 pid_t sys_fork(void) << 181 { << 182 return my_syscall5(__NR_clone, 0, SIGC << 183 } << 184 #define sys_fork sys_fork << 185 << 186 #endif /* _NOLIBC_ARCH_S390_H */ << 187 227
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.