syscall.h 4.5 KB

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