diff options
author | Wade Farnsworth <wade_farnsworth@mentor.com> | 2012-04-04 16:19:02 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-04-25 19:49:27 +0100 |
commit | bf2c9f9866928df60157bc4f1ab39f93a32c754e (patch) | |
tree | 791a1ebb200ca690ae472a150859aeabdddeffcd | |
parent | 58834eecdeaab191b7c07a5eba8fdf9b637156e8 (diff) | |
download | lwn-bf2c9f9866928df60157bc4f1ab39f93a32c754e.tar.gz lwn-bf2c9f9866928df60157bc4f1ab39f93a32c754e.zip |
ARM: 7373/1: add support for the generic syscall.h interface
Supplying the asm-generic/syscall.h interface is a
pre-requisite for HAVE_ARCH_TRACEHOOK
Signed-off-by: Steven Walter <stevenrwalter@gmail.com>
Signed-off-by: Wade Farnsworth <wade_farnsworth@mentor.com>
Reviewed-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/include/asm/syscall.h | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/arch/arm/include/asm/syscall.h b/arch/arm/include/asm/syscall.h new file mode 100644 index 000000000000..c334a23ddf75 --- /dev/null +++ b/arch/arm/include/asm/syscall.h @@ -0,0 +1,93 @@ +/* + * Access to user system call parameters and results + * + * See asm-generic/syscall.h for descriptions of what we must do here. + */ + +#ifndef _ASM_ARM_SYSCALL_H +#define _ASM_ARM_SYSCALL_H + +#include <linux/err.h> + +extern const unsigned long sys_call_table[]; + +static inline int syscall_get_nr(struct task_struct *task, + struct pt_regs *regs) +{ + return task_thread_info(task)->syscall; +} + +static inline void syscall_rollback(struct task_struct *task, + struct pt_regs *regs) +{ + regs->ARM_r0 = regs->ARM_ORIG_r0; +} + +static inline long syscall_get_error(struct task_struct *task, + struct pt_regs *regs) +{ + unsigned long error = regs->ARM_r0; + return IS_ERR_VALUE(error) ? error : 0; +} + +static inline long syscall_get_return_value(struct task_struct *task, + struct pt_regs *regs) +{ + return regs->ARM_r0; +} + +static inline void syscall_set_return_value(struct task_struct *task, + struct pt_regs *regs, + int error, long val) +{ + regs->ARM_r0 = (long) error ? error : val; +} + +#define SYSCALL_MAX_ARGS 7 + +static inline void syscall_get_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + unsigned long *args) +{ + if (i + n > SYSCALL_MAX_ARGS) { + unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i; + unsigned int n_bad = n + i - SYSCALL_MAX_ARGS; + pr_warning("%s called with max args %d, handling only %d\n", + __func__, i + n, SYSCALL_MAX_ARGS); + memset(args_bad, 0, n_bad * sizeof(args[0])); + n = SYSCALL_MAX_ARGS - i; + } + + if (i == 0) { + args[0] = regs->ARM_ORIG_r0; + args++; + i++; + n--; + } + + memcpy(args, ®s->ARM_r0 + i, n * sizeof(args[0])); +} + +static inline void syscall_set_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + const unsigned long *args) +{ + if (i + n > SYSCALL_MAX_ARGS) { + pr_warning("%s called with max args %d, handling only %d\n", + __func__, i + n, SYSCALL_MAX_ARGS); + n = SYSCALL_MAX_ARGS - i; + } + + if (i == 0) { + regs->ARM_ORIG_r0 = args[0]; + args++; + i++; + n--; + } + + memcpy(®s->ARM_r0 + i, args, n * sizeof(args[0])); +} + +#endif /* _ASM_ARM_SYSCALL_H */ |