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 */ 15extern const unsigned int sys_call_table[]; 16 17/* The system call number is given by the user in %g1 */ 18static 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 26static 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 39static inline bool syscall_has_error(struct pt_regs *regs) 40{ 41 return (regs->psr & PSR_C) ? true : false; 42} 43static inline void syscall_set_error(struct pt_regs *regs) 44{ 45 regs->psr |= PSR_C; 46} 47static inline void syscall_clear_error(struct pt_regs *regs) 48{ 49 regs->psr &= ~PSR_C; 50} 51#else 52static inline bool syscall_has_error(struct pt_regs *regs) 53{ 54 return (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)) ? true : false; 55} 56static inline void syscall_set_error(struct pt_regs *regs) 57{ 58 regs->tstate |= (TSTATE_XCARRY | TSTATE_ICARRY); 59} 60static inline void syscall_clear_error(struct pt_regs *regs) 61{ 62 regs->tstate &= ~(TSTATE_XCARRY | TSTATE_ICARRY); 63} 64#endif 65 66static 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 74static 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 82static 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 95static 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 118static 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 129static 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