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