syscall.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __ASM_SPARC_SYSCALL_H
  3. #define __ASM_SPARC_SYSCALL_H
  4. #include <uapi/linux/audit.h>
  5. #include <linux/kernel.h>
  6. #include <linux/compat.h>
  7. #include <linux/sched.h>
  8. #include <asm/ptrace.h>
  9. #include <asm/thread_info.h>
  10. /*
  11. * The syscall table always contains 32 bit pointers since we know that the
  12. * address of the function to be called is (way) below 4GB. So the "int"
  13. * type here is what we want [need] for both 32 bit and 64 bit systems.
  14. */
  15. extern const unsigned int sys_call_table[];
  16. /* The system call number is given by the user in %g1 */
  17. static inline long syscall_get_nr(struct task_struct *task,
  18. struct pt_regs *regs)
  19. {
  20. int syscall_p = pt_regs_is_syscall(regs);
  21. return (syscall_p ? regs->u_regs[UREG_G1] : -1L);
  22. }
  23. static inline void syscall_rollback(struct task_struct *task,
  24. struct pt_regs *regs)
  25. {
  26. /* XXX This needs some thought. On Sparc we don't
  27. * XXX save away the original %o0 value somewhere.
  28. * XXX Instead we hold it in register %l5 at the top
  29. * XXX level trap frame and pass this down to the signal
  30. * XXX dispatch code which is the only place that value
  31. * XXX ever was needed.
  32. */
  33. }
  34. #ifdef CONFIG_SPARC32
  35. static inline bool syscall_has_error(struct pt_regs *regs)
  36. {
  37. return (regs->psr & PSR_C) ? true : false;
  38. }
  39. static inline void syscall_set_error(struct pt_regs *regs)
  40. {
  41. regs->psr |= PSR_C;
  42. }
  43. static inline void syscall_clear_error(struct pt_regs *regs)
  44. {
  45. regs->psr &= ~PSR_C;
  46. }
  47. #else
  48. static inline bool syscall_has_error(struct pt_regs *regs)
  49. {
  50. return (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)) ? true : false;
  51. }
  52. static inline void syscall_set_error(struct pt_regs *regs)
  53. {
  54. regs->tstate |= (TSTATE_XCARRY | TSTATE_ICARRY);
  55. }
  56. static inline void syscall_clear_error(struct pt_regs *regs)
  57. {
  58. regs->tstate &= ~(TSTATE_XCARRY | TSTATE_ICARRY);
  59. }
  60. #endif
  61. static inline long syscall_get_error(struct task_struct *task,
  62. struct pt_regs *regs)
  63. {
  64. long val = regs->u_regs[UREG_I0];
  65. return (syscall_has_error(regs) ? -val : 0);
  66. }
  67. static inline long syscall_get_return_value(struct task_struct *task,
  68. struct pt_regs *regs)
  69. {
  70. long val = regs->u_regs[UREG_I0];
  71. return val;
  72. }
  73. static inline void syscall_set_return_value(struct task_struct *task,
  74. struct pt_regs *regs,
  75. int error, long val)
  76. {
  77. if (error) {
  78. syscall_set_error(regs);
  79. regs->u_regs[UREG_I0] = -error;
  80. } else {
  81. syscall_clear_error(regs);
  82. regs->u_regs[UREG_I0] = val;
  83. }
  84. }
  85. static inline void syscall_get_arguments(struct task_struct *task,
  86. struct pt_regs *regs,
  87. unsigned long *args)
  88. {
  89. int zero_extend = 0;
  90. unsigned int j;
  91. unsigned int n = 6;
  92. #ifdef CONFIG_SPARC64
  93. if (test_tsk_thread_flag(task, TIF_32BIT))
  94. zero_extend = 1;
  95. #endif
  96. for (j = 0; j < n; j++) {
  97. unsigned long val = regs->u_regs[UREG_I0 + j];
  98. if (zero_extend)
  99. args[j] = (u32) val;
  100. else
  101. args[j] = val;
  102. }
  103. }
  104. static inline int syscall_get_arch(struct task_struct *task)
  105. {
  106. #if defined(CONFIG_SPARC64) && defined(CONFIG_COMPAT)
  107. return test_tsk_thread_flag(task, TIF_32BIT)
  108. ? AUDIT_ARCH_SPARC : AUDIT_ARCH_SPARC64;
  109. #elif defined(CONFIG_SPARC64)
  110. return AUDIT_ARCH_SPARC64;
  111. #else
  112. return AUDIT_ARCH_SPARC;
  113. #endif
  114. }
  115. #endif /* __ASM_SPARC_SYSCALL_H */