1 #ifndef __ASM_SPARC_SYSCALL_H 2 #define __ASM_SPARC_SYSCALL_H 3 4 #include <uapi/linux/audit.h> 5 #include <linux/kernel.h> 6 #include <linux/sched.h> 7 #include <asm/ptrace.h> 8 #include <asm/thread_info.h> 9 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 17 /* The system call number is given by the user in %g1 */ 18 static inline long syscall_get_nr(struct task_struct *task, 19 struct pt_regs *regs) 20 { 21 int syscall_p = pt_regs_is_syscall(regs); 22 23 return (syscall_p ? regs->u_regs[UREG_G1] : -1L); 24 } 25 26 static inline void syscall_rollback(struct task_struct *task, 27 struct pt_regs *regs) 28 { 29 /* XXX This needs some thought. On Sparc we don't 30 * XXX save away the original %o0 value somewhere. 31 * XXX Instead we hold it in register %l5 at the top 32 * XXX level trap frame and pass this down to the signal 33 * XXX dispatch code which is the only place that value 34 * XXX ever was needed. 35 */ 36 } 37 38 #ifdef CONFIG_SPARC32 39 static inline bool syscall_has_error(struct pt_regs *regs) 40 { 41 return (regs->psr & PSR_C) ? true : false; 42 } 43 static inline void syscall_set_error(struct pt_regs *regs) 44 { 45 regs->psr |= PSR_C; 46 } 47 static inline void syscall_clear_error(struct pt_regs *regs) 48 { 49 regs->psr &= ~PSR_C; 50 } 51 #else 52 static inline bool syscall_has_error(struct pt_regs *regs) 53 { 54 return (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)) ? true : false; 55 } 56 static inline void syscall_set_error(struct pt_regs *regs) 57 { 58 regs->tstate |= (TSTATE_XCARRY | TSTATE_ICARRY); 59 } 60 static inline void syscall_clear_error(struct pt_regs *regs) 61 { 62 regs->tstate &= ~(TSTATE_XCARRY | TSTATE_ICARRY); 63 } 64 #endif 65 66 static inline long syscall_get_error(struct task_struct *task, 67 struct pt_regs *regs) 68 { 69 long val = regs->u_regs[UREG_I0]; 70 71 return (syscall_has_error(regs) ? -val : 0); 72 } 73 74 static inline long syscall_get_return_value(struct task_struct *task, 75 struct pt_regs *regs) 76 { 77 long val = regs->u_regs[UREG_I0]; 78 79 return val; 80 } 81 82 static inline void syscall_set_return_value(struct task_struct *task, 83 struct pt_regs *regs, 84 int error, long val) 85 { 86 if (error) { 87 syscall_set_error(regs); 88 regs->u_regs[UREG_I0] = -error; 89 } else { 90 syscall_clear_error(regs); 91 regs->u_regs[UREG_I0] = val; 92 } 93 } 94 95 static inline void syscall_get_arguments(struct task_struct *task, 96 struct pt_regs *regs, 97 unsigned int i, unsigned int n, 98 unsigned long *args) 99 { 100 int zero_extend = 0; 101 unsigned int j; 102 103 #ifdef CONFIG_SPARC64 104 if (test_tsk_thread_flag(task, TIF_32BIT)) 105 zero_extend = 1; 106 #endif 107 108 for (j = 0; j < n; j++) { 109 unsigned long val = regs->u_regs[UREG_I0 + i + j]; 110 111 if (zero_extend) 112 args[j] = (u32) val; 113 else 114 args[j] = val; 115 } 116 } 117 118 static inline void syscall_set_arguments(struct task_struct *task, 119 struct pt_regs *regs, 120 unsigned int i, unsigned int n, 121 const unsigned long *args) 122 { 123 unsigned int j; 124 125 for (j = 0; j < n; j++) 126 regs->u_regs[UREG_I0 + i + j] = args[j]; 127 } 128 129 static inline int syscall_get_arch(void) 130 { 131 return is_32bit_task() ? AUDIT_ARCH_SPARC : AUDIT_ARCH_SPARC64; 132 } 133 134 #endif /* __ASM_SPARC_SYSCALL_H */ 135