From patchwork Wed Sep 19 23:42:00 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anton Vorontsov X-Patchwork-Id: 11519 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 60D4B23E41 for ; Wed, 19 Sep 2012 23:49:20 +0000 (UTC) Received: from mail-ie0-f180.google.com (mail-ie0-f180.google.com [209.85.223.180]) by fiordland.canonical.com (Postfix) with ESMTP id A550EA1914A for ; Wed, 19 Sep 2012 23:49:19 +0000 (UTC) Received: by ieje10 with SMTP id e10so2023684iej.11 for ; Wed, 19 Sep 2012 16:49:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to:cc :subject:date:message-id:x-mailer:in-reply-to:references :mime-version:content-type:content-transfer-encoding :x-gm-message-state; bh=5SFnJoq1+umpX+7wfWC87fPjvDQNfAAbm+Nx1AUGbaA=; b=OeJNkxoTqg4H0BjJnxepT2ELM6nR4EgSxSQQ7xJgXQM+ROgUQOOK02B2lYSPSP5WuM OkuSa8zsXf0C++dQSUguksB9QKDV0T988HxZMocBdUwYJfwqH4R9qMBXrmeQjEM3EgcS +3QUuTLwy0KxvPf67ZeptGDrmouTMEKxMB+Zc8Fxl+WhAZ2hbgD4SbKMEqeJ9MTJq9ic 589o8IrvheLpgNPhouQLqNG7/RdN7zHmJ43K/k8tyXX2HsBdAddqLS1WzesgnSbuiSGf Jw2I9ay0RVQ7Rk/OD5QrRmJ10r/ZbWIKP+NmFs+9LM50fxa4lMCoYflxiNBJ2myAagKY h3Jg== Received: by 10.50.217.229 with SMTP id pb5mr114592igc.28.1348098558951; Wed, 19 Sep 2012 16:49:18 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.50.184.232 with SMTP id ex8csp49795igc; Wed, 19 Sep 2012 16:49:18 -0700 (PDT) Received: by 10.68.221.72 with SMTP id qc8mr2006151pbc.63.1348098557986; Wed, 19 Sep 2012 16:49:17 -0700 (PDT) Received: from mail-pb0-f50.google.com (mail-pb0-f50.google.com [209.85.160.50]) by mx.google.com with ESMTPS id oo1si5196157pbc.99.2012.09.19.16.49.17 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 19 Sep 2012 16:49:17 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.160.50 is neither permitted nor denied by best guess record for domain of anton.vorontsov@linaro.org) client-ip=209.85.160.50; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.160.50 is neither permitted nor denied by best guess record for domain of anton.vorontsov@linaro.org) smtp.mail=anton.vorontsov@linaro.org Received: by mail-pb0-f50.google.com with SMTP id md12so3892864pbc.37 for ; Wed, 19 Sep 2012 16:49:17 -0700 (PDT) Received: by 10.66.84.6 with SMTP id u6mr833166pay.75.1348098557724; Wed, 19 Sep 2012 16:49:17 -0700 (PDT) Received: from localhost (ip-64-134-220-225.public.wayport.net. [64.134.220.225]) by mx.google.com with ESMTPS id c5sm1448173pay.5.2012.09.19.16.48.47 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 19 Sep 2012 16:49:17 -0700 (PDT) From: Anton Vorontsov To: Andrew Morton , Russell King , Jason Wessel , Greg Kroah-Hartman , Alan Cox Cc: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= , Colin Cross , Brian Swetland , John Stultz , Thomas Gleixner , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linaro-kernel@lists.linaro.org, patches@linaro.org, kernel-team@android.com, kgdb-bugreport@lists.sourceforge.net, linux-serial@vger.kernel.org Subject: =?UTF-8?q?=5BPATCH=2009/11=5D=20ARM=3A=20Add=20KGDB/KDB=20FIQ=20debugger=20generic=20code?= Date: Wed, 19 Sep 2012 16:42:00 -0700 Message-Id: <1348098122-11041-9-git-send-email-anton.vorontsov@linaro.org> X-Mailer: git-send-email 1.7.11.5 In-Reply-To: <20120919234003.GA24143@lizard> References: <20120919234003.GA24143@lizard> MIME-Version: 1.0 X-Gm-Message-State: ALoCoQnNiRaKYai0Kp/WaDdW63hz7gMkV5jLS+jpYO3CVippq0UJGQc1j2WY7xlvbwEFn2gQJSu6 The FIQ debugger may be used to debug situations when the kernel stuck in uninterruptable sections, e.g. the kernel infinitely loops or deadlocked in an interrupt or with interrupts disabled. By default KGDB FIQ is disabled in runtime, but can be enabled with kgdb_fiq.enable=1 kernel command line option. Signed-off-by: Anton Vorontsov --- arch/arm/Kconfig | 18 ++++++ arch/arm/include/asm/kgdb.h | 8 +++ arch/arm/kernel/Makefile | 1 + arch/arm/kernel/kgdb_fiq.c | 124 +++++++++++++++++++++++++++++++++++++++ arch/arm/kernel/kgdb_fiq_entry.S | 87 +++++++++++++++++++++++++++ 5 files changed, 238 insertions(+) create mode 100644 arch/arm/kernel/kgdb_fiq.c create mode 100644 arch/arm/kernel/kgdb_fiq_entry.S diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2f88d8d..fa10a2d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -171,6 +171,24 @@ config GENERIC_ISA_DMA config FIQ bool +config ARCH_MIGHT_HAVE_KGDB_FIQ + bool + +config KGDB_FIQ + bool "KGDB/KDB FIQ debugger" + depends on KGDB_KDB && ARCH_MIGHT_HAVE_KGDB_FIQ && !THUMB2_KERNEL + select FIQ + help + The FIQ debugger may be used to debug situations when the + kernel stuck in uninterruptable sections, e.g. the kernel + infinitely loops or deadlocked in an interrupt or with + interrupts disabled. + + By default KGDB FIQ is disabled in runtime, but can be + enabled with kgdb_fiq.enable=1 kernel command line option. + + If unsure, say N. + config NEED_RET_TO_USER bool diff --git a/arch/arm/include/asm/kgdb.h b/arch/arm/include/asm/kgdb.h index 48066ce..807e547 100644 --- a/arch/arm/include/asm/kgdb.h +++ b/arch/arm/include/asm/kgdb.h @@ -11,6 +11,8 @@ #define __ARM_KGDB_H__ #include +#include +#include /* * GDB assumes that we're a user process being debugged, so @@ -47,6 +49,12 @@ static inline void arch_kgdb_breakpoint(void) extern void kgdb_handle_bus_error(void); extern int kgdb_fault_expected; +extern char kgdb_fiq_handler; +extern char kgdb_fiq_handler_end; +asmlinkage void __exception_irq_entry kgdb_fiq_do_handle(struct pt_regs *regs); +extern int __init kgdb_register_fiq(unsigned int mach_kgdb_fiq, + void (*mach_kgdb_enable_fiq)(unsigned int irq, bool on), + bool (*mach_is_kgdb_fiq)(unsigned int irq)); #endif /* !__ASSEMBLY__ */ /* diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 7ad2d5c..5aa079b 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -56,6 +56,7 @@ obj-$(CONFIG_ATAGS_PROC) += atags.o obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o obj-$(CONFIG_ARM_THUMBEE) += thumbee.o obj-$(CONFIG_KGDB) += kgdb.o +obj-$(CONFIG_KGDB_FIQ) += kgdb_fiq_entry.o kgdb_fiq.o obj-$(CONFIG_ARM_UNWIND) += unwind.o obj-$(CONFIG_HAVE_TCM) += tcm.o obj-$(CONFIG_OF) += devtree.o diff --git a/arch/arm/kernel/kgdb_fiq.c b/arch/arm/kernel/kgdb_fiq.c new file mode 100644 index 0000000..f3df754 --- /dev/null +++ b/arch/arm/kernel/kgdb_fiq.c @@ -0,0 +1,124 @@ +/* + * KGDB FIQ + * + * Copyright 2010 Google, Inc. + * Arve Hjønnevåg + * Colin Cross + * Copyright 2012 Linaro Ltd. + * Anton Vorontsov + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int kgdb_fiq_enabled; +module_param_named(enable, kgdb_fiq_enabled, int, 0600); +MODULE_PARM_DESC(enable, "set to 1 to enable FIQ KGDB"); + +static unsigned int kgdb_fiq; +static bool (*is_kgdb_fiq)(unsigned int irq); + +asmlinkage void __exception_irq_entry kgdb_fiq_do_handle(struct pt_regs *regs) +{ + if (!is_kgdb_fiq(kgdb_fiq)) + return; + if (!kgdb_nmi_poll_knock()) + return; + + nmi_enter(); + kgdb_handle_exception(1, 0, 0, regs); + nmi_exit(); +} + +static struct fiq_handler kgdb_fiq_desc = { + .name = "kgdb", +}; + +static long kgdb_fiq_setup_stack(void *info) +{ + struct pt_regs regs; + + regs.ARM_sp = __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER) + + THREAD_START_SP; + WARN_ON(!regs.ARM_sp); + + set_fiq_regs(®s); + return 0; +} + +static void (*kgdb_enable_fiq)(unsigned int irq, bool on); + +/** + * kgdb_fiq_enable_nmi - Manage NMI-triggered entry to KGDB + * @on: Flag to either enable or disable an NMI + * + * This function manages NMIs that usually cause KGDB to enter. That is, not + * all NMIs should be enabled or disabled, but only those that issue + * kgdb_handle_exception(). + * + * The call counts disable requests, and thus allows to nest disables. But + * trying to enable already enabled NMI is an error. + */ +static void kgdb_fiq_enable_nmi(bool on) +{ + static atomic_t cnt; + int ret; + + ret = atomic_add_return(on ? 1 : -1, &cnt); + if (ret > 1 && on) { + /* + * There should be only one instance that calls this function + * in "enable, disable" order. All other users must call + * disable first, then enable. If not, something is wrong. + */ + WARN_ON(1); + return; + } + + kgdb_enable_fiq(kgdb_fiq, ret > 0); +} + +int __init kgdb_register_fiq(unsigned int mach_kgdb_fiq, + void (*mach_kgdb_enable_fiq)(unsigned int irq, bool on), + bool (*mach_is_kgdb_fiq)(unsigned int irq)) +{ + int err; + int cpu; + + if (!kgdb_fiq_enabled) + return -ENODEV; + if (kgdb_fiq) + return -EBUSY; + + kgdb_fiq = mach_kgdb_fiq; + kgdb_enable_fiq = mach_kgdb_enable_fiq; + is_kgdb_fiq = mach_is_kgdb_fiq; + + err = claim_fiq(&kgdb_fiq_desc); + if (err) { + pr_warn("%s: unable to claim fiq", __func__); + return err; + } + + for_each_possible_cpu(cpu) + work_on_cpu(cpu, kgdb_fiq_setup_stack, NULL); + + set_fiq_handler(&kgdb_fiq_handler, + &kgdb_fiq_handler_end - &kgdb_fiq_handler); + + arch_kgdb_ops.enable_nmi = kgdb_fiq_enable_nmi; + return 0; +} diff --git a/arch/arm/kernel/kgdb_fiq_entry.S b/arch/arm/kernel/kgdb_fiq_entry.S new file mode 100644 index 0000000..d6becca --- /dev/null +++ b/arch/arm/kernel/kgdb_fiq_entry.S @@ -0,0 +1,87 @@ +/* + * KGDB FIQ entry + * + * Copyright 1996,1997,1998 Russell King. + * Copyright 2012 Linaro Ltd. + * Anton Vorontsov + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include "entry-header.S" + + .text + +@ This is needed for usr_entry/alignment_trap +.LCcralign: + .long cr_alignment +.LCdohandle: + .long kgdb_fiq_do_handle + + .macro fiq_handler + ldr r1, =.LCdohandle + mov r0, sp + adr lr, BSYM(9997f) + ldr pc, [r1] +9997: + .endm + + .align 5 +__fiq_svc: + svc_entry + fiq_handler + mov r0, sp + ldmib r0, {r1 - r14} + msr cpsr_c, #FIQ_MODE | PSR_I_BIT | PSR_F_BIT + add r8, r0, #S_PC + ldr r9, [r0, #S_PSR] + msr spsr_cxsf, r9 + ldr r0, [r0, #S_R0] + ldmia r8, {pc}^ + + UNWIND(.fnend ) +ENDPROC(__fiq_svc) + .ltorg + + .align 5 +__fiq_usr: + usr_entry + kuser_cmpxchg_check + fiq_handler + get_thread_info tsk + mov why, #0 + b ret_to_user_from_irq + UNWIND(.fnend ) +ENDPROC(__fiq_usr) + .ltorg + + .global kgdb_fiq_handler +kgdb_fiq_handler: + + vector_stub fiq, FIQ_MODE, 4 + + .long __fiq_usr @ 0 (USR_26 / USR_32) + .long __fiq_svc @ 1 (FIQ_26 / FIQ_32) + .long __fiq_svc @ 2 (IRQ_26 / IRQ_32) + .long __fiq_svc @ 3 (SVC_26 / SVC_32) + .long __fiq_svc @ 4 + .long __fiq_svc @ 5 + .long __fiq_svc @ 6 + .long __fiq_svc @ 7 + .long __fiq_svc @ 8 + .long __fiq_svc @ 9 + .long __fiq_svc @ a + .long __fiq_svc @ b + .long __fiq_svc @ c + .long __fiq_svc @ d + .long __fiq_svc @ e + .long __fiq_svc @ f + + .global kgdb_fiq_handler_end +kgdb_fiq_handler_end: