From patchwork Wed Feb 8 10:08:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qing Zhang X-Patchwork-Id: 54331 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp3369058wrn; Wed, 8 Feb 2023 02:11:51 -0800 (PST) X-Google-Smtp-Source: AK7set8VE+W2nTtwvWeZKiKRzoiQp9qKSKoRfrNdq6tFBpsG8p0MO/0sAZ9a0GW4EwFRi9vBCA+/ X-Received: by 2002:a17:906:1d2:b0:893:526b:c77b with SMTP id 18-20020a17090601d200b00893526bc77bmr6927866ejj.7.1675851111797; Wed, 08 Feb 2023 02:11:51 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1675851111; cv=none; d=google.com; s=arc-20160816; b=MhLBSYFlq/2q0XIq9s3IhHMdlRyfukY9N6kTjJtvmqBcrMsDcM3twsxkKB/dylPZ9k 5plAK8TjW6mAWoYKa8yopHI9PcAy2s5+ydqViabelAn7zb+sknvyJDG7LWMieKK6kKVy 6pbVBOQU1JxtVadnNvQfq2+lXAz3OUhGvC2dB4SJzNWq7hnn8Dm5SxTkNUY58vBsTuWZ dniWj/b86w3jg5/U9r4QSNzYcOI6vPMTCI6g+wHWshWK7QdAFRBTubMpFg1GSQN05UvX amTxkhg7BEFTAyqS/KErF0/vrGFnweHykC+WtEFM9ImVnNKCdTm8LuCVJQ3RzN/nEpAz q++Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=frWskjYI8JJdrzytwAIAtJscLy5fgOWzKs6LgKkwfzw=; b=diDMYZ/1cIpr9eJuzOSXWUoEwpOBbmkuKNWpN4HXpM3VpcnypUuvK+yZwkrItkQKMV PdrQiodJlJD8eY8R4/Ef43UAnxdNBq35bXZOp6r8/Hw04YYtRigHFdNnnnyjWIQaMB/Z xILQAx7FADVIXcZtIqT7YOZhBh9m83tCPTnCKzoL4PmKNI8R+4nSGjL10HPatJ2nbZTu hcw5EHzo/+h6Gpt7UUHAyUYKK2p8stI++izSEs3Q8Z78/MuGFyS/uNEomEoR+GjDoGJi JDyBDKFvaE+Gnr5KrBCvDBTmBI01e0lfqCmxSWogEgO44y2DPNTsda96c5VH7qGqCs3Y hdUA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id f11-20020a056402354b00b0048c1bb5d23bsi24995528edd.67.2023.02.08.02.11.28; Wed, 08 Feb 2023 02:11:51 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229797AbjBHKIp (ORCPT + 99 others); Wed, 8 Feb 2023 05:08:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49966 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229515AbjBHKIm (ORCPT ); Wed, 8 Feb 2023 05:08:42 -0500 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 7F55E125AA for ; Wed, 8 Feb 2023 02:08:40 -0800 (PST) Received: from loongson.cn (unknown [113.200.148.30]) by gateway (Coremail) with SMTP id _____8DxTuundONjzOwPAA--.31599S3; Wed, 08 Feb 2023 18:08:39 +0800 (CST) Received: from localhost.localdomain (unknown [113.200.148.30]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxtOWldONjv1gtAA--.52925S4; Wed, 08 Feb 2023 18:08:39 +0800 (CST) From: Qing Zhang To: Huacai Chen , Oleg Nesterov , WANG Xuerui Cc: Jiaxun Yang , loongarch@lists.linux.dev, linux-kernel@vger.kernel.org Subject: [PATCH 2/2] LoongArch: Add ptrace single step support Date: Wed, 8 Feb 2023 18:08:37 +0800 Message-Id: <20230208100837.2451-3-zhangqing@loongson.cn> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20230208100837.2451-1-zhangqing@loongson.cn> References: <20230208100837.2451-1-zhangqing@loongson.cn> MIME-Version: 1.0 X-CM-TRANSID: AQAAf8BxtOWldONjv1gtAA--.52925S4 X-CM-SenderInfo: x2kd0wptlqwqxorr0wxvrqhubq/ X-Coremail-Antispam: 1Uk129KBjvJXoWxKrykGw4UWFyrtw4rAr4kCrg_yoW7tFW5pF 9rCrn5GrW5GF1kWFnIy3Z8ZrnxJw4kW3y2ga4IyaySyw17tr4rXr1kCr1qvF45A3yUWa4S grZ8KF4SgFs8Zw7anT9S1TB71UUUUjUqnTZGkaVYY2UrUUUUj1kv1TuYvTs0mT0YCTnIWj qI5I8CrVACY4xI64kE6c02F40Ex7xfYxn0WfASr-VFAUDa7-sFnT9fnUUIcSsGvfJTRUUU b3kYFVCjjxCrM7AC8VAFwI0_Jr0_Gr1l1xkIjI8I6I8E6xAIw20EY4v20xvaj40_Wr0E3s 1l1IIY67AEw4v_JF0_JFyl8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxSw2x7M28EF7xv wVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwA2z4 x0Y4vEx4A2jsIE14v26r4UJVWxJr1l84ACjcxK6I8E87Iv6xkF7I0E14v26F4UJVW0owAa w2AFwI0_Jrv_JF1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqjxCEc2xF0cIa020Ex4CE44 I27wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI8IcVAFwI0_Jw0_WrylYx0Ex4A2 jsIE14v26r4j6F4UMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwCF04k20x vY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwCFI7km07C267AKxVWUXVWUAwC20s02 6c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_JF 0_Jw1lIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvE c7CjxVAFwI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14 v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x 07jrPEfUUUUU= X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_PASS, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1757257255022576312?= X-GMAIL-MSGID: =?utf-8?q?1757257255022576312?= Use the generic ptrace_resume code for PTRACE_SYSCALL, PTRACE_CONT, PTRACE_KILL and PTRACE_SINGLESTEP. This implies defining arch_has_single_step in and implementing the user_enable_single_step and user_disable_single_step functions. LongArch has no hardware single-step register. the hardware single-step function multiplex fetch instruction watchpoint(FWPS) and specifies that the next instruction must trigger the watch exception by setting the mask bit. Signed-off-by: Qing Zhang --- arch/loongarch/include/asm/ptrace.h | 2 + arch/loongarch/kernel/hw_breakpoint.c | 13 ++++- arch/loongarch/kernel/ptrace.c | 68 +++++++++++++++++++++++++++ arch/loongarch/kernel/traps.c | 27 +++++++++-- 4 files changed, 103 insertions(+), 7 deletions(-) diff --git a/arch/loongarch/include/asm/ptrace.h b/arch/loongarch/include/asm/ptrace.h index 58596c4f8a0f..66a0e6c480a3 100644 --- a/arch/loongarch/include/asm/ptrace.h +++ b/arch/loongarch/include/asm/ptrace.h @@ -150,4 +150,6 @@ static inline void user_stack_pointer_set(struct pt_regs *regs, regs->regs[3] = val; } +#define arch_has_single_step() (1) + #endif /* _ASM_PTRACE_H */ diff --git a/arch/loongarch/kernel/hw_breakpoint.c b/arch/loongarch/kernel/hw_breakpoint.c index 4ba1e730f3e9..bcecc076b420 100644 --- a/arch/loongarch/kernel/hw_breakpoint.c +++ b/arch/loongarch/kernel/hw_breakpoint.c @@ -497,9 +497,18 @@ arch_initcall(arch_hw_breakpoint_init); void hw_breakpoint_thread_switch(struct task_struct *next) { struct pt_regs *regs = task_pt_regs(next); + u64 addr, mask; - /* Update breakpoints/watchpoints. */ - update_bp_registers(regs, 1); + if (test_bit(TIF_SINGLESTEP, &task_thread_info(next)->flags)) { + addr = read_wb_reg(CSR_CFG_ADDR, 0, 0); + mask = read_wb_reg(CSR_CFG_MASK, 0, 0); + if ((task_pt_regs(next)->csr_era & ~mask) == (addr & ~mask)) + csr_write32(0x10000, LOONGARCH_CSR_FWPS); + regs->csr_prmd |= CSR_PRMD_PWE; + } else { + /* Update breakpoints/watchpoints. */ + update_bp_registers(regs, 1); + } } void hw_breakpoint_pmu_read(struct perf_event *bp) diff --git a/arch/loongarch/kernel/ptrace.c b/arch/loongarch/kernel/ptrace.c index bee4194177fd..52a3ee4366f4 100644 --- a/arch/loongarch/kernel/ptrace.c +++ b/arch/loongarch/kernel/ptrace.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,7 @@ #include #include #include +#include #include #include @@ -39,6 +41,7 @@ #include #include #include +#include #include #include @@ -541,3 +544,68 @@ long arch_ptrace(struct task_struct *child, long request, return ret; } + +void ptrace_triggered(struct perf_event *bp, + struct perf_sample_data *data, struct pt_regs *regs) +{ + struct perf_event_attr attr; + + attr = bp->attr; + attr.disabled = true; + modify_user_hw_breakpoint(bp, &attr); +} + +static int set_single_step(struct task_struct *tsk, unsigned long addr) +{ + struct thread_struct *thread = &tsk->thread; + struct perf_event *bp; + struct perf_event_attr attr; + struct arch_hw_breakpoint *info; + + bp = thread->hbp_break[0]; + if (!bp) { + ptrace_breakpoint_init(&attr); + + attr.bp_addr = addr; + attr.bp_len = HW_BREAKPOINT_LEN_8; + attr.bp_type = HW_BREAKPOINT_X; + + bp = register_user_hw_breakpoint(&attr, ptrace_triggered, + NULL, tsk); + if (IS_ERR(bp)) + return PTR_ERR(bp); + + thread->hbp_break[0] = bp; + } else { + int err; + + attr = bp->attr; + attr.bp_addr = addr; + /* reenable breakpoint */ + attr.disabled = false; + err = modify_user_hw_breakpoint(bp, &attr); + if (unlikely(err)) + return err; + + csr_write64(attr.bp_addr, LOONGARCH_CSR_IB0ADDR); + } + info = counter_arch_bp(bp); + info->mask = 0xffffffffffff; + + return 0; +} + +/* ptrace API */ +void user_enable_single_step(struct task_struct *task) +{ + struct thread_info *ti = task_thread_info(task); + + set_single_step(task, task_pt_regs(task)->csr_era); + task->thread.single_step = task_pt_regs(task)->csr_era; + set_ti_thread_flag(ti, TIF_SINGLESTEP); +} + +void user_disable_single_step(struct task_struct *task) +{ + clear_tsk_thread_flag(task, TIF_SINGLESTEP); +} diff --git a/arch/loongarch/kernel/traps.c b/arch/loongarch/kernel/traps.c index 70085d83476d..0c4c6dcf9a4e 100644 --- a/arch/loongarch/kernel/traps.c +++ b/arch/loongarch/kernel/traps.c @@ -512,13 +512,30 @@ asmlinkage void noinstr do_watch(struct pt_regs *regs) prev_state = exception_enter(); + if (test_tsk_thread_flag(current, TIF_SINGLESTEP)) { + int llbit = (csr_read32(LOONGARCH_CSR_LLBCTL) & 0x1); + unsigned long pc = regs->csr_era; + + if (llbit) { + csr_write32(0x10000, LOONGARCH_CSR_FWPS); + csr_write32(0x4, LOONGARCH_CSR_LLBCTL); + } else if (pc == current->thread.single_step) { + csr_write32(0x10000, LOONGARCH_CSR_FWPS); + } else { + csr_write32(0x10000, LOONGARCH_CSR_FWPS); + pr_info("Single step in progress\n"); + force_sig(SIGTRAP); + } + } else { #ifdef CONFIG_HAVE_HW_BREAKPOINT - if (breakpoint_handler(regs)) - return; - if (watchpoint_handler(regs)) - return; + if (breakpoint_handler(regs)) + return; + if (watchpoint_handler(regs)) + return; + force_sig(SIGTRAP); #endif - force_sig(SIGTRAP); + } + exception_exit(prev_state); return; }