arch-s390.h 5.2 KB

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