Received: by 2002:a25:1506:0:0:0:0:0 with SMTP id 6csp61011ybv; Wed, 12 Feb 2020 19:12:00 -0800 (PST) X-Google-Smtp-Source: APXvYqx2FaMA1c3OCAKhMvIG1Yjgs1Mup83K68iajohnlVdk5Gt1e6vHOn9l40hGg9cEpPx+PvZr X-Received: by 2002:a05:6808:611:: with SMTP id y17mr1511980oih.146.1581563520323; Wed, 12 Feb 2020 19:12:00 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1581563520; cv=none; d=google.com; s=arc-20160816; b=bwEcNlqNmTO0CxTO/s6gbDjXW5hR7rInGenqa7ZKLN4YOLg33Ci+YlqkyZNV/9BZD9 9a4tP6DJ9PxTU+0HA9LjKcb7BB1/HA9uc8BznNB6pJHCm4Pze075mmpN9arLrLE9YLGg i8ZSlt2rZ3FWsHPobMZYSUzK0j/WbKrortHqvhR9hG9LiRlQC6YdhE2Jjo54vhVdpvf4 sJrZVgnDFA3XjszNmhCZifFGryDhteNNXNGoBf+Xaq3KnKM5kDBKNhVqhr6QqHpRs79T x5hw/iHizw0uuhqCY0Keg6h1jRzknpMTlA4vayiBCJc+7PpmA4sPO26/Mg7p3APxvicv xpCA== 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:message-id:date :subject:cc:to:from:dkim-signature; bh=KJ1cbKxSOkkJkYmSO9MG9FaSPDVN9iwyOwbghCa/jtg=; b=H47v1XOSvi4Sjya+Y6xQ+ljTIyVdduepcvvUV8DsxEvMI95DRzgOetQohqbfOchzSk HIvAw9vXZeALRu33FXqYkzuSQglkm4njRonWYaRHhTiEMDHbyMRhtdAY77/JYbERHnq5 qRtQ12hIrFu1kaNaC42JrqCaSyDvXxJTuK77lUehHvBN8HbYe8vq1AAh/NnMTOqctPaO DnZq3Ih7RwWBrxNknUpPum8O5C2uxVH1+YSDQu88Bb/fL9Kcz2i/XibxQ0yaYFqrZYZh pZf0XV4USnLi7C/zIgtrUbBPj5Sl0rgVEtbtUV63feHDKPPrqDVbQUUCgTwddxipBC03 gCtw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@gmail.com header.s=20161025 header.b=oXBOKXpc; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v18si417292otq.209.2020.02.12.19.11.47; Wed, 12 Feb 2020 19:12:00 -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=fail header.i=@gmail.com header.s=20161025 header.b=oXBOKXpc; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729581AbgBMDLj (ORCPT + 99 others); Wed, 12 Feb 2020 22:11:39 -0500 Received: from mail-oi1-f196.google.com ([209.85.167.196]:45334 "EHLO mail-oi1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729378AbgBMDLj (ORCPT ); Wed, 12 Feb 2020 22:11:39 -0500 Received: by mail-oi1-f196.google.com with SMTP id v19so4298610oic.12 for ; Wed, 12 Feb 2020 19:11:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=KJ1cbKxSOkkJkYmSO9MG9FaSPDVN9iwyOwbghCa/jtg=; b=oXBOKXpcItHfv4s3EsQVQteHfurtrQ6mrHee+WEyMt4RcFVZVzPrAM2IX5iVcqFHDF ggdFJebWJo4tS2fy1u82DGyu7AW2TuLpNKof9ZOh+RUhr2PO+KyLj1GVBY1UnnsPyHRT YmEVVRfl9Rsmj/Onq2+50dIBVXupdYVBaKcQfnJB0mtWRvPldzjzG5igdgrzDZO7eteP WZIV1dnrzILifztrU0tTKRnvkkONqpZGXdz2gql0XUkvgan+ZFcn7L9ijKNR2Y8FoAIT DGJIRLbALOyvLyW0pR1HZR4RDhMoLNJa7uNVOX5PiUGthjljSuDbCVmYjra+DUQkhj84 VxDw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=KJ1cbKxSOkkJkYmSO9MG9FaSPDVN9iwyOwbghCa/jtg=; b=tsfh0+Hyn5zHfp68CGl5j5DoSU7dePlWSfT5MglDc76TjGKskZLrcmq+ePoKB56S4G NiDOZ7h+CIw584ET1opOU9UC88GeOpCJcLwe+KLiH2z6mR57JM5yp7fiynemRGYvvEH2 Aik3AMxpUI/scvoG2Z/WwMt0E5HLspaySz8r+KUn2UQJ8v8pVJU8V/c9pFhPy0fKCQEa BcNjHMCXHhiD1570boDfMdnfLAbSdXnKlGsEZX2TLDdDqadzndl0L3k9fUpPo3aKzozw 70JpEdnf8JODldFu3R61VitgTuUCSCnjVAQEvjFi7cWuoQFRBQSaG9Hj7wsrUlWb7/r8 wkVQ== X-Gm-Message-State: APjAAAWQ6aCK48jQ4RgETwNzOw197lmGbQNmpB88I2zAuY0rriBmWQMv mAqnMrYk+gSHIXnamLqLfw== X-Received: by 2002:aca:f1d4:: with SMTP id p203mr1558648oih.116.1581563497684; Wed, 12 Feb 2020 19:11:37 -0800 (PST) Received: from serve.minyard.net ([47.184.136.59]) by smtp.gmail.com with ESMTPSA id t20sm307533oij.19.2020.02.12.19.11.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 12 Feb 2020 19:11:36 -0800 (PST) Received: from t560.minyard.net (unknown [IPv6:2001:470:b8f6:1b:e166:6491:dd75:4196]) by serve.minyard.net (Postfix) with ESMTPA id 84C4B180055; Thu, 13 Feb 2020 03:11:36 +0000 (UTC) From: minyard@acm.org To: Catalin Marinas , Will Deacon , linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, Corey Minyard Subject: [RFC PATCH 2/2] arm64:kgdb: Fix kernel single-stepping Date: Wed, 12 Feb 2020 21:11:31 -0600 Message-Id: <20200213031131.13255-3-minyard@acm.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200213031131.13255-1-minyard@acm.org> References: <20200213031131.13255-1-minyard@acm.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Corey Minyard Single stepping on arm64 in kernel mode was just broken. Here are the problems: If single step is set and an interrupt is pending, the interrupt is taken. The interrupt should run and then return and the single stepped instruction run. However, instead, as soon as the kernel calls enable_dbg, the single step happens right there. To fix this, disable SS in the MDSCR register on entry and save it's value for later use. The SS bit in the MDSCR register is set globally for the CPU, not for the task being single stepped. If the task migrates, that could cause the bit to be set on the wrong core. So instead, store the value of SS in the thread structure and set it properly on exit back to the kernel. If a single step occurs, it clears the SS bit in PSTATE. So subsiquent single steps will not work. The bit needs to be reset on each single step operation. Signed-off-by: Corey Minyard --- arch/arm64/include/asm/ptrace.h | 4 ++-- arch/arm64/kernel/asm-offsets.c | 1 + arch/arm64/kernel/debug-monitors.c | 7 ++++--- arch/arm64/kernel/entry.S | 21 +++++++++++++++++++++ arch/arm64/kernel/kgdb.c | 3 +++ 5 files changed, 31 insertions(+), 5 deletions(-) diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h index fbebb411ae20..a07847deff8f 100644 --- a/arch/arm64/include/asm/ptrace.h +++ b/arch/arm64/include/asm/ptrace.h @@ -168,11 +168,11 @@ struct pt_regs { }; u64 orig_x0; #ifdef __AARCH64EB__ - u32 unused2; + u32 ss_enable; /* Kernel single-step for a task */ s32 syscallno; #else s32 syscallno; - u32 unused2; + u32 ss_enable; #endif u64 orig_addr_limit; diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index a5bdce8af65b..038e76d2f0c4 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c @@ -62,6 +62,7 @@ int main(void) DEFINE(S_PSTATE, offsetof(struct pt_regs, pstate)); DEFINE(S_PC, offsetof(struct pt_regs, pc)); DEFINE(S_SYSCALLNO, offsetof(struct pt_regs, syscallno)); + DEFINE(S_SS_ENABLE, offsetof(struct pt_regs, ss_enable)); DEFINE(S_ORIG_ADDR_LIMIT, offsetof(struct pt_regs, orig_addr_limit)); DEFINE(S_PMR_SAVE, offsetof(struct pt_regs, pmr_save)); DEFINE(S_STACKFRAME, offsetof(struct pt_regs, stackframe)); diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c index 2a0dfd8b1265..d4085cfef5a7 100644 --- a/arch/arm64/kernel/debug-monitors.c +++ b/arch/arm64/kernel/debug-monitors.c @@ -409,7 +409,7 @@ void kernel_enable_single_step(struct pt_regs *regs) { WARN_ON(!irqs_disabled()); set_regs_spsr_ss(regs); - mdscr_write(mdscr_read() | DBG_MDSCR_SS); + regs->ss_enable = DBG_MDSCR_SS; enable_debug_monitors(DBG_ACTIVE_EL1); } NOKPROBE_SYMBOL(kernel_enable_single_step); @@ -417,7 +417,8 @@ NOKPROBE_SYMBOL(kernel_enable_single_step); void kernel_disable_single_step(struct pt_regs *regs) { WARN_ON(!irqs_disabled()); - mdscr_write(mdscr_read() & ~DBG_MDSCR_SS); + regs->ss_enable = 0; + clear_regs_spsr_ss(regs); disable_debug_monitors(DBG_ACTIVE_EL1); } NOKPROBE_SYMBOL(kernel_disable_single_step); @@ -425,7 +426,7 @@ NOKPROBE_SYMBOL(kernel_disable_single_step); int kernel_active_single_step(struct pt_regs *regs) { WARN_ON(!irqs_disabled()); - return mdscr_read() & DBG_MDSCR_SS; + return regs->ss_enable; } NOKPROBE_SYMBOL(kernel_active_single_step); diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 7c6a0a41676f..fcf979b17d94 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -174,6 +174,17 @@ alternative_cb_end apply_ssbd 1, x22, x23 .else + /* + * If single-step was enabled, save it off and disable it, + * or it will trap on clearing the D bit in PSTATE. + * The restore code will re-enable it if necessary. + */ + mrs x20, mdscr_el1 + bic x21, x20, #1 + msr mdscr_el1, x21 + and x20, x20, #1 + str w20, [sp, #S_SS_ENABLE] + add x21, sp, #S_FRAME_SIZE get_current_task tsk /* Save the task's original addr_limit and set USER_DS */ @@ -349,6 +360,16 @@ alternative_else_nop_endif msr elr_el1, x21 // set up the return data msr spsr_el1, x22 + + .if \el != 0 + /* Restore the single-step bit. */ + ldr w21, [sp, #S_SS_ENABLE] + mrs x20, mdscr_el1 + orr x20, x20, x21 + msr mdscr_el1, x20 + /* PSTATE.D and PSTATE.SS will be restored from SPSR_EL1. */ + .endif + ldp x0, x1, [sp, #16 * 0] ldp x2, x3, [sp, #16 * 1] ldp x4, x5, [sp, #16 * 2] diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c index 220fe8fd6ace..260f12c76b6e 100644 --- a/arch/arm64/kernel/kgdb.c +++ b/arch/arm64/kernel/kgdb.c @@ -223,6 +223,9 @@ int kgdb_arch_handle_exception(int exception_vector, int signo, */ if (!kernel_active_single_step(linux_regs)) kernel_enable_single_step(linux_regs); + else + /* Doing a single-step clears ss, reset it. */ + linux_regs->pstate |= DBG_SPSR_SS; err = 0; break; default: -- 2.17.1