diff options
Diffstat (limited to 'arch/metag/kernel/ptrace.c')
-rw-r--r-- | arch/metag/kernel/ptrace.c | 427 |
1 files changed, 0 insertions, 427 deletions
diff --git a/arch/metag/kernel/ptrace.c b/arch/metag/kernel/ptrace.c deleted file mode 100644 index e615603a4b0a..000000000000 --- a/arch/metag/kernel/ptrace.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Copyright (C) 2005-2012 Imagination Technologies Ltd. - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file COPYING in the main directory of - * this archive for more details. - */ - -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/errno.h> -#include <linux/ptrace.h> -#include <linux/user.h> -#include <linux/regset.h> -#include <linux/tracehook.h> -#include <linux/elf.h> -#include <linux/uaccess.h> -#include <linux/sched/task_stack.h> - -#include <trace/syscall.h> - -#define CREATE_TRACE_POINTS -#include <trace/events/syscalls.h> - -/* - * user_regset definitions. - */ - -static unsigned long user_txstatus(const struct pt_regs *regs) -{ - unsigned long data = (unsigned long)regs->ctx.Flags; - - if (regs->ctx.SaveMask & TBICTX_CBUF_BIT) - data |= USER_GP_REGS_STATUS_CATCH_BIT; - - return data; -} - -int metag_gp_regs_copyout(const struct pt_regs *regs, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - const void *ptr; - unsigned long data; - int ret; - - /* D{0-1}.{0-7} */ - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - regs->ctx.DX, 0, 4*16); - if (ret) - goto out; - /* A{0-1}.{0-1} */ - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - regs->ctx.AX, 4*16, 4*20); - if (ret) - goto out; - /* A{0-1}.2 */ - if (regs->ctx.SaveMask & TBICTX_XEXT_BIT) - ptr = regs->ctx.Ext.Ctx.pExt; - else - ptr = ®s->ctx.Ext.AX2; - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - ptr, 4*20, 4*22); - if (ret) - goto out; - /* A{0-1}.3 */ - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - ®s->ctx.AX3, 4*22, 4*24); - if (ret) - goto out; - /* PC */ - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - ®s->ctx.CurrPC, 4*24, 4*25); - if (ret) - goto out; - /* TXSTATUS */ - data = user_txstatus(regs); - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &data, 4*25, 4*26); - if (ret) - goto out; - /* TXRPT, TXBPOBITS, TXMODE */ - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - ®s->ctx.CurrRPT, 4*26, 4*29); - if (ret) - goto out; - /* Padding */ - ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, - 4*29, 4*30); -out: - return ret; -} - -int metag_gp_regs_copyin(struct pt_regs *regs, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - void *ptr; - unsigned long data; - int ret; - - /* D{0-1}.{0-7} */ - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - regs->ctx.DX, 0, 4*16); - if (ret) - goto out; - /* A{0-1}.{0-1} */ - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - regs->ctx.AX, 4*16, 4*20); - if (ret) - goto out; - /* A{0-1}.2 */ - if (regs->ctx.SaveMask & TBICTX_XEXT_BIT) - ptr = regs->ctx.Ext.Ctx.pExt; - else - ptr = ®s->ctx.Ext.AX2; - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - ptr, 4*20, 4*22); - if (ret) - goto out; - /* A{0-1}.3 */ - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - ®s->ctx.AX3, 4*22, 4*24); - if (ret) - goto out; - /* PC */ - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - ®s->ctx.CurrPC, 4*24, 4*25); - if (ret) - goto out; - /* TXSTATUS */ - data = user_txstatus(regs); - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - &data, 4*25, 4*26); - if (ret) - goto out; - regs->ctx.Flags = data & 0xffff; - if (data & USER_GP_REGS_STATUS_CATCH_BIT) - regs->ctx.SaveMask |= TBICTX_XCBF_BIT | TBICTX_CBUF_BIT; - else - regs->ctx.SaveMask &= ~TBICTX_CBUF_BIT; - /* TXRPT, TXBPOBITS, TXMODE */ - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - ®s->ctx.CurrRPT, 4*26, 4*29); -out: - return ret; -} - -static int metag_gp_regs_get(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - const struct pt_regs *regs = task_pt_regs(target); - return metag_gp_regs_copyout(regs, pos, count, kbuf, ubuf); -} - -static int metag_gp_regs_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - struct pt_regs *regs = task_pt_regs(target); - return metag_gp_regs_copyin(regs, pos, count, kbuf, ubuf); -} - -int metag_cb_regs_copyout(const struct pt_regs *regs, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - int ret; - - /* TXCATCH{0-3} */ - if (regs->ctx.SaveMask & TBICTX_XCBF_BIT) - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - regs->extcb0, 0, 4*4); - else - ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, - 0, 4*4); - return ret; -} - -int metag_cb_regs_copyin(struct pt_regs *regs, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - int ret; - - /* TXCATCH{0-3} */ - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - regs->extcb0, 0, 4*4); - return ret; -} - -static int metag_cb_regs_get(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - const struct pt_regs *regs = task_pt_regs(target); - return metag_cb_regs_copyout(regs, pos, count, kbuf, ubuf); -} - -static int metag_cb_regs_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - struct pt_regs *regs = task_pt_regs(target); - return metag_cb_regs_copyin(regs, pos, count, kbuf, ubuf); -} - -int metag_rp_state_copyout(const struct pt_regs *regs, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - unsigned long mask; - u64 *ptr; - int ret, i; - - /* Empty read pipeline */ - if (!(regs->ctx.SaveMask & TBICTX_CBRP_BIT)) { - ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, - 0, 4*13); - goto out; - } - - mask = (regs->ctx.CurrDIVTIME & TXDIVTIME_RPMASK_BITS) >> - TXDIVTIME_RPMASK_S; - - /* Read pipeline entries */ - ptr = (void *)®s->extcb0[1]; - for (i = 0; i < 6; ++i, ++ptr) { - if (mask & (1 << i)) - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - ptr, 8*i, 8*(i + 1)); - else - ret = user_regset_copyout_zero(&pos, &count, &kbuf, - &ubuf, 8*i, 8*(i + 1)); - if (ret) - goto out; - } - /* Mask of entries */ - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &mask, 4*12, 4*13); -out: - return ret; -} - -int metag_rp_state_copyin(struct pt_regs *regs, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - struct user_rp_state rp; - unsigned long long *ptr; - int ret, i; - - if (count < 4*13) - return -EINVAL; - /* Read the entire pipeline before making any changes */ - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - &rp, 0, 4*13); - if (ret) - goto out; - - /* Write pipeline entries */ - ptr = (void *)®s->extcb0[1]; - for (i = 0; i < 6; ++i, ++ptr) - if (rp.mask & (1 << i)) - *ptr = rp.entries[i]; - - /* Update RPMask in TXDIVTIME */ - regs->ctx.CurrDIVTIME &= ~TXDIVTIME_RPMASK_BITS; - regs->ctx.CurrDIVTIME |= (rp.mask << TXDIVTIME_RPMASK_S) - & TXDIVTIME_RPMASK_BITS; - - /* Set/clear flags to indicate catch/read pipeline state */ - if (rp.mask) - regs->ctx.SaveMask |= TBICTX_XCBF_BIT | TBICTX_CBRP_BIT; - else - regs->ctx.SaveMask &= ~TBICTX_CBRP_BIT; -out: - return ret; -} - -static int metag_rp_state_get(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - const struct pt_regs *regs = task_pt_regs(target); - return metag_rp_state_copyout(regs, pos, count, kbuf, ubuf); -} - -static int metag_rp_state_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - struct pt_regs *regs = task_pt_regs(target); - return metag_rp_state_copyin(regs, pos, count, kbuf, ubuf); -} - -static int metag_tls_get(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - void __user *tls = target->thread.tls_ptr; - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &tls, 0, -1); -} - -static int metag_tls_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - int ret; - void __user *tls = target->thread.tls_ptr; - - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1); - if (ret) - return ret; - - target->thread.tls_ptr = tls; - return ret; -} - -enum metag_regset { - REGSET_GENERAL, - REGSET_CBUF, - REGSET_READPIPE, - REGSET_TLS, -}; - -static const struct user_regset metag_regsets[] = { - [REGSET_GENERAL] = { - .core_note_type = NT_PRSTATUS, - .n = ELF_NGREG, - .size = sizeof(long), - .align = sizeof(long long), - .get = metag_gp_regs_get, - .set = metag_gp_regs_set, - }, - [REGSET_CBUF] = { - .core_note_type = NT_METAG_CBUF, - .n = sizeof(struct user_cb_regs) / sizeof(long), - .size = sizeof(long), - .align = sizeof(long long), - .get = metag_cb_regs_get, - .set = metag_cb_regs_set, - }, - [REGSET_READPIPE] = { - .core_note_type = NT_METAG_RPIPE, - .n = sizeof(struct user_rp_state) / sizeof(long), - .size = sizeof(long), - .align = sizeof(long long), - .get = metag_rp_state_get, - .set = metag_rp_state_set, - }, - [REGSET_TLS] = { - .core_note_type = NT_METAG_TLS, - .n = 1, - .size = sizeof(void *), - .align = sizeof(void *), - .get = metag_tls_get, - .set = metag_tls_set, - }, -}; - -static const struct user_regset_view user_metag_view = { - .name = "metag", - .e_machine = EM_METAG, - .regsets = metag_regsets, - .n = ARRAY_SIZE(metag_regsets) -}; - -const struct user_regset_view *task_user_regset_view(struct task_struct *task) -{ - return &user_metag_view; -} - -/* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure single step bits etc are not set. - */ -void ptrace_disable(struct task_struct *child) -{ - /* nothing to do.. */ -} - -long arch_ptrace(struct task_struct *child, long request, unsigned long addr, - unsigned long data) -{ - int ret; - - switch (request) { - default: - ret = ptrace_request(child, request, addr, data); - break; - } - - return ret; -} - -int syscall_trace_enter(struct pt_regs *regs) -{ - int ret = 0; - - if (test_thread_flag(TIF_SYSCALL_TRACE)) - ret = tracehook_report_syscall_entry(regs); - - if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) - trace_sys_enter(regs, regs->ctx.DX[0].U1); - - return ret ? -1 : regs->ctx.DX[0].U1; -} - -void syscall_trace_leave(struct pt_regs *regs) -{ - if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) - trace_sys_exit(regs, regs->ctx.DX[0].U1); - - if (test_thread_flag(TIF_SYSCALL_TRACE)) - tracehook_report_syscall_exit(regs, 0); -} |