187 lines · c
1/* SPDX-License-Identifier: LGPL-2.1 OR MIT */2/*3 * s390 specific definitions for NOLIBC4 */5 6#ifndef _NOLIBC_ARCH_S390_H7#define _NOLIBC_ARCH_S390_H8#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-bit16 * - syscall number is passed in r117 * - arguments are in r2-r718 * - the system call is performed by calling the svc instruction19 * - syscall return value is in r220 * - r1 and r2 are clobbered, others are preserved.21 *22 * Link s390 ABI: https://github.com/IBM/s390x-abi23 *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 */142void __attribute__((weak, noreturn)) __nolibc_entrypoint __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 __nolibc_entrypoint_epilogue();151}152 153struct 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 162static __attribute__((unused))163void *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)offset173 };174 175 return (void *)my_syscall1(__NR_mmap, &args);176}177#define sys_mmap sys_mmap178 179static __attribute__((unused))180pid_t sys_fork(void)181{182 return my_syscall5(__NR_clone, 0, SIGCHLD, 0, 0, 0);183}184#define sys_fork sys_fork185 186#endif /* _NOLIBC_ARCH_S390_H */187