at v4.8 141 lines 3.4 kB view raw
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 */ 16extern const unsigned int sys_call_table[]; 17 18/* The system call number is given by the user in %g1 */ 19static 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 27static 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 40static inline bool syscall_has_error(struct pt_regs *regs) 41{ 42 return (regs->psr & PSR_C) ? true : false; 43} 44static inline void syscall_set_error(struct pt_regs *regs) 45{ 46 regs->psr |= PSR_C; 47} 48static inline void syscall_clear_error(struct pt_regs *regs) 49{ 50 regs->psr &= ~PSR_C; 51} 52#else 53static inline bool syscall_has_error(struct pt_regs *regs) 54{ 55 return (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)) ? true : false; 56} 57static inline void syscall_set_error(struct pt_regs *regs) 58{ 59 regs->tstate |= (TSTATE_XCARRY | TSTATE_ICARRY); 60} 61static inline void syscall_clear_error(struct pt_regs *regs) 62{ 63 regs->tstate &= ~(TSTATE_XCARRY | TSTATE_ICARRY); 64} 65#endif 66 67static 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 75static 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 83static 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 96static 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 119static 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 130static 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 */