syscalls.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /* Copyright (C) 2011-2018 Free Software Foundation, Inc.
  2. The GNU C Library is free software; you can redistribute it and/or
  3. modify it under the terms of the GNU Lesser General Public
  4. License as published by the Free Software Foundation; either
  5. version 2.1 of the License, or (at your option) any later version.
  6. The GNU C Library is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  9. Lesser General Public License for more details.
  10. You should have received a copy of the GNU Lesser General Public
  11. License along with the GNU C Library. If not, see
  12. <http://www.gnu.org/licenses/>. */
  13. #ifndef _BITS_SYSCALLS_H
  14. #define _BITS_SYSCALLS_H
  15. #ifndef _SYSCALL_H
  16. # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
  17. #endif
  18. /* Define a macro which expands inline into the wrapper code for a system
  19. call. */
  20. # undef INLINE_SYSCALL
  21. # define INLINE_SYSCALL(name, nr, args...) \
  22. ({ \
  23. INTERNAL_SYSCALL_DECL (_sc_err); \
  24. unsigned long _sc_val = INTERNAL_SYSCALL (name, _sc_err, nr, args); \
  25. if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sc_val, _sc_err), 0)) \
  26. { \
  27. __set_errno (INTERNAL_SYSCALL_ERRNO (_sc_val, _sc_err)); \
  28. _sc_val = -1; \
  29. } \
  30. (long) _sc_val; \
  31. })
  32. #undef INTERNAL_SYSCALL
  33. #define INTERNAL_SYSCALL(name, err, nr, args...) \
  34. internal_syscall##nr (SYS_ify (name), err, args)
  35. #undef INTERNAL_SYSCALL_NCS
  36. #define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
  37. internal_syscall##nr (number, err, args)
  38. #undef INTERNAL_SYSCALL_DECL
  39. #define INTERNAL_SYSCALL_DECL(err) int err
  40. #undef INTERNAL_SYSCALL_ERROR_P
  41. #define INTERNAL_SYSCALL_ERROR_P(val, err) ({ (void) (val); (err) != 0; })
  42. #undef INTERNAL_SYSCALL_ERRNO
  43. #define INTERNAL_SYSCALL_ERRNO(val, err) ({ (void) (val); (err); })
  44. #define internal_syscall0(num, err, dummy...) \
  45. ({ \
  46. long _sys_result, __SYSCALL_CLOBBER_DECLS; \
  47. __asm__ __volatile__ ( \
  48. "swint1" \
  49. : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \
  50. : "R10" (num) \
  51. : __SYSCALL_CLOBBERS); \
  52. _sys_result; \
  53. })
  54. #define internal_syscall1(num, err, arg0) \
  55. ({ \
  56. long _sys_result, __SYSCALL_CLOBBER_DECLS; \
  57. __asm__ __volatile__ ( \
  58. "swint1" \
  59. : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \
  60. : "R10" (num), "R00" (arg0) \
  61. : __SYSCALL_CLOBBERS); \
  62. _sys_result; \
  63. })
  64. #define internal_syscall2(num, err, arg0, arg1) \
  65. ({ \
  66. long _sys_result, __SYSCALL_CLOBBER_DECLS; \
  67. __asm__ __volatile__ ( \
  68. "swint1" \
  69. : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \
  70. : "R10" (num), "R00" (arg0), "R01" (arg1) \
  71. : __SYSCALL_CLOBBERS); \
  72. _sys_result; \
  73. })
  74. #define internal_syscall3(num, err, arg0, arg1, arg2) \
  75. ({ \
  76. long _sys_result, __SYSCALL_CLOBBER_DECLS; \
  77. __asm__ __volatile__ ( \
  78. "swint1" \
  79. : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \
  80. : "R10" (num), "R00" (arg0), "R01" (arg1), "R02" (arg2) \
  81. : __SYSCALL_CLOBBERS); \
  82. _sys_result; \
  83. })
  84. #define internal_syscall4(num, err, arg0, arg1, arg2, arg3) \
  85. ({ \
  86. long _sys_result, __SYSCALL_CLOBBER_DECLS; \
  87. __asm__ __volatile__ ( \
  88. "swint1" \
  89. : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \
  90. : "R10" (num), "R00" (arg0), "R01" (arg1), "R02" (arg2), \
  91. "R03" (arg3) \
  92. : __SYSCALL_CLOBBERS); \
  93. _sys_result; \
  94. })
  95. #define internal_syscall5(num, err, arg0, arg1, arg2, arg3, arg4) \
  96. ({ \
  97. long _sys_result, __SYSCALL_CLOBBER_DECLS; \
  98. __asm__ __volatile__ ( \
  99. "swint1" \
  100. : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \
  101. : "R10" (num), "R00" (arg0), "R01" (arg1), "R02" (arg2), \
  102. "R03" (arg3), "R04" (arg4) \
  103. : __SYSCALL_CLOBBERS); \
  104. _sys_result; \
  105. })
  106. #define internal_syscall6(num, err, arg0, arg1, arg2, arg3, arg4, arg5) \
  107. ({ \
  108. long _sys_result, __SYSCALL_CLOBBER_DECLS; \
  109. __asm__ __volatile__ ( \
  110. "swint1" \
  111. : "=R00" (_sys_result), "=R01" (err), __SYSCALL_CLOBBER_OUTPUTS \
  112. : "R10" (num), "R00" (arg0), "R01" (arg1), "R02" (arg2), \
  113. "R03" (arg3), "R04" (arg4), "R05" (arg5) \
  114. : __SYSCALL_CLOBBERS); \
  115. _sys_result; \
  116. })
  117. #undef __SYSCALL_CLOBBERS
  118. #define __SYSCALL_CLOBBERS \
  119. "r6", "r7", \
  120. "r8", "r9", "r11", "r12", "r13", "r14", "r15", \
  121. "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \
  122. "r24", "r25", "r26", "r27", "r28", "r29", "memory"
  123. /* gcc doesn't seem to allow an input operand to be clobbered, so we
  124. fake it with dummy outputs. */
  125. #define __SYSCALL_CLOBBER_DECLS \
  126. _clobber_r2, _clobber_r3, _clobber_r4, _clobber_r5, _clobber_r10
  127. #define __SYSCALL_CLOBBER_OUTPUTS \
  128. "=R02" (_clobber_r2), "=R03" (_clobber_r3), "=R04" (_clobber_r4), \
  129. "=R05" (_clobber_r5), "=R10" (_clobber_r10)
  130. #endif