sysdep.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /* Copyright (C) 2005-2019 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public License as
  5. published by the Free Software Foundation; either version 2.1 of the
  6. License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <http://www.gnu.org/licenses/>. */
  14. #ifndef _LINUX_AARCH64_SYSDEP_H
  15. #define _LINUX_AARCH64_SYSDEP_H 1
  16. /* Always enable vsyscalls on aarch64 */
  17. #define ALWAYS_USE_VSYSCALL 1
  18. #include <sysdeps/unix/sysdep.h>
  19. #include <sysdeps/aarch64/sysdep.h>
  20. #include <sysdeps/unix/sysv/linux/generic/sysdep.h>
  21. /* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO. */
  22. #include <dl-sysdep.h>
  23. #include <tls.h>
  24. /* In order to get __set_errno() definition in INLINE_SYSCALL. */
  25. #ifndef __ASSEMBLER__
  26. #include <errno.h>
  27. #endif
  28. /* For Linux we can use the system call table in the header file
  29. /usr/include/asm/unistd.h
  30. of the kernel. But these symbols do not follow the SYS_* syntax
  31. so we have to redefine the `SYS_ify' macro here. */
  32. #undef SYS_ify
  33. #define SYS_ify(syscall_name) (__NR_##syscall_name)
  34. #ifdef __ASSEMBLER__
  35. /* Linux uses a negative return value to indicate syscall errors,
  36. unlike most Unices, which use the condition codes' carry flag.
  37. Since version 2.1 the return value of a system call might be
  38. negative even if the call succeeded. E.g., the `lseek' system call
  39. might return a large offset. Therefore we must not anymore test
  40. for < 0, but test for a real error by making sure the value in R0
  41. is a real error number. Linus said he will make sure the no syscall
  42. returns a value in -1 .. -4095 as a valid result so we can safely
  43. test with -4095. */
  44. # undef PSEUDO
  45. # define PSEUDO(name, syscall_name, args) \
  46. .text; \
  47. ENTRY (name); \
  48. DO_CALL (syscall_name, args); \
  49. cmn x0, #4095; \
  50. b.cs .Lsyscall_error;
  51. # undef PSEUDO_END
  52. # define PSEUDO_END(name) \
  53. SYSCALL_ERROR_HANDLER \
  54. END (name)
  55. # undef PSEUDO_NOERRNO
  56. # define PSEUDO_NOERRNO(name, syscall_name, args) \
  57. .text; \
  58. ENTRY (name); \
  59. DO_CALL (syscall_name, args);
  60. # undef PSEUDO_END_NOERRNO
  61. # define PSEUDO_END_NOERRNO(name) \
  62. END (name)
  63. # define ret_NOERRNO ret
  64. /* The function has to return the error code. */
  65. # undef PSEUDO_ERRVAL
  66. # define PSEUDO_ERRVAL(name, syscall_name, args) \
  67. .text; \
  68. ENTRY (name) \
  69. DO_CALL (syscall_name, args); \
  70. neg x0, x0
  71. # undef PSEUDO_END_ERRVAL
  72. # define PSEUDO_END_ERRVAL(name) \
  73. END (name)
  74. # define ret_ERRVAL ret
  75. # if !IS_IN (libc)
  76. # define SYSCALL_ERROR .Lsyscall_error
  77. # if RTLD_PRIVATE_ERRNO
  78. # define SYSCALL_ERROR_HANDLER \
  79. .Lsyscall_error: \
  80. adrp x1, C_SYMBOL_NAME(rtld_errno); \
  81. neg w0, w0; \
  82. str w0, [x1, :lo12:C_SYMBOL_NAME(rtld_errno)]; \
  83. mov x0, -1; \
  84. RET;
  85. # else
  86. # define SYSCALL_ERROR_HANDLER \
  87. .Lsyscall_error: \
  88. adrp x1, :gottprel:errno; \
  89. neg w2, w0; \
  90. ldr PTR_REG(1), [x1, :gottprel_lo12:errno]; \
  91. mrs x3, tpidr_el0; \
  92. mov x0, -1; \
  93. str w2, [x1, x3]; \
  94. RET;
  95. # endif
  96. # else
  97. # define SYSCALL_ERROR __syscall_error
  98. # define SYSCALL_ERROR_HANDLER \
  99. .Lsyscall_error: \
  100. b __syscall_error;
  101. # endif
  102. /* Linux takes system call args in registers:
  103. syscall number x8
  104. arg 1 x0
  105. arg 2 x1
  106. arg 3 x2
  107. arg 4 x3
  108. arg 5 x4
  109. arg 6 x5
  110. arg 7 x6
  111. The compiler is going to form a call by coming here, through PSEUDO, with
  112. arguments
  113. syscall number in the DO_CALL macro
  114. arg 1 x0
  115. arg 2 x1
  116. arg 3 x2
  117. arg 4 x3
  118. arg 5 x4
  119. arg 6 x5
  120. arg 7 x6
  121. */
  122. # undef DO_CALL
  123. # define DO_CALL(syscall_name, args) \
  124. mov x8, SYS_ify (syscall_name); \
  125. svc 0
  126. #else /* not __ASSEMBLER__ */
  127. /* List of system calls which are supported as vsyscalls. */
  128. # define HAVE_CLOCK_GETRES_VSYSCALL 1
  129. # define HAVE_CLOCK_GETTIME_VSYSCALL 1
  130. # define HAVE_GETTIMEOFDAY_VSYSCALL 1
  131. /* Previously AArch64 used the generic version without the libc_hidden_def
  132. which lead in a non existent __send symbol in libc.so. */
  133. # undef HAVE_INTERNAL_SEND_SYMBOL
  134. # define SINGLE_THREAD_BY_GLOBAL 1
  135. /* Define a macro which expands into the inline wrapper code for a system
  136. call. */
  137. # undef INLINE_SYSCALL
  138. # define INLINE_SYSCALL(name, nr, args...) \
  139. ({ unsigned long _sys_result = INTERNAL_SYSCALL (name, , nr, args); \
  140. if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result, ), 0))\
  141. { \
  142. __set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, )); \
  143. _sys_result = (unsigned long) -1; \
  144. } \
  145. (long) _sys_result; })
  146. # undef INTERNAL_SYSCALL_DECL
  147. # define INTERNAL_SYSCALL_DECL(err) do { } while (0)
  148. # undef INTERNAL_SYSCALL_RAW
  149. # define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \
  150. ({ long _sys_result; \
  151. { \
  152. LOAD_ARGS_##nr (args) \
  153. register long _x8 asm ("x8") = (name); \
  154. asm volatile ("svc 0 // syscall " # name \
  155. : "=r" (_x0) : "r"(_x8) ASM_ARGS_##nr : "memory"); \
  156. _sys_result = _x0; \
  157. } \
  158. _sys_result; })
  159. # undef INTERNAL_SYSCALL
  160. # define INTERNAL_SYSCALL(name, err, nr, args...) \
  161. INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args)
  162. # undef INTERNAL_SYSCALL_AARCH64
  163. # define INTERNAL_SYSCALL_AARCH64(name, err, nr, args...) \
  164. INTERNAL_SYSCALL_RAW(__ARM_NR_##name, err, nr, args)
  165. # undef INTERNAL_SYSCALL_ERROR_P
  166. # define INTERNAL_SYSCALL_ERROR_P(val, err) \
  167. ((unsigned long) (val) >= (unsigned long) -4095)
  168. # undef INTERNAL_SYSCALL_ERRNO
  169. # define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
  170. # define LOAD_ARGS_0() \
  171. register long _x0 asm ("x0");
  172. # define LOAD_ARGS_1(x0) \
  173. long _x0tmp = (long) (x0); \
  174. LOAD_ARGS_0 () \
  175. _x0 = _x0tmp;
  176. # define LOAD_ARGS_2(x0, x1) \
  177. long _x1tmp = (long) (x1); \
  178. LOAD_ARGS_1 (x0) \
  179. register long _x1 asm ("x1") = _x1tmp;
  180. # define LOAD_ARGS_3(x0, x1, x2) \
  181. long _x2tmp = (long) (x2); \
  182. LOAD_ARGS_2 (x0, x1) \
  183. register long _x2 asm ("x2") = _x2tmp;
  184. # define LOAD_ARGS_4(x0, x1, x2, x3) \
  185. long _x3tmp = (long) (x3); \
  186. LOAD_ARGS_3 (x0, x1, x2) \
  187. register long _x3 asm ("x3") = _x3tmp;
  188. # define LOAD_ARGS_5(x0, x1, x2, x3, x4) \
  189. long _x4tmp = (long) (x4); \
  190. LOAD_ARGS_4 (x0, x1, x2, x3) \
  191. register long _x4 asm ("x4") = _x4tmp;
  192. # define LOAD_ARGS_6(x0, x1, x2, x3, x4, x5) \
  193. long _x5tmp = (long) (x5); \
  194. LOAD_ARGS_5 (x0, x1, x2, x3, x4) \
  195. register long _x5 asm ("x5") = _x5tmp;
  196. # define LOAD_ARGS_7(x0, x1, x2, x3, x4, x5, x6)\
  197. long _x6tmp = (long) (x6); \
  198. LOAD_ARGS_6 (x0, x1, x2, x3, x4, x5) \
  199. register long _x6 asm ("x6") = _x6tmp;
  200. # define ASM_ARGS_0
  201. # define ASM_ARGS_1 , "r" (_x0)
  202. # define ASM_ARGS_2 ASM_ARGS_1, "r" (_x1)
  203. # define ASM_ARGS_3 ASM_ARGS_2, "r" (_x2)
  204. # define ASM_ARGS_4 ASM_ARGS_3, "r" (_x3)
  205. # define ASM_ARGS_5 ASM_ARGS_4, "r" (_x4)
  206. # define ASM_ARGS_6 ASM_ARGS_5, "r" (_x5)
  207. # define ASM_ARGS_7 ASM_ARGS_6, "r" (_x6)
  208. # undef INTERNAL_SYSCALL_NCS
  209. # define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
  210. INTERNAL_SYSCALL_RAW (number, err, nr, args)
  211. #endif /* __ASSEMBLER__ */
  212. /* Pointer mangling is supported for AArch64. */
  213. #if (IS_IN (rtld) || \
  214. (!defined SHARED && (IS_IN (libc) \
  215. || IS_IN (libpthread))))
  216. # ifdef __ASSEMBLER__
  217. /* Note, dst, src, guard, and tmp are all register numbers rather than
  218. register names so they will work with both ILP32 and LP64. */
  219. # define PTR_MANGLE(dst, src, guard, tmp) \
  220. LDST_PCREL (ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard_local)); \
  221. PTR_MANGLE2 (dst, src, guard)
  222. /* Use PTR_MANGLE2 for efficiency if guard is already loaded. */
  223. # define PTR_MANGLE2(dst, src, guard)\
  224. eor x##dst, x##src, x##guard
  225. # define PTR_DEMANGLE(dst, src, guard, tmp)\
  226. PTR_MANGLE (dst, src, guard, tmp)
  227. # define PTR_DEMANGLE2(dst, src, guard)\
  228. PTR_MANGLE2 (dst, src, guard)
  229. # else
  230. extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
  231. # define PTR_MANGLE(var) \
  232. (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
  233. # define PTR_DEMANGLE(var) PTR_MANGLE (var)
  234. # endif
  235. #else
  236. # ifdef __ASSEMBLER__
  237. /* Note, dst, src, guard, and tmp are all register numbers rather than
  238. register names so they will work with both ILP32 and LP64. */
  239. # define PTR_MANGLE(dst, src, guard, tmp) \
  240. LDST_GLOBAL (ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard)); \
  241. PTR_MANGLE2 (dst, src, guard)
  242. /* Use PTR_MANGLE2 for efficiency if guard is already loaded. */
  243. # define PTR_MANGLE2(dst, src, guard)\
  244. eor x##dst, x##src, x##guard
  245. # define PTR_DEMANGLE(dst, src, guard, tmp)\
  246. PTR_MANGLE (dst, src, guard, tmp)
  247. # define PTR_DEMANGLE2(dst, src, guard)\
  248. PTR_MANGLE2 (dst, src, guard)
  249. # else
  250. extern uintptr_t __pointer_chk_guard attribute_relro;
  251. # define PTR_MANGLE(var) \
  252. (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
  253. # define PTR_DEMANGLE(var) PTR_MANGLE (var)
  254. # endif
  255. #endif
  256. #endif /* linux/aarch64/sysdep.h */