From patchwork Tue Oct 3 05:10:18 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 9981657 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B99D860291 for ; Tue, 3 Oct 2017 05:10:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9F9C028893 for ; Tue, 3 Oct 2017 05:10:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 945682871B; Tue, 3 Oct 2017 05:10:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 1B3A22871B for ; Tue, 3 Oct 2017 05:10:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=e7yId3B2qo1zj4IMgcCBORsHebMv4bOwj5vsr1jO5g4=; b=BbrOffrKBnmYKHbtE5aQnKPnzT xURQ7w1aYhHqerm/Q1J77mLddIGuTQWGIN2jTUrXrL+LM6hHViLDjFX0QMhxLZlhcdKmJP/F5L4lx PI8njbSra4PP8QBQLaSUYopMhmcBbEYnKfqap/pG5HUjaD5z2uAvDvr+3C9eJSqi9RvZyBMc6c7og V5xRwHtAshHrcHct02ZAIj50vTQU/h6UcoVOQSYxjmCPH+Ak4s7sw05uzf83eGWdpGtFJIw1IFvNi qTbfodCgECzUxq2a7eW1YgJlQdAxvvBVyE9twZWSCSU/CyFIWlH/HARt7AYNQMN1XxC/ufWbSFUh8 Txp6i1FA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1dzFTA-0000aO-Ri; Tue, 03 Oct 2017 05:10:12 +0000 Received: from mail-pf0-x231.google.com ([2607:f8b0:400e:c00::231]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1dzFS0-0007VC-NI for linux-arm-kernel@lists.infradead.org; Tue, 03 Oct 2017 05:09:16 +0000 Received: by mail-pf0-x231.google.com with SMTP id r68so4026757pfj.3 for ; Mon, 02 Oct 2017 22:08:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Zps1L7/8xG2/8ret7hCrJA4aFqA7e4pJT1k6g0hB+DU=; b=OQ5QxQ5JcmgRs1bv5uvjAM883TTmtzrg8wuZyYOXYPedGqdcrvfKmmasp4wpsMv2h6 /uxP2Dnro8ADewQuebxwu62+/eDtacXtbnAZ6P9jKOT8lWI/SCi4qq2ujtNYXtAypdcP 3iQmwOQM3Qk3ZgzhJNwjx9tFjtV1N3iuhgTPU= 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; bh=Zps1L7/8xG2/8ret7hCrJA4aFqA7e4pJT1k6g0hB+DU=; b=A1x0LYB1esFqfn22jjzr08Zr2YS9HRXaoNuvGHB506EstKauEISmJGisjU5xEdzTCm asyKS9pfyQkWE6Tsp87pNMebIhUnX2oT4tTSmZkowLrKVJ39Dl+iGapRzzQQH0p7F8Vh iDRqk9cw765vSHm/m8JqUgdhEeuMw2WRNMTdPbsJEMYj1TAT0JbfFgLy48N5aw0Wesd8 z4eQSL0gaaXjmr8sKnky7wXrCmTHPPcU1vS7U+A6ceQZp7u3YWC7kXPgTwHkFQXEvqk9 yCJPbC2WmVYFmAROtJFGpEODdBK7q5KIWitZKIBYLelRnyug6noovEdNotuJJKHmWg/P 1mkQ== X-Gm-Message-State: AHPjjUiXqxDs9cc/5wYlmnota4brXM6P/zRcxKf/tPasPgitZ4X6b0Ws aRJWwElLNaLx3tBUioqdTS3yZw== X-Google-Smtp-Source: AOwi7QBX5tfTtirvKFCX6bf7s/p5aWa7+4JQ2ykYfGF3MBbyCTDkhkp7QO2H6Q1gaF0Ga2bR2jWHRg== X-Received: by 10.99.167.68 with SMTP id w4mr14084985pgo.390.1507007300872; Mon, 02 Oct 2017 22:08:20 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id q67sm22452341pfg.160.2017.10.02.22.08.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 02 Oct 2017 22:08:20 -0700 (PDT) From: AKASHI Takahiro To: catalin.marinas@arm.com, will.deacon@arm.com, jason.wessel@windriver.com Subject: [PATCH v4 2/3] arm64: kgdb: prevent kgdb from being invoked recursively Date: Tue, 3 Oct 2017 14:10:18 +0900 Message-Id: <20171003051019.29714-3-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20171003051019.29714-1-takahiro.akashi@linaro.org> References: <20171003051019.29714-1-takahiro.akashi@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20171002_220901_394996_B1821B0D X-CRM114-Status: GOOD ( 18.41 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kgdb-bugreport@lists.sourceforge.net, linux-arm-kernel@lists.infradead.org, AKASHI Takahiro MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP If a breakpoint is set in an interrupt-sensitive place, like gic_handle_irq(), a debug exception can be triggerred recursively. We will see the following message: KGDB: re-enter error: breakpoint removed ffffffc000081258 ------------[ cut here ]------------ WARNING: CPU: 0 PID: 650 at kernel/debug/debug_core.c:435 kgdb_handle_exception+0x1dc/0x1f4() Modules linked in: CPU: 0 PID: 650 Comm: sh Not tainted 3.17.0-rc2+ #177 Call trace: [] dump_backtrace+0x0/0x130 [] show_stack+0x10/0x1c [] dump_stack+0x74/0xb8 [] warn_slowpath_common+0x8c/0xb4 [] warn_slowpath_null+0x14/0x20 [] kgdb_handle_exception+0x1d8/0x1f4 [] kgdb_brk_fn+0x18/0x28 [] brk_handler+0x9c/0xe8 [] do_debug_exception+0x3c/0xac Exception stack(0xffffffc07e027650 to 0xffffffc07e027770) ... [] el1_dbg+0x14/0x68 [] kgdb_cpu_enter+0x464/0x5c0 [] kgdb_handle_exception+0x190/0x1f4 [] kgdb_brk_fn+0x18/0x28 [] brk_handler+0x9c/0xe8 [] do_debug_exception+0x3c/0xac Exception stack(0xffffffc07e027ac0 to 0xffffffc07e027be0) ... [] el1_dbg+0x14/0x68 [] __handle_sysrq+0x11c/0x190 [] write_sysrq_trigger+0x4c/0x60 [] proc_reg_write+0x54/0x84 [] vfs_write+0x98/0x1c8 [] SyS_write+0x40/0xa0 When some interrupt occurs, a breakpoint at gic_handle_irq() invokes kgdb. Kgdb then calls kgdb_roundup_cpus() to sync with other cpus. Current kgdb_roundup_cpus() unmasks interrupts temporarily to use smp_call_function(). This eventually allows another interrupt to occur and likely results in hitting a breakpoint at gic_handle_irq() again since a debug exception is always enabled in el1_irq. We can avoid this issue by specifying "nokgdbroundup" in a kernel command line, but this will also leave other cpus be in unknown state in terms of kgdb, and may result in interfering with kgdb. This patch re-implements kgdb_roundup_cpus() by using irq_work so that we won't have to enable interrupts there. Signed-off-by: AKASHI Takahiro Cc: Catalin Marinas Cc: Will Deacon Cc: Jason Wessel --- arch/arm64/kernel/kgdb.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c index 8d3ec8cf4ec4..508b413a3518 100644 --- a/arch/arm64/kernel/kgdb.c +++ b/arch/arm64/kernel/kgdb.c @@ -20,10 +20,13 @@ */ #include +#include #include +#include #include #include #include +#include #include #include @@ -111,6 +114,8 @@ struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = { { "fpcr", 4, -1 }, }; +static DEFINE_PER_CPU(struct irq_work, kgdb_irq_work); + char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs) { if (regno >= DBG_MAX_REG_NUM || regno < 0) @@ -277,16 +282,33 @@ static struct step_hook kgdb_step_hook = { .fn = kgdb_step_brk_fn }; -static void kgdb_call_nmi_hook(void *ignored) +static void kgdb_roundup_hook(struct irq_work *work) { kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs()); } void kgdb_roundup_cpus(unsigned long flags) { - local_irq_enable(); - smp_call_function(kgdb_call_nmi_hook, NULL, 0); - local_irq_disable(); + int cpu, this_cpu; + struct irq_work *work; + + if (num_online_cpus() == 1) + return; + + /* + * We assume that no cpus go up or down here, but we can't guarantee + * this because get_online_cpus() may not be called in an atomic + * context. It is fragile, but kgdb_handle_exception()/ + * kgdb_cpu_enter() doesn't deal with this, neither. + */ + this_cpu = raw_smp_processor_id(); + for_each_online_cpu(cpu) { + if (cpu == this_cpu) + continue; + + work = per_cpu_ptr(&kgdb_irq_work, cpu); + irq_work_queue_on(work, cpu); + } } static int __kgdb_notify(struct die_args *args, unsigned long cmd) @@ -327,6 +349,8 @@ static struct notifier_block kgdb_notifier = { int kgdb_arch_init(void) { int ret = register_die_notifier(&kgdb_notifier); + int cpu; + struct irq_work *work; if (ret != 0) return ret; @@ -334,6 +358,12 @@ int kgdb_arch_init(void) register_break_hook(&kgdb_brkpt_hook); register_break_hook(&kgdb_compiled_brkpt_hook); register_step_hook(&kgdb_step_hook); + + for_each_possible_cpu(cpu) { + work = per_cpu_ptr(&kgdb_irq_work, cpu); + init_irq_work(work, kgdb_roundup_hook); + } + return 0; }