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=-10.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,INCLUDES_PATCH,MAILING_LIST_MULTI,NICE_REPLY_A, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED 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 86EB7C00A89 for ; Mon, 2 Nov 2020 13:54:24 +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 05C7C223BD for ; Mon, 2 Nov 2020 13:54:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="eDNjMGWB"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=kernel.org header.i=@kernel.org header.b="kDOxOHrt" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 05C7C223BD 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:Mime-Version:References:In-Reply-To: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=vTRldCkowlr+itC5DvYCUgi4M4fR/IwBtweHSg+iGhs=; b=eDNjMGWBouuYCdG9dODP8YC3b NzZZVoSoSJWoLnVp2fAyQ+OF3NZf42SnIuYsYoxMzSx/DxLbDjI3ZxKQgATT9vbZ2AwkdDUtkS9ob oEFI8KaVViBhMq/K5DVv4wT7PI7rwbXmA3CJq+NO2Zj7w4z461F8Z1pzptHHo9mmx5URUf7THWf/N 0qzQskTSFXStcSpGfkExLkV00FRtaglv5TYhmp+/IViSr5f/UliJXEY/qFsselfQ+lbqKG8UZ9DXW 8U4NyBEAEdhHct7z2jX8nuxvMlW5Z/qu5a3SCepkTYrslGAZnJCIRjqoBekhDC9D9JobYQ5Ls/U8C fVGCU1Naw==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kZaGc-0004ds-8b; Mon, 02 Nov 2020 13:53: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 1kZaGZ-0004d0-CT for linux-arm-kernel@lists.infradead.org; Mon, 02 Nov 2020 13:53:00 +0000 Received: from devnote2 (NE2965lan1.rev.em-net.ne.jp [210.141.244.193]) (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 86033208B6; Mon, 2 Nov 2020 13:52:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604325178; bh=VkrrWoloX7vmmfIZfMGclJ9xyq7JoUGeTJ8OraX6z4M=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=kDOxOHrtGoQawIm+pvZ2Z1nAD7Y5fuVvDDfuCQf9fIQYghO7l++irlzyEA8Lb5gVB tC7uP8X8pcXzjWOyhiPweBlqyVNT4ZDCXt//gNj5ltJQx7Wls9I9+r5EEX9gSPbqbR GNC2qeoQoDPeqSf5iHKyCP2ilDPfaTZdOg2nbpoc= Date: Mon, 2 Nov 2020 22:52:55 +0900 From: Masami Hiramatsu To: Will Deacon Subject: Re: [PATCH] arm64: kprobes: Use BRK instead of single-step when executing instructions out-of-line Message-Id: <20201102225255.fa991f3607c45bbbb161803c@kernel.org> In-Reply-To: <20201102114152.GA3452@willie-the-truck> References: <20201029173440.117174-1-jean-philippe@linaro.org> <20201102114152.GA3452@willie-the-truck> X-Mailer: Sylpheed 3.7.0 (GTK+ 2.24.32; x86_64-pc-linux-gnu) Mime-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201102_085259_585164_2266D2D0 X-CRM114-Status: GOOD ( 38.15 ) 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: Jean-Philippe Brucker , mhiramat@kernel.org, linux-arm-kernel@lists.infradead.org, catalin.marinas@arm.com 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 Mon, 2 Nov 2020 11:41:52 +0000 Will Deacon wrote: > 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? Agreed. I guess it's just because histrically used. > > 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. Hmm, I think we just ignore D bit above. If someone (kgdb?) is set D flag then there may be no reason to prohibit it on the trampoline. (Of course they must handle this case) Thank you, -- Masami Hiramatsu _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel