From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-11.5 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2357EC00A89 for ; Mon, 2 Nov 2020 11:43:28 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A7B3E207C3 for ; Mon, 2 Nov 2020 11:43:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="TUhw+53O"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=kernel.org header.i=@kernel.org header.b="WpiExiBh" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A7B3E207C3 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References:Message-ID: Subject:To:From:Date:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=mhVIBeTQGaTadjf5jLI2XOTzFthgdXcQoeaSLl8GVUU=; b=TUhw+53OFUXVD5EErrvJZolWh cYpYukCQ3iD4T/POzTAa/TViyyynbZKaNrnPhrlrjGDzkPlOcKWc36qNnLwDClzGckfo56SdxU0k0 Ji4bJda+CMKn5glKdab6VFeAIONZxsi5lX4WPksW9pPuZk4un7XXXDKSP9w3ov6+cD5O5lyOnhcqi dqHKeYmvJEXBdQdiPj306fVLKvOmdah274Cn7YrEium1OLwC4Jv9FX4zzJhmhOcC4mHyh2NVCVUCs JdBw7rxwtbgZfRSsvrA1HgI1g3d+107iHpVJh0eR2ed+/++rGZcMvzgauEQrbhtrwFq1yeKfRSR43 bzgBGiPFw==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kZYDq-0006Ug-JH; Mon, 02 Nov 2020 11:42:02 +0000 Received: from mail.kernel.org ([198.145.29.99]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kZYDm-0006TV-NW for linux-arm-kernel@lists.infradead.org; Mon, 02 Nov 2020 11:42:00 +0000 Received: from willie-the-truck (236.31.169.217.in-addr.arpa [217.169.31.236]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id EE932207C3; Mon, 2 Nov 2020 11:41:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604317316; bh=SMcMmnOC/lLmXcnhQkhq5NzmW5mLLRcHky9qc09yeGw=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=WpiExiBh7eX0WPaOpnuMOBsJPs8Ofp4+mILZIzTk3TxWqbxULvfGklxmd96HuF9I2 QlYA5WocmXRszaJ/9mH6h6G2r2mGMdufNOZAUk82ApWMIiwJQwhqZsnNS9lAo4YL6Q +mJ9RBY8hUgjETWvNQ1tAkU7peTtRZcfk2U3Srv8= Date: Mon, 2 Nov 2020 11:41:52 +0000 From: Will Deacon To: Jean-Philippe Brucker Subject: Re: [PATCH] arm64: kprobes: Use BRK instead of single-step when executing instructions out-of-line Message-ID: <20201102114152.GA3452@willie-the-truck> References: <20201029173440.117174-1-jean-philippe@linaro.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20201029173440.117174-1-jean-philippe@linaro.org> User-Agent: Mutt/1.10.1 (2018-07-13) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201102_064159_043645_C923554F X-CRM114-Status: GOOD ( 33.83 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: catalin.marinas@arm.com, mhiramat@kernel.org, linux-arm-kernel@lists.infradead.org Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org On Thu, Oct 29, 2020 at 06:34:42PM +0100, Jean-Philippe Brucker wrote: > Commit 36dadef23fcc ("kprobes: Init kprobes in early_initcall") enabled > using kprobes from early_initcall. Unfortunately at this point the > hardware debug infrastructure is not operational. The OS lock may still > be locked, and the hardware watchpoints may have unknown values when > kprobe enables debug monitors to single-step instructions. > > Rather than using hardware single-step, append a BRK instruction after > the instruction to be executed out-of-line. > > Fixes: 36dadef23fcc ("kprobes: Init kprobes in early_initcall") > Suggested-by: Will Deacon > Signed-off-by: Jean-Philippe Brucker > --- > > An alternative to fix [1]. I haven't done uprobes yet since they don't > suffer the same problem, but could add it to the bottom of my list. > Lightly tested with kprobe smoke test and the BPF selftests. > Interestingly on Seattle when running the "overhead" BPF selftest, that > triggers a kprobe a bunch of times, I see a 20-30% improvement with this > patch. I'm guessing it's the cost of touching the debug sysregs? > > [1] https://lore.kernel.org/linux-arm-kernel/20201026172907.1468294-1-jean-philippe@linaro.org/ > --- > arch/arm64/include/asm/brk-imm.h | 2 + > arch/arm64/include/asm/debug-monitors.h | 1 + > arch/arm64/include/asm/kprobes.h | 2 +- > arch/arm64/kernel/probes/kprobes.c | 56 +++++++++---------------- > 4 files changed, 24 insertions(+), 37 deletions(-) > > diff --git a/arch/arm64/include/asm/brk-imm.h b/arch/arm64/include/asm/brk-imm.h > index e3d47b52161d..ec7720dbe2c8 100644 > --- a/arch/arm64/include/asm/brk-imm.h > +++ b/arch/arm64/include/asm/brk-imm.h > @@ -10,6 +10,7 @@ > * #imm16 values used for BRK instruction generation > * 0x004: for installing kprobes > * 0x005: for installing uprobes > + * 0x006: for kprobe software single-step > * Allowed values for kgdb are 0x400 - 0x7ff > * 0x100: for triggering a fault on purpose (reserved) > * 0x400: for dynamic BRK instruction > @@ -19,6 +20,7 @@ > */ > #define KPROBES_BRK_IMM 0x004 > #define UPROBES_BRK_IMM 0x005 > +#define KPROBES_BRK_SS_IMM 0x006 > #define FAULT_BRK_IMM 0x100 > #define KGDB_DYN_DBG_BRK_IMM 0x400 > #define KGDB_COMPILED_DBG_BRK_IMM 0x401 > diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h > index 0b298f48f5bf..657c921fd784 100644 > --- a/arch/arm64/include/asm/debug-monitors.h > +++ b/arch/arm64/include/asm/debug-monitors.h > @@ -53,6 +53,7 @@ > > /* kprobes BRK opcodes with ESR encoding */ > #define BRK64_OPCODE_KPROBES (AARCH64_BREAK_MON | (KPROBES_BRK_IMM << 5)) > +#define BRK64_OPCODE_KPROBES_SS (AARCH64_BREAK_MON | (KPROBES_BRK_SS_IMM << 5)) > /* uprobes BRK opcodes with ESR encoding */ > #define BRK64_OPCODE_UPROBES (AARCH64_BREAK_MON | (UPROBES_BRK_IMM << 5)) > > diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h > index 97e511d645a2..8699ce30f587 100644 > --- a/arch/arm64/include/asm/kprobes.h > +++ b/arch/arm64/include/asm/kprobes.h > @@ -16,7 +16,7 @@ > #include > > #define __ARCH_WANT_KPROBES_INSN_SLOT > -#define MAX_INSN_SIZE 1 > +#define MAX_INSN_SIZE 2 > > #define flush_insn_slot(p) do { } while (0) > #define kretprobe_blacklist_size 0 > diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c > index deba738142ed..ec1446ceacc9 100644 > --- a/arch/arm64/kernel/probes/kprobes.c > +++ b/arch/arm64/kernel/probes/kprobes.c > @@ -36,21 +36,25 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); > static void __kprobes > post_kprobe_handler(struct kprobe_ctlblk *, struct pt_regs *); > > -static int __kprobes patch_text(kprobe_opcode_t *addr, u32 opcode) > +static int __kprobes patch_text(kprobe_opcode_t *addr, u32 opc1, u32 opc2) > { > - void *addrs[1]; > - u32 insns[1]; > + void *addrs[2]; > + u32 insns[2]; > > addrs[0] = addr; > - insns[0] = opcode; > + insns[0] = opc1; > + if (opc2) { > + addrs[1] = addr + 1; > + insns[1] = opc2; > + } > > - return aarch64_insn_patch_text(addrs, insns, 1); > + return aarch64_insn_patch_text(addrs, insns, opc2 ? 2 : 1); > } > > static void __kprobes arch_prepare_ss_slot(struct kprobe *p) > { > /* prepare insn slot */ > - patch_text(p->ainsn.api.insn, p->opcode); > + patch_text(p->ainsn.api.insn, p->opcode, BRK64_OPCODE_KPROBES_SS); > > flush_icache_range((uintptr_t) (p->ainsn.api.insn), > (uintptr_t) (p->ainsn.api.insn) + > @@ -128,13 +132,13 @@ void *alloc_insn_page(void) > /* arm kprobe: install breakpoint in text */ > void __kprobes arch_arm_kprobe(struct kprobe *p) > { > - patch_text(p->addr, BRK64_OPCODE_KPROBES); > + patch_text(p->addr, BRK64_OPCODE_KPROBES, 0); > } > > /* disarm kprobe: remove breakpoint from text */ > void __kprobes arch_disarm_kprobe(struct kprobe *p) > { > - patch_text(p->addr, p->opcode); > + patch_text(p->addr, p->opcode, 0); I don't think patch_text() is offering an awful lot to these callers. Why don't we just call aarch64_insn_patch_text() directly, which I think will make the code easier to read too? > void __kprobes arch_remove_kprobe(struct kprobe *p) > @@ -163,20 +167,14 @@ static void __kprobes set_current_kprobe(struct kprobe *p) > } > > /* > - * Interrupts need to be disabled before single-step mode is set, and not > - * reenabled until after single-step mode ends. > - * Without disabling interrupt on local CPU, there is a chance of > - * interrupt occurrence in the period of exception return and start of > - * out-of-line single-step, that result in wrongly single stepping > - * into the interrupt handler. > + * Keep interrupts disabled while executing the instruction out-of-line. Since > + * the kprobe state is per-CPU, we can't afford to be migrated. > */ > static void __kprobes kprobes_save_local_irqflag(struct kprobe_ctlblk *kcb, > struct pt_regs *regs) > { > kcb->saved_irqflag = regs->pstate & DAIF_MASK; > regs->pstate |= PSR_I_BIT; > - /* Unmask PSTATE.D for enabling software step exceptions. */ > - regs->pstate &= ~PSR_D_BIT; Can we set the D bit now? Would be one less thing to worry about. Cheers, Will _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel