syscall.h 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (C) 2012 ARM Ltd.
  4. */
  5. #ifndef __ASM_SYSCALL_H
  6. #define __ASM_SYSCALL_H
  7. #include <uapi/linux/audit.h>
  8. #include <linux/compat.h>
  9. #include <linux/err.h>
  10. typedef long (*syscall_fn_t)(const struct pt_regs *regs);
  11. extern const syscall_fn_t sys_call_table[];
  12. #ifdef CONFIG_COMPAT
  13. extern const syscall_fn_t compat_sys_call_table[];
  14. #endif
  15. static inline int syscall_get_nr(struct task_struct *task,
  16. struct pt_regs *regs)
  17. {
  18. return regs->syscallno;
  19. }
  20. static inline void syscall_rollback(struct task_struct *task,
  21. struct pt_regs *regs)
  22. {
  23. regs->regs[0] = regs->orig_x0;
  24. }
  25. static inline long syscall_get_return_value(struct task_struct *task,
  26. struct pt_regs *regs)
  27. {
  28. unsigned long val = regs->regs[0];
  29. if (is_compat_thread(task_thread_info(task)))
  30. val = sign_extend64(val, 31);
  31. return val;
  32. }
  33. static inline long syscall_get_error(struct task_struct *task,
  34. struct pt_regs *regs)
  35. {
  36. unsigned long error = syscall_get_return_value(task, regs);
  37. return IS_ERR_VALUE(error) ? error : 0;
  38. }
  39. static inline void syscall_set_return_value(struct task_struct *task,
  40. struct pt_regs *regs,
  41. int error, long val)
  42. {
  43. if (error)
  44. val = error;
  45. if (is_compat_thread(task_thread_info(task)))
  46. val = lower_32_bits(val);
  47. regs->regs[0] = val;
  48. }
  49. #define SYSCALL_MAX_ARGS 6
  50. static inline void syscall_get_arguments(struct task_struct *task,
  51. struct pt_regs *regs,
  52. unsigned long *args)
  53. {
  54. args[0] = regs->orig_x0;
  55. args++;
  56. memcpy(args, &regs->regs[1], 5 * sizeof(args[0]));
  57. }
  58. /*
  59. * We don't care about endianness (__AUDIT_ARCH_LE bit) here because
  60. * AArch64 has the same system calls both on little- and big- endian.
  61. */
  62. static inline int syscall_get_arch(struct task_struct *task)
  63. {
  64. if (is_compat_thread(task_thread_info(task)))
  65. return AUDIT_ARCH_ARM;
  66. return AUDIT_ARCH_AARCH64;
  67. }
  68. #endif /* __ASM_SYSCALL_H */