Received: by 10.223.164.202 with SMTP id h10csp1599336wrb; Mon, 27 Nov 2017 05:04:13 -0800 (PST) X-Google-Smtp-Source: AGs4zMYfEp7sNxeDp8BuMXUEz7GS04uBiTv+UQhUBUtMtYPci/7yPchy1i3EmJfJAor59HWbjLgD X-Received: by 10.101.91.193 with SMTP id o1mr22845420pgr.373.1511787853324; Mon, 27 Nov 2017 05:04:13 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1511787853; cv=none; d=google.com; s=arc-20160816; b=FOFCCUPOAN2alf9DWC1qNIgx2aH8/M/2h8tEc3wyRTBllrrs6FLU4qibOwfzqTTNyx LpJ54BxAEgPVCDd487iC5Oit3aXS7/45bogr/cDZTfSGgNJHwO3GZHQZIvCKW8hw92st XnjAm5dG/anjEHKRJaEL7x/f5X6M1fs5ziaXjqChpM/fGu3TQBNTbL/EDZPFeBqcixoQ l/ZAwaqyP5r9EBkyBHIUMEb+f1LHVfugvuj7uHUXLlC6axaPRCa7Yl5i/J9vr3fbtacV Y3c66APrTl/vOpM9wP4NMoiLRHhRrkJKUnwCihBOP3rZmiSdo8uTkjkL4nuG1qx0+8cX tPSA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=ce26pBbsC9A+RQdNmLrmQGVtR1OQ+IMcPooH1ueRZjE=; b=B/n1wbyIMH31qxoAuHjJV9B8LUGg7EZ6UejG+imCmYlkuTJ0I8anZs+BqcvdonlxlZ G5MpvNy9+KhaebbxX/IQTEyIoyvJ3HXjdV6UUj+GyQEpcddJV2HgOnugNFSq91mMMXPM ACU77F6OeEqmc1oSCcjO0uLnJFBRdLJtkYmJCvRNHA5x+r910iqoenx/UVof9NKUgf2f LrvrAHU4Af8h1HNay7hqC3r15/l6hdWHKu/04Ea9NNbSm4SlmOMPhMHqpNMaYnba9gwe AAUG2vxRknBpTs+ZUQBmljg6oJklqsYskRmJ8Bdz1QOxpXrDj1rjxumQFzXTf16TszFn l14Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=uKAXJU84; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o4si22488972pgf.8.2017.11.27.05.04.01; Mon, 27 Nov 2017 05:04:13 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=uKAXJU84; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752584AbdK0Myd (ORCPT + 77 others); Mon, 27 Nov 2017 07:54:33 -0500 Received: from mail-pf0-f194.google.com ([209.85.192.194]:43368 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751873AbdK0My1 (ORCPT ); Mon, 27 Nov 2017 07:54:27 -0500 Received: by mail-pf0-f194.google.com with SMTP id r68so11177140pfe.10; Mon, 27 Nov 2017 04:54:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=ce26pBbsC9A+RQdNmLrmQGVtR1OQ+IMcPooH1ueRZjE=; b=uKAXJU84F0CV8+t50huw4k3SwwKWp/7F0A4XavzcmbG6haRkdr8CL/sN+MNGEZ16M/ Ak+mCvK5WucX0xzsMrcfNNCb4ydo2kCmMrJgQb9UUmAxclxbK5aVDYF0A/VWt8AeXFoD t7pSv7k++R23zQ6BsWpqp0iRPdy7lXlKmJrmT+J5FOPDaZNhiQtI+0DuKQYLZTDzL1L6 ejoA/8JKljCUvfeviZINdPR56m26pFJUI0XBz2AKzl3xC1j9eTmmc44Y3yTPoA5zmbvS 8GOWSWCkNn3T28eyj7crwJmh5FCHlHnsNrqYWhlx0SOfov+8MyyJcFqAmZQ1bbtrHoCc +x0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=ce26pBbsC9A+RQdNmLrmQGVtR1OQ+IMcPooH1ueRZjE=; b=uK/551XM3bOP9RXogLsoKk6AkVle/gCrAqdkdlnV5HdJFMexQe2RN1ETP2lZrwyFHO tFLbPeHCpBPV1jBIB4r5rSrcOZl4TgpoEnt6EOLnTX3y1Orp/pE+CxzPlMIWkae4YNtK ZMoHFKQvwFRkztQrUFd9CocS1LrsdqGzaEO0UQteumng6TxlUPYsMRJWQl/smy7BG562 uTq5KjGuJcJ3upSo+JenRUJ+GfpO2tWuBw2dTKlDeGeG1x6A7EpX+XNHQwz2m6yz51O7 pvOpAp3PMPFdFiIPmyYg7cXM66taV6f0c191eFhw1QhfXzBzXsIbRgaQXmngl//Z93o9 cyvg== X-Gm-Message-State: AJaThX4t7WxQ/cGUvM7r+zzbUQ+eAlxXWe8p8mm9XPnqJFjgj39FA+jJ hmFsoyzU7WskMrnKXYK8No8= X-Received: by 10.99.169.25 with SMTP id u25mr35859678pge.77.1511787266116; Mon, 27 Nov 2017 04:54:26 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id w64sm55225459pfj.62.2017.11.27.04.54.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 27 Nov 2017 04:54:25 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org, deanbo422@gmail.com, devicetree@vger.kernel.org, viro@zeniv.linux.org.uk, dhowells@redhat.com, will.deacon@arm.com, daniel.lezcano@linaro.org, linux-serial@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH v2 18/35] nds32: Debugging support Date: Mon, 27 Nov 2017 20:28:05 +0800 Message-Id: <01fc485408504e6a43b768664f44b9fd42a89503.1511785528.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Greentime Hu This patch adds ptrace support. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/uapi/asm/ptrace.h | 42 +++++ arch/nds32/kernel/ptrace.c | 325 ++++++++++++++++++++++++++++++++++ 2 files changed, 367 insertions(+) create mode 100644 arch/nds32/include/uapi/asm/ptrace.h create mode 100644 arch/nds32/kernel/ptrace.c diff --git a/arch/nds32/include/uapi/asm/ptrace.h b/arch/nds32/include/uapi/asm/ptrace.h new file mode 100644 index 0000000..20f9718 --- /dev/null +++ b/arch/nds32/include/uapi/asm/ptrace.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2005-2017 Andes Technology Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __UAPI_ASM_NDS32_PTRACE_H +#define __UAPI_ASM_NDS32_PTRACE_H + +#ifndef __ASSEMBLY__ + +/* + * User structures for general purpose register. + */ +struct user_pt_regs { + long uregs[26]; + long fp; + long gp; + long lp; + long sp; + long ipc; +#if defined(CONFIG_HWZOL) + long lb; + long le; + long lc; +#else + long dummy[3]; +#endif + long syscallno; +}; +#endif +#endif diff --git a/arch/nds32/kernel/ptrace.c b/arch/nds32/kernel/ptrace.c new file mode 100644 index 0000000..d91b3b8 --- /dev/null +++ b/arch/nds32/kernel/ptrace.c @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2005-2017 Andes Technology Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +enum nds32_regset { + REGSET_GPR, +}; + +static int gpr_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user * ubuf) +{ + struct user_pt_regs *uregs = &task_pt_regs(target)->user_regs; + return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1); +} + +static int gpr_set(struct task_struct *target, const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user * ubuf) +{ + int err; + struct user_pt_regs newregs = task_pt_regs(target)->user_regs; + + err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1); + if (err) + return err; + + task_pt_regs(target)->user_regs = newregs; + return 0; +} + +static const struct user_regset nds32_regsets[] = { + [REGSET_GPR] = { + .core_note_type = NT_PRSTATUS, + .n = sizeof(struct user_pt_regs) / sizeof(u32), + .size = sizeof(u32), + .align = sizeof(u32), + .get = gpr_get, + .set = gpr_set} +}; + +static const struct user_regset_view nds32_user_view = { + .name = "nds32",.e_machine = EM_NDS32, + .regsets = nds32_regsets,.n = ARRAY_SIZE(nds32_regsets) +}; + +const struct user_regset_view *task_user_regset_view(struct task_struct *task) +{ + return &nds32_user_view; +} + +/* get_user_reg() + * + * This routine will get a word off of the processes privileged stack. + * the offset is how far from the base addr as stored in the THREAD. + * this routine assumes that all the privileged stacks are in our + * data space. + */ +static inline unsigned int get_user_reg(struct task_struct *task, int offset) +{ + return task_pt_regs(task)->uregs[offset]; +} + +/* put_user_reg() + * + * this routine will put a word on the processes privileged stack. + * the offset is how far from the base addr as stored in the THREAD. + * this routine assumes that all the privileged stacks are in our + * data space. + */ +static inline int put_user_reg(struct task_struct *task, int offset, long data) +{ + struct pt_regs newregs, *regs = task_pt_regs(task); + int ret = -EINVAL; + + newregs = *regs; + newregs.uregs[offset] = data; + + if (valid_user_regs(&newregs)) { + regs->uregs[offset] = data; + ret = 0; + } + + return ret; +} + +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure the single step bit is not set. + */ +void ptrace_disable(struct task_struct *child) +{ + user_disable_single_step(child); +} + +static void fill_sigtrap_info(struct task_struct *tsk, + struct pt_regs *regs, + int error_code, int si_code, struct siginfo *info) +{ + tsk->thread.trap_no = ENTRY_DEBUG_RELATED; + tsk->thread.error_code = error_code; + + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = si_code; + info->si_addr = (void __user *)instruction_pointer(regs); +} + +void user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, struct siginfo *info) +{ + fill_sigtrap_info(tsk, regs, 0, TRAP_BRKPT, info); +} + +/* + * Handle hitting a breakpoint. + */ +void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, + int error_code, int si_code) +{ + struct siginfo info; + + fill_sigtrap_info(tsk, regs, error_code, TRAP_BRKPT, &info); + /* Send us the fake SIGTRAP */ + force_sig_info(SIGTRAP, &info, tsk); +} + +/* ptrace_read_user() + * + * Read the word at offset "off" into the "struct user". We + * actually access the pt_regs stored on the kernel stack. + */ +static int +ptrace_read_user(struct task_struct *tsk, unsigned long off, + unsigned long __user * ret) +{ + unsigned long tmp = 0; + + if (off < sizeof(struct pt_regs)) { + if (off & 3) + return -EIO; + tmp = get_user_reg(tsk, off >> 2); + return put_user(tmp, ret); + } else + return -EIO; +} + +/* ptrace_write_user() + * + * Write the word at offset "off" into "struct user". We + * actually access the pt_regs stored on the kernel stack. + */ +static int +ptrace_write_user(struct task_struct *tsk, unsigned long off, unsigned long val) +{ + if (off < sizeof(struct pt_regs)) { + if (off & 3) + return -EIO; + return put_user_reg(tsk, off >> 2, val); + } else + return -EIO; +} + +/* ptrace_getregs() + * + * Get all user integer registers. + */ +static int ptrace_getregs(struct task_struct *tsk, void __user * uregs) +{ + struct pt_regs *regs = task_pt_regs(tsk); + + return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0; +} + +/* ptrace_setregs() + * + * Set all user integer registers. + */ +static int ptrace_setregs(struct task_struct *tsk, void __user * uregs) +{ + struct pt_regs newregs; + int ret; + + ret = -EFAULT; + if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) { + struct pt_regs *regs = task_pt_regs(tsk); + + ret = -EINVAL; + if (valid_user_regs(&newregs)) { + *regs = newregs; + ret = 0; + } + } + + return ret; +} + +/* ptrace_getfpregs() + * + * Get the child FPU state. + */ +static int ptrace_getfpregs(struct task_struct *tsk, void __user * ufpregs) +{ + return -EFAULT; +} + +/* + * Set the child FPU state. + */ +static int ptrace_setfpregs(struct task_struct *tsk, void __user * ufpregs) +{ + return -EFAULT; +} + +/* do_ptrace() + * + * Provide ptrace defined service. + */ +long arch_ptrace(struct task_struct *child, long request, unsigned long addr, + unsigned long data) +{ + int ret; + + switch (request) { + case PTRACE_PEEKUSR: + ret = + ptrace_read_user(child, addr, (unsigned long __user *)data); + break; + + case PTRACE_POKEUSR: + ret = ptrace_write_user(child, addr, data); + break; + + case PTRACE_GETREGS: + ret = ptrace_getregs(child, (void __user *)data); + break; + + case PTRACE_SETREGS: + ret = ptrace_setregs(child, (void __user *)data); + break; + + case PTRACE_GETFPREGS: + ret = ptrace_getfpregs(child, (void __user *)data); + break; + + case PTRACE_SETFPREGS: + ret = ptrace_setfpregs(child, (void __user *)data); + break; + + default: + ret = ptrace_request(child, request, addr, data); + break; + } + + return ret; +} + +void user_enable_single_step(struct task_struct *child) +{ + struct pt_regs *regs; + regs = task_pt_regs(child); + regs->ipsw |= PSW_mskHSS; + set_tsk_thread_flag(child, TIF_SINGLESTEP); +} + +void user_disable_single_step(struct task_struct *child) +{ + struct pt_regs *regs; + regs = task_pt_regs(child); + regs->ipsw &= ~PSW_mskHSS; + clear_tsk_thread_flag(child, TIF_SINGLESTEP); +} + +/* sys_trace() + * + * syscall trace handler. + */ + +asmlinkage int syscall_trace_enter(int syscall, struct pt_regs *regs) +{ + if (test_thread_flag(TIF_SYSCALL_TRACE)) { + if (tracehook_report_syscall_entry(regs)) + return -1; + } + return syscall; +} + +asmlinkage void syscall_trace_leave(struct pt_regs *regs) +{ + int step = test_thread_flag(TIF_SINGLESTEP); + if (step || test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(regs, step); + +} -- 1.7.9.5 From 1585259026971785145@xxx Mon Nov 27 22:13:38 +0000 2017 X-GM-THRID: 1584466576386250796 X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread