syscall.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Access to user system call parameters and results
  3. *
  4. * Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved.
  5. *
  6. * This copyrighted material is made available to anyone wishing to use,
  7. * modify, copy, or redistribute it subject to the terms and conditions
  8. * of the GNU General Public License v.2.
  9. *
  10. * See asm-generic/syscall.h for descriptions of what we must do here.
  11. */
  12. #ifndef _ASM_X86_SYSCALL_H
  13. #define _ASM_X86_SYSCALL_H
  14. #include <linux/sched.h>
  15. #include <linux/err.h>
  16. extern const unsigned long sys_call_table[];
  17. /*
  18. * Only the low 32 bits of orig_ax are meaningful, so we return int.
  19. * This importantly ignores the high bits on 64-bit, so comparisons
  20. * sign-extend the low 32 bits.
  21. */
  22. static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
  23. {
  24. return regs->orig_ax;
  25. }
  26. static inline void syscall_rollback(struct task_struct *task,
  27. struct pt_regs *regs)
  28. {
  29. regs->ax = regs->orig_ax;
  30. }
  31. static inline long syscall_get_error(struct task_struct *task,
  32. struct pt_regs *regs)
  33. {
  34. unsigned long error = regs->ax;
  35. #ifdef CONFIG_IA32_EMULATION
  36. /*
  37. * TS_COMPAT is set for 32-bit syscall entries and then
  38. * remains set until we return to user mode.
  39. */
  40. if (task_thread_info(task)->status & TS_COMPAT)
  41. /*
  42. * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
  43. * and will match correctly in comparisons.
  44. */
  45. error = (long) (int) error;
  46. #endif
  47. return IS_ERR_VALUE(error) ? error : 0;
  48. }
  49. static inline long syscall_get_return_value(struct task_struct *task,
  50. struct pt_regs *regs)
  51. {
  52. return regs->ax;
  53. }
  54. static inline void syscall_set_return_value(struct task_struct *task,
  55. struct pt_regs *regs,
  56. int error, long val)
  57. {
  58. regs->ax = (long) error ?: val;
  59. }
  60. #ifdef CONFIG_X86_32
  61. static inline void syscall_get_arguments(struct task_struct *task,
  62. struct pt_regs *regs,
  63. unsigned int i, unsigned int n,
  64. unsigned long *args)
  65. {
  66. BUG_ON(i + n > 6);
  67. memcpy(args, &regs->bx + i, n * sizeof(args[0]));
  68. }
  69. static inline void syscall_set_arguments(struct task_struct *task,
  70. struct pt_regs *regs,
  71. unsigned int i, unsigned int n,
  72. const unsigned long *args)
  73. {
  74. BUG_ON(i + n > 6);
  75. memcpy(&regs->bx + i, args, n * sizeof(args[0]));
  76. }
  77. #else /* CONFIG_X86_64 */
  78. static inline void syscall_get_arguments(struct task_struct *task,
  79. struct pt_regs *regs,
  80. unsigned int i, unsigned int n,
  81. unsigned long *args)
  82. {
  83. # ifdef CONFIG_IA32_EMULATION
  84. if (task_thread_info(task)->status & TS_COMPAT)
  85. switch (i) {
  86. case 0:
  87. if (!n--) break;
  88. *args++ = regs->bx;
  89. case 1:
  90. if (!n--) break;
  91. *args++ = regs->cx;
  92. case 2:
  93. if (!n--) break;
  94. *args++ = regs->dx;
  95. case 3:
  96. if (!n--) break;
  97. *args++ = regs->si;
  98. case 4:
  99. if (!n--) break;
  100. *args++ = regs->di;
  101. case 5:
  102. if (!n--) break;
  103. *args++ = regs->bp;
  104. case 6:
  105. if (!n--) break;
  106. default:
  107. BUG();
  108. break;
  109. }
  110. else
  111. # endif
  112. switch (i) {
  113. case 0:
  114. if (!n--) break;
  115. *args++ = regs->di;
  116. case 1:
  117. if (!n--) break;
  118. *args++ = regs->si;
  119. case 2:
  120. if (!n--) break;
  121. *args++ = regs->dx;
  122. case 3:
  123. if (!n--) break;
  124. *args++ = regs->r10;
  125. case 4:
  126. if (!n--) break;
  127. *args++ = regs->r8;
  128. case 5:
  129. if (!n--) break;
  130. *args++ = regs->r9;
  131. case 6:
  132. if (!n--) break;
  133. default:
  134. BUG();
  135. break;
  136. }
  137. }
  138. static inline void syscall_set_arguments(struct task_struct *task,
  139. struct pt_regs *regs,
  140. unsigned int i, unsigned int n,
  141. const unsigned long *args)
  142. {
  143. # ifdef CONFIG_IA32_EMULATION
  144. if (task_thread_info(task)->status & TS_COMPAT)
  145. switch (i) {
  146. case 0:
  147. if (!n--) break;
  148. regs->bx = *args++;
  149. case 1:
  150. if (!n--) break;
  151. regs->cx = *args++;
  152. case 2:
  153. if (!n--) break;
  154. regs->dx = *args++;
  155. case 3:
  156. if (!n--) break;
  157. regs->si = *args++;
  158. case 4:
  159. if (!n--) break;
  160. regs->di = *args++;
  161. case 5:
  162. if (!n--) break;
  163. regs->bp = *args++;
  164. case 6:
  165. if (!n--) break;
  166. default:
  167. BUG();
  168. break;
  169. }
  170. else
  171. # endif
  172. switch (i) {
  173. case 0:
  174. if (!n--) break;
  175. regs->di = *args++;
  176. case 1:
  177. if (!n--) break;
  178. regs->si = *args++;
  179. case 2:
  180. if (!n--) break;
  181. regs->dx = *args++;
  182. case 3:
  183. if (!n--) break;
  184. regs->r10 = *args++;
  185. case 4:
  186. if (!n--) break;
  187. regs->r8 = *args++;
  188. case 5:
  189. if (!n--) break;
  190. regs->r9 = *args++;
  191. case 6:
  192. if (!n--) break;
  193. default:
  194. BUG();
  195. break;
  196. }
  197. }
  198. #endif /* CONFIG_X86_32 */
  199. #endif /* _ASM_X86_SYSCALL_H */