syscalls.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #ifndef _BITS_SYSCALLS_H
  2. #define _BITS_SYSCALLS_H
  3. #ifndef _SYSCALL_H
  4. # error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
  5. #endif
  6. #include <errno.h>
  7. /* This includes the `__NR_<name>' syscall numbers taken from the Linux kernel
  8. * header files. It also defines the traditional `SYS_<name>' macros for older
  9. * programs. */
  10. #include <bits/sysnum.h>
  11. /* Define a macro which expands inline into the wrapper code for a system
  12. call. This use is for internal calls that do not need to handle errors
  13. normally. It will never touch errno.
  14. On powerpc a system call basically clobbers the same registers like a
  15. function call, with the exception of LR (which is needed for the
  16. "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal
  17. an error return status). */
  18. # undef INLINE_SYSCALL
  19. #if 1
  20. # define INLINE_SYSCALL(name, nr, args...) \
  21. ({ \
  22. INTERNAL_SYSCALL_DECL (sc_err); \
  23. long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args); \
  24. if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \
  25. { \
  26. __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err)); \
  27. sc_ret = -1L; \
  28. } \
  29. sc_ret; \
  30. })
  31. #else
  32. # define INLINE_SYSCALL(name, nr, args...) \
  33. ({ \
  34. INTERNAL_SYSCALL_DECL (sc_err); \
  35. long int sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, args); \
  36. if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \
  37. { \
  38. sc_ret = __syscall_error(INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err));\
  39. } \
  40. sc_ret; \
  41. })
  42. #endif
  43. /* Define a macro which expands inline into the wrapper code for a system
  44. call. This use is for internal calls that do not need to handle errors
  45. normally. It will never touch errno.
  46. On powerpc a system call basically clobbers the same registers like a
  47. function call, with the exception of LR (which is needed for the
  48. "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal
  49. an error return status). */
  50. # undef INTERNAL_SYSCALL_DECL
  51. # define INTERNAL_SYSCALL_DECL(err) long int err
  52. # undef INTERNAL_SYSCALL
  53. # define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
  54. ({ \
  55. register long int r0 __asm__ ("r0"); \
  56. register long int r3 __asm__ ("r3"); \
  57. register long int r4 __asm__ ("r4"); \
  58. register long int r5 __asm__ ("r5"); \
  59. register long int r6 __asm__ ("r6"); \
  60. register long int r7 __asm__ ("r7"); \
  61. register long int r8 __asm__ ("r8"); \
  62. register long int r9 __asm__ ("r9"); \
  63. register long int r10 __asm__ ("r10"); \
  64. register long int r11 __asm__ ("r11"); \
  65. register long int r12 __asm__ ("r12"); \
  66. LOADARGS_##nr(name, args); \
  67. __asm__ __volatile__ \
  68. ("sc \n\t" \
  69. "mfcr %0" \
  70. : "=&r" (r0), \
  71. "=&r" (r3), "=&r" (r4), "=&r" (r5), "=&r" (r6), "=&r" (r7), \
  72. "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12) \
  73. : ASM_INPUT_##nr \
  74. : "cr0", "ctr", "memory"); \
  75. err = r0; \
  76. (int) r3; \
  77. })
  78. # define INTERNAL_SYSCALL(name, err, nr, args...) \
  79. INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
  80. # undef INTERNAL_SYSCALL_ERROR_P
  81. # define INTERNAL_SYSCALL_ERROR_P(val, err) \
  82. ((void) (val), __builtin_expect ((err) & (1 << 28), 0))
  83. # undef INTERNAL_SYSCALL_ERRNO
  84. # define INTERNAL_SYSCALL_ERRNO(val, err) (val)
  85. # define LOADARGS_0(name, dummy) \
  86. r0 = (long int)name
  87. # define LOADARGS_1(name, __arg1) \
  88. LOADARGS_0(name, 0); \
  89. r3 = (long int)__arg1
  90. # define LOADARGS_2(name, __arg1, __arg2) \
  91. LOADARGS_1(name, __arg1); \
  92. r4 = (long int)__arg2
  93. # define LOADARGS_3(name, __arg1, __arg2, __arg3) \
  94. LOADARGS_2(name, __arg1, __arg2); \
  95. r5 = (long int)__arg3
  96. # define LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4) \
  97. LOADARGS_3(name, __arg1, __arg2, __arg3); \
  98. r6 = (long int)__arg4
  99. # define LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \
  100. LOADARGS_4(name, __arg1, __arg2, __arg3, __arg4); \
  101. r7 = (long int)__arg5
  102. # define LOADARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \
  103. LOADARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \
  104. r8 = (long int)__arg6
  105. # define ASM_INPUT_0 "0" (r0)
  106. # define ASM_INPUT_1 ASM_INPUT_0, "1" (r3)
  107. # define ASM_INPUT_2 ASM_INPUT_1, "2" (r4)
  108. # define ASM_INPUT_3 ASM_INPUT_2, "3" (r5)
  109. # define ASM_INPUT_4 ASM_INPUT_3, "4" (r6)
  110. # define ASM_INPUT_5 ASM_INPUT_4, "5" (r7)
  111. # define ASM_INPUT_6 ASM_INPUT_5, "6" (r8)
  112. #undef _syscall0
  113. #define _syscall0(type,name) \
  114. type name(void){ \
  115. return (type) INLINE_SYSCALL(name, 0); \
  116. }
  117. #undef _syscall1
  118. #define _syscall1(type,name,type1,arg1) \
  119. type name(type1 arg1){ \
  120. return (type) INLINE_SYSCALL(name, 1, arg1); \
  121. }
  122. #undef _syscall2
  123. #define _syscall2(type,name,type1,arg1,type2,arg2) \
  124. type name(type1 arg1, type2 arg2){ \
  125. return (type) INLINE_SYSCALL(name, 2, arg1, arg2); \
  126. }
  127. #undef _syscall3
  128. #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
  129. type name(type1 arg1, type2 arg2, type3 arg3){ \
  130. return (type) INLINE_SYSCALL(name, 3, arg1, arg2, arg3); \
  131. }
  132. #undef _syscall4
  133. #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
  134. type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4){ \
  135. return (type) INLINE_SYSCALL(name, 4, arg1, arg2, arg3, arg4); \
  136. }
  137. #undef _syscall5
  138. #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
  139. type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5){ \
  140. return (type) INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5); \
  141. }
  142. #undef _syscall6
  143. #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
  144. type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6){ \
  145. return (type) INLINE_SYSCALL(name, 6, arg1, arg2, arg3, arg4, arg5, arg6); \
  146. }
  147. #endif /* _BITS_SYSCALLS_H */