diff options
author | Max Filippov | 2018-11-09 15:45:53 -0800 |
---|---|---|
committer | Max Filippov | 2018-12-17 13:50:22 -0800 |
commit | 9f24f3c1067c8e4ffbbcd759180b422c9a761b1b (patch) | |
tree | f7986bc6fa89dc75069bf1286342188c42195bf3 | |
parent | 921534473a6bc2ff822f19c222970d213d2e0f76 (diff) |
xtensa: implement tracehook functions and enable HAVE_ARCH_TRACEHOOK
Implement syscall_get_nr, syscall_rollback, syscall_get_error,
syscall_{get,set}_return_value and syscall_{get,set}_arguments.
Select HAVE_ARCH_TRACEHOOK as Xtensa now has all support for that.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
-rw-r--r-- | arch/xtensa/Kconfig | 1 | ||||
-rw-r--r-- | arch/xtensa/include/asm/syscall.h | 80 |
2 files changed, 80 insertions, 1 deletions
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index d29b7365da8d..55d13b589ff3 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -18,6 +18,7 @@ config XTENSA select GENERIC_SCHED_CLOCK select GENERIC_STRNCPY_FROM_USER if KASAN select HAVE_ARCH_KASAN if MMU + select HAVE_ARCH_TRACEHOOK select HAVE_DEBUG_KMEMLEAK select HAVE_DMA_CONTIGUOUS select HAVE_EXIT_THREAD diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h index 6969956d3f93..e47470ec8ea8 100644 --- a/arch/xtensa/include/asm/syscall.h +++ b/arch/xtensa/include/asm/syscall.h @@ -10,6 +10,8 @@ #ifndef _ASM_SYSCALL_H #define _ASM_SYSCALL_H +#include <linux/err.h> +#include <asm/ptrace.h> #include <uapi/linux/audit.h> static inline int syscall_get_arch(void) @@ -17,7 +19,83 @@ static inline int syscall_get_arch(void) return AUDIT_ARCH_XTENSA; } -struct pt_regs; +static inline long syscall_get_nr(struct task_struct *task, + struct pt_regs *regs) +{ + return regs->syscall; +} + +static inline void syscall_rollback(struct task_struct *task, + struct pt_regs *regs) +{ + /* Do nothing. */ +} + +static inline long syscall_get_error(struct task_struct *task, + struct pt_regs *regs) +{ + /* 0 if syscall succeeded, otherwise -Errorcode */ + return IS_ERR_VALUE(regs->areg[2]) ? regs->areg[2] : 0; +} + +static inline long syscall_get_return_value(struct task_struct *task, + struct pt_regs *regs) +{ + return regs->areg[2]; +} + +static inline void syscall_set_return_value(struct task_struct *task, + struct pt_regs *regs, + int error, long val) +{ + regs->areg[0] = (long) error ? error : val; +} + +#define SYSCALL_MAX_ARGS 6 +#define XTENSA_SYSCALL_ARGUMENT_REGS {6, 3, 4, 5, 8, 9} + +static inline void syscall_get_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + unsigned long *args) +{ + static const unsigned int reg[] = XTENSA_SYSCALL_ARGUMENT_REGS; + unsigned int j; + + if (n == 0) + return; + + WARN_ON_ONCE(i + n > SYSCALL_MAX_ARGS); + + for (j = 0; j < n; ++j) { + if (i + j < SYSCALL_MAX_ARGS) + args[j] = regs->areg[reg[i + j]]; + else + args[j] = 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) +{ + static const unsigned int reg[] = XTENSA_SYSCALL_ARGUMENT_REGS; + unsigned int j; + + if (n == 0) + return; + + if (WARN_ON_ONCE(i + n > SYSCALL_MAX_ARGS)) { + if (i < SYSCALL_MAX_ARGS) + n = SYSCALL_MAX_ARGS - i; + else + return; + } + + for (j = 0; j < n; ++j) + regs->areg[reg[i + j]] = args[j]; +} asmlinkage long xtensa_rt_sigreturn(struct pt_regs*); asmlinkage long xtensa_shmat(int, char __user *, int); |