arch-s390.h 4.9 KB

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