arch-aarch64.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
  2. /*
  3. * AARCH64 specific definitions for NOLIBC
  4. * Copyright (C) 2017-2022 Willy Tarreau <[email protected]>
  5. */
  6. #ifndef _NOLIBC_ARCH_AARCH64_H
  7. #define _NOLIBC_ARCH_AARCH64_H
  8. /* O_* macros for fcntl/open are architecture-specific */
  9. #define O_RDONLY 0
  10. #define O_WRONLY 1
  11. #define O_RDWR 2
  12. #define O_CREAT 0x40
  13. #define O_EXCL 0x80
  14. #define O_NOCTTY 0x100
  15. #define O_TRUNC 0x200
  16. #define O_APPEND 0x400
  17. #define O_NONBLOCK 0x800
  18. #define O_DIRECTORY 0x4000
  19. /* The struct returned by the newfstatat() syscall. Differs slightly from the
  20. * x86_64's stat one by field ordering, so be careful.
  21. */
  22. struct sys_stat_struct {
  23. unsigned long st_dev;
  24. unsigned long st_ino;
  25. unsigned int st_mode;
  26. unsigned int st_nlink;
  27. unsigned int st_uid;
  28. unsigned int st_gid;
  29. unsigned long st_rdev;
  30. unsigned long __pad1;
  31. long st_size;
  32. int st_blksize;
  33. int __pad2;
  34. long st_blocks;
  35. long st_atime;
  36. unsigned long st_atime_nsec;
  37. long st_mtime;
  38. unsigned long st_mtime_nsec;
  39. long st_ctime;
  40. unsigned long st_ctime_nsec;
  41. unsigned int __unused[2];
  42. };
  43. /* Syscalls for AARCH64 :
  44. * - registers are 64-bit
  45. * - stack is 16-byte aligned
  46. * - syscall number is passed in x8
  47. * - arguments are in x0, x1, x2, x3, x4, x5
  48. * - the system call is performed by calling svc 0
  49. * - syscall return comes in x0.
  50. * - the arguments are cast to long and assigned into the target registers
  51. * which are then simply passed as registers to the asm code, so that we
  52. * don't have to experience issues with register constraints.
  53. *
  54. * On aarch64, select() is not implemented so we have to use pselect6().
  55. */
  56. #define __ARCH_WANT_SYS_PSELECT6
  57. #define my_syscall0(num) \
  58. ({ \
  59. register long _num __asm__ ("x8") = (num); \
  60. register long _arg1 __asm__ ("x0"); \
  61. \
  62. __asm__ volatile ( \
  63. "svc #0\n" \
  64. : "=r"(_arg1) \
  65. : "r"(_num) \
  66. : "memory", "cc" \
  67. ); \
  68. _arg1; \
  69. })
  70. #define my_syscall1(num, arg1) \
  71. ({ \
  72. register long _num __asm__ ("x8") = (num); \
  73. register long _arg1 __asm__ ("x0") = (long)(arg1); \
  74. \
  75. __asm__ volatile ( \
  76. "svc #0\n" \
  77. : "=r"(_arg1) \
  78. : "r"(_arg1), \
  79. "r"(_num) \
  80. : "memory", "cc" \
  81. ); \
  82. _arg1; \
  83. })
  84. #define my_syscall2(num, arg1, arg2) \
  85. ({ \
  86. register long _num __asm__ ("x8") = (num); \
  87. register long _arg1 __asm__ ("x0") = (long)(arg1); \
  88. register long _arg2 __asm__ ("x1") = (long)(arg2); \
  89. \
  90. __asm__ volatile ( \
  91. "svc #0\n" \
  92. : "=r"(_arg1) \
  93. : "r"(_arg1), "r"(_arg2), \
  94. "r"(_num) \
  95. : "memory", "cc" \
  96. ); \
  97. _arg1; \
  98. })
  99. #define my_syscall3(num, arg1, arg2, arg3) \
  100. ({ \
  101. register long _num __asm__ ("x8") = (num); \
  102. register long _arg1 __asm__ ("x0") = (long)(arg1); \
  103. register long _arg2 __asm__ ("x1") = (long)(arg2); \
  104. register long _arg3 __asm__ ("x2") = (long)(arg3); \
  105. \
  106. __asm__ volatile ( \
  107. "svc #0\n" \
  108. : "=r"(_arg1) \
  109. : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
  110. "r"(_num) \
  111. : "memory", "cc" \
  112. ); \
  113. _arg1; \
  114. })
  115. #define my_syscall4(num, arg1, arg2, arg3, arg4) \
  116. ({ \
  117. register long _num __asm__ ("x8") = (num); \
  118. register long _arg1 __asm__ ("x0") = (long)(arg1); \
  119. register long _arg2 __asm__ ("x1") = (long)(arg2); \
  120. register long _arg3 __asm__ ("x2") = (long)(arg3); \
  121. register long _arg4 __asm__ ("x3") = (long)(arg4); \
  122. \
  123. __asm__ volatile ( \
  124. "svc #0\n" \
  125. : "=r"(_arg1) \
  126. : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
  127. "r"(_num) \
  128. : "memory", "cc" \
  129. ); \
  130. _arg1; \
  131. })
  132. #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
  133. ({ \
  134. register long _num __asm__ ("x8") = (num); \
  135. register long _arg1 __asm__ ("x0") = (long)(arg1); \
  136. register long _arg2 __asm__ ("x1") = (long)(arg2); \
  137. register long _arg3 __asm__ ("x2") = (long)(arg3); \
  138. register long _arg4 __asm__ ("x3") = (long)(arg4); \
  139. register long _arg5 __asm__ ("x4") = (long)(arg5); \
  140. \
  141. __asm__ volatile ( \
  142. "svc #0\n" \
  143. : "=r" (_arg1) \
  144. : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
  145. "r"(_num) \
  146. : "memory", "cc" \
  147. ); \
  148. _arg1; \
  149. })
  150. #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
  151. ({ \
  152. register long _num __asm__ ("x8") = (num); \
  153. register long _arg1 __asm__ ("x0") = (long)(arg1); \
  154. register long _arg2 __asm__ ("x1") = (long)(arg2); \
  155. register long _arg3 __asm__ ("x2") = (long)(arg3); \
  156. register long _arg4 __asm__ ("x3") = (long)(arg4); \
  157. register long _arg5 __asm__ ("x4") = (long)(arg5); \
  158. register long _arg6 __asm__ ("x5") = (long)(arg6); \
  159. \
  160. __asm__ volatile ( \
  161. "svc #0\n" \
  162. : "=r" (_arg1) \
  163. : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
  164. "r"(_arg6), "r"(_num) \
  165. : "memory", "cc" \
  166. ); \
  167. _arg1; \
  168. })
  169. /* startup code */
  170. __asm__ (".section .text\n"
  171. ".weak _start\n"
  172. "_start:\n"
  173. "ldr x0, [sp]\n" // argc (x0) was in the stack
  174. "add x1, sp, 8\n" // argv (x1) = sp
  175. "lsl x2, x0, 3\n" // envp (x2) = 8*argc ...
  176. "add x2, x2, 8\n" // + 8 (skip null)
  177. "add x2, x2, x1\n" // + argv
  178. "and sp, x1, -16\n" // sp must be 16-byte aligned in the callee
  179. "bl main\n" // main() returns the status code, we'll exit with it.
  180. "mov x8, 93\n" // NR_exit == 93
  181. "svc #0\n"
  182. "");
  183. #endif // _NOLIBC_ARCH_AARCH64_H