diff options
author | David S. Miller <davem@davemloft.net> | 2008-07-27 11:53:10 +0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-28 04:31:48 +0400 |
commit | badcbf0e8654c4a4ca51fe46c75a70376e83c1ef (patch) | |
tree | 630b9fc4e0bfc277703a9413c80af5e112667e76 /arch/sparc | |
parent | 73ccefab8a6590bb3d5b44c046010139108ab7ca (diff) | |
download | linux-badcbf0e8654c4a4ca51fe46c75a70376e83c1ef.tar.xz |
sparc: Add asm/syscall.h
Based upon a patch by Roland McGrath.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/include/asm/syscall.h | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/arch/sparc/include/asm/syscall.h b/arch/sparc/include/asm/syscall.h new file mode 100644 index 000000000000..7486c605e23c --- /dev/null +++ b/arch/sparc/include/asm/syscall.h @@ -0,0 +1,120 @@ +#ifndef __ASM_SPARC_SYSCALL_H +#define __ASM_SPARC_SYSCALL_H + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <asm/ptrace.h> + +/* The system call number is given by the user in %g1 */ +static inline long syscall_get_nr(struct task_struct *task, + struct pt_regs *regs) +{ + int syscall_p = pt_regs_is_syscall(regs); + + return (syscall_p ? regs->u_regs[UREG_G1] : -1L); +} + +static inline void syscall_rollback(struct task_struct *task, + struct pt_regs *regs) +{ + /* XXX This needs some thought. On Sparc we don't + * XXX save away the original %o0 value somewhere. + * XXX Instead we hold it in register %l5 at the top + * XXX level trap frame and pass this down to the signal + * XXX dispatch code which is the only place that value + * XXX ever was needed. + */ +} + +#ifdef CONFIG_SPARC32 +static inline bool syscall_has_error(struct pt_regs *regs) +{ + return (regs->psr & PSR_C) ? true : false; +} +static inline void syscall_set_error(struct pt_regs *regs) +{ + regs->psr |= PSR_C; +} +static inline void syscall_clear_error(struct pt_regs *regs) +{ + regs->psr &= ~PSR_C; +} +#else +static inline bool syscall_has_error(struct pt_regs *regs) +{ + return (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)) ? true : false; +} +static inline void syscall_set_error(struct pt_regs *regs) +{ + regs->tstate |= (TSTATE_XCARRY | TSTATE_ICARRY); +} +static inline void syscall_clear_error(struct pt_regs *regs) +{ + regs->tstate &= ~(TSTATE_XCARRY | TSTATE_ICARRY); +} +#endif + +static inline long syscall_get_error(struct task_struct *task, + struct pt_regs *regs) +{ + long val = regs->u_regs[UREG_I0]; + + return (syscall_has_error(regs) ? -val : 0); +} + +static inline long syscall_get_return_value(struct task_struct *task, + struct pt_regs *regs) +{ + long val = regs->u_regs[UREG_I0]; + + return val; +} + +static inline void syscall_set_return_value(struct task_struct *task, + struct pt_regs *regs, + int error, long val) +{ + if (error) { + syscall_set_error(regs); + regs->u_regs[UREG_I0] = -error; + } else { + syscall_clear_error(regs); + regs->u_regs[UREG_I0] = val; + } +} + +static inline void syscall_get_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + unsigned long *args) +{ + int zero_extend = 0; + unsigned int j; + +#ifdef CONFIG_SPARC64 + if (test_tsk_thread_flag(task, TIF_32BIT)) + zero_extend = 1; +#endif + + for (j = 0; j < n; j++) { + unsigned long val = regs->u_regs[UREG_I0 + i + j]; + + if (zero_extend) + args[j] = (u32) val; + else + args[j] = val; + } +} + +static inline void syscall_set_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + const unsigned long *args) +{ + unsigned int j; + + for (j = 0; j < n; j++) + regs->u_regs[UREG_I0 + i + j] = args[j]; +} + +#endif /* __ASM_SPARC_SYSCALL_H */ |