syscall.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved.
  3. // Copyright (C) 2005-2017 Andes Technology Corporation
  4. #ifndef _ASM_NDS32_SYSCALL_H
  5. #define _ASM_NDS32_SYSCALL_H 1
  6. #include <linux/err.h>
  7. struct task_struct;
  8. struct pt_regs;
  9. /**
  10. * syscall_get_nr - find what system call a task is executing
  11. * @task: task of interest, must be blocked
  12. * @regs: task_pt_regs() of @task
  13. *
  14. * If @task is executing a system call or is at system call
  15. * tracing about to attempt one, returns the system call number.
  16. * If @task is not executing a system call, i.e. it's blocked
  17. * inside the kernel for a fault or signal, returns -1.
  18. *
  19. * Note this returns int even on 64-bit machines. Only 32 bits of
  20. * system call number can be meaningful. If the actual arch value
  21. * is 64 bits, this truncates to 32 bits so 0xffffffff means -1.
  22. *
  23. * It's only valid to call this when @task is known to be blocked.
  24. */
  25. int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
  26. {
  27. return regs->syscallno;
  28. }
  29. /**
  30. * syscall_rollback - roll back registers after an aborted system call
  31. * @task: task of interest, must be in system call exit tracing
  32. * @regs: task_pt_regs() of @task
  33. *
  34. * It's only valid to call this when @task is stopped for system
  35. * call exit tracing (due to TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT),
  36. * after tracehook_report_syscall_entry() returned nonzero to prevent
  37. * the system call from taking place.
  38. *
  39. * This rolls back the register state in @regs so it's as if the
  40. * system call instruction was a no-op. The registers containing
  41. * the system call number and arguments are as they were before the
  42. * system call instruction. This may not be the same as what the
  43. * register state looked like at system call entry tracing.
  44. */
  45. void syscall_rollback(struct task_struct *task, struct pt_regs *regs)
  46. {
  47. regs->uregs[0] = regs->orig_r0;
  48. }
  49. /**
  50. * syscall_get_error - check result of traced system call
  51. * @task: task of interest, must be blocked
  52. * @regs: task_pt_regs() of @task
  53. *
  54. * Returns 0 if the system call succeeded, or -ERRORCODE if it failed.
  55. *
  56. * It's only valid to call this when @task is stopped for tracing on exit
  57. * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
  58. */
  59. long syscall_get_error(struct task_struct *task, struct pt_regs *regs)
  60. {
  61. unsigned long error = regs->uregs[0];
  62. return IS_ERR_VALUE(error) ? error : 0;
  63. }
  64. /**
  65. * syscall_get_return_value - get the return value of a traced system call
  66. * @task: task of interest, must be blocked
  67. * @regs: task_pt_regs() of @task
  68. *
  69. * Returns the return value of the successful system call.
  70. * This value is meaningless if syscall_get_error() returned nonzero.
  71. *
  72. * It's only valid to call this when @task is stopped for tracing on exit
  73. * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
  74. */
  75. long syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
  76. {
  77. return regs->uregs[0];
  78. }
  79. /**
  80. * syscall_set_return_value - change the return value of a traced system call
  81. * @task: task of interest, must be blocked
  82. * @regs: task_pt_regs() of @task
  83. * @error: negative error code, or zero to indicate success
  84. * @val: user return value if @error is zero
  85. *
  86. * This changes the results of the system call that user mode will see.
  87. * If @error is zero, the user sees a successful system call with a
  88. * return value of @val. If @error is nonzero, it's a negated errno
  89. * code; the user sees a failed system call with this errno code.
  90. *
  91. * It's only valid to call this when @task is stopped for tracing on exit
  92. * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
  93. */
  94. void syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
  95. int error, long val)
  96. {
  97. regs->uregs[0] = (long)error ? error : val;
  98. }
  99. /**
  100. * syscall_get_arguments - extract system call parameter values
  101. * @task: task of interest, must be blocked
  102. * @regs: task_pt_regs() of @task
  103. * @i: argument index [0,5]
  104. * @n: number of arguments; n+i must be [1,6].
  105. * @args: array filled with argument values
  106. *
  107. * Fetches @n arguments to the system call starting with the @i'th argument
  108. * (from 0 through 5). Argument @i is stored in @args[0], and so on.
  109. * An arch inline version is probably optimal when @i and @n are constants.
  110. *
  111. * It's only valid to call this when @task is stopped for tracing on
  112. * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
  113. * It's invalid to call this with @i + @n > 6; we only support system calls
  114. * taking up to 6 arguments.
  115. */
  116. #define SYSCALL_MAX_ARGS 6
  117. void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
  118. unsigned int i, unsigned int n, unsigned long *args)
  119. {
  120. if (n == 0)
  121. return;
  122. if (i + n > SYSCALL_MAX_ARGS) {
  123. unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i;
  124. unsigned int n_bad = n + i - SYSCALL_MAX_ARGS;
  125. pr_warning("%s called with max args %d, handling only %d\n",
  126. __func__, i + n, SYSCALL_MAX_ARGS);
  127. memset(args_bad, 0, n_bad * sizeof(args[0]));
  128. memset(args_bad, 0, n_bad * sizeof(args[0]));
  129. }
  130. if (i == 0) {
  131. args[0] = regs->orig_r0;
  132. args++;
  133. i++;
  134. n--;
  135. }
  136. memcpy(args, &regs->uregs[0] + i, n * sizeof(args[0]));
  137. }
  138. /**
  139. * syscall_set_arguments - change system call parameter value
  140. * @task: task of interest, must be in system call entry tracing
  141. * @regs: task_pt_regs() of @task
  142. * @i: argument index [0,5]
  143. * @n: number of arguments; n+i must be [1,6].
  144. * @args: array of argument values to store
  145. *
  146. * Changes @n arguments to the system call starting with the @i'th argument.
  147. * Argument @i gets value @args[0], and so on.
  148. * An arch inline version is probably optimal when @i and @n are constants.
  149. *
  150. * It's only valid to call this when @task is stopped for tracing on
  151. * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
  152. * It's invalid to call this with @i + @n > 6; we only support system calls
  153. * taking up to 6 arguments.
  154. */
  155. void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
  156. unsigned int i, unsigned int n,
  157. const unsigned long *args)
  158. {
  159. if (n == 0)
  160. return;
  161. if (i + n > SYSCALL_MAX_ARGS) {
  162. pr_warn("%s called with max args %d, handling only %d\n",
  163. __func__, i + n, SYSCALL_MAX_ARGS);
  164. n = SYSCALL_MAX_ARGS - i;
  165. }
  166. if (i == 0) {
  167. regs->orig_r0 = args[0];
  168. args++;
  169. i++;
  170. n--;
  171. }
  172. memcpy(&regs->uregs[0] + i, args, n * sizeof(args[0]));
  173. }
  174. #endif /* _ASM_NDS32_SYSCALL_H */