From patchwork Wed Aug 1 20:52:18 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anton Vorontsov X-Patchwork-Id: 10448 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 7045623E56 for ; Wed, 1 Aug 2012 20:54:35 +0000 (UTC) Received: from mail-gh0-f180.google.com (mail-gh0-f180.google.com [209.85.160.180]) by fiordland.canonical.com (Postfix) with ESMTP id 0DE40A18277 for ; Wed, 1 Aug 2012 20:54:34 +0000 (UTC) Received: by ghbz12 with SMTP id z12so7667942ghb.11 for ; Wed, 01 Aug 2012 13:54:34 -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:date:from :to:cc:subject:message-id:references:mime-version:content-type :content-disposition:content-transfer-encoding:in-reply-to :user-agent:x-gm-message-state; bh=WYYOvgOEAH2cm8gW+O3ik362J9iiUxNrfYTWrq4eQ5U=; b=CEKsQvsoiXXue+gSzQWEeJWRrzYU7n7MJfQ6TcZrlFnHMwtI8gwhYsTipqxvVLrCoQ arJqe0bC7JgMZfp4Zv8rjDto9S8DWYHP2AUeOaYPVBoAxY5N670UxFpOoSt2fN0RROLZ 8VWQPPFeWLwQfzXot3vFpmm7LE0bWhLvIcoYPr6UI8O8wZSNJ7JgToxmjW2gWifqD0SP /f2ZxG9DkRTn3kw9GCdsL0DwCP11RWOnkgQnMVw3PpsB/7bfmTU+7p5eRNXprohzTrX+ iFThyy1UH8dltV/H72wn1Fs2yR7uLneFbvPaTGmRn28+UiAOqD+67jKSdXyasodxVc3G 6IpA== Received: by 10.50.163.5 with SMTP id ye5mr5354477igb.51.1343854474341; Wed, 01 Aug 2012 13:54:34 -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.87.40 with SMTP id u8csp220276igz; Wed, 1 Aug 2012 13:54:33 -0700 (PDT) Received: by 10.60.24.4 with SMTP id q4mr9978936oef.50.1343854473689; Wed, 01 Aug 2012 13:54:33 -0700 (PDT) Received: from mail-ob0-f178.google.com (mail-ob0-f178.google.com [209.85.214.178]) by mx.google.com with ESMTPS id ks5si3744591obb.158.2012.08.01.13.54.33 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 01 Aug 2012 13:54:33 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.214.178 is neither permitted nor denied by best guess record for domain of anton.vorontsov@linaro.org) client-ip=209.85.214.178; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.214.178 is neither permitted nor denied by best guess record for domain of anton.vorontsov@linaro.org) smtp.mail=anton.vorontsov@linaro.org Received: by obbwd20 with SMTP id wd20so16440476obb.37 for ; Wed, 01 Aug 2012 13:54:33 -0700 (PDT) Received: by 10.182.50.103 with SMTP id b7mr31054772obo.15.1343854473294; Wed, 01 Aug 2012 13:54:33 -0700 (PDT) Received: from localhost (ip-64-134-231-11.public.wayport.net. [64.134.231.11]) by mx.google.com with ESMTPS id c6sm3448182obn.13.2012.08.01.13.54.29 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 01 Aug 2012 13:54:32 -0700 (PDT) Date: Wed, 1 Aug 2012 13:52:18 -0700 From: Anton Vorontsov To: Russell King - ARM Linux Cc: Jason Wessel , Greg Kroah-Hartman , Alan Cox , Arve =?utf-8?B?SGrDuG5uZXbDpWc=?= , Colin Cross , John Stultz , 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 Subject: Re: [PATCH 07/11] ARM: Add KGDB/KDB FIQ debugger generic code Message-ID: <20120801205218.GA20714@lizard> References: <20120730115719.GA5742@lizard> <1343649500-18491-7-git-send-email-anton.vorontsov@linaro.org> <20120730140724.GI6802@n2100.arm.linux.org.uk> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20120730140724.GI6802@n2100.arm.linux.org.uk> User-Agent: Mutt/1.5.21 (2010-09-15) X-Gm-Message-State: ALoCoQn45RrYLm17lNB3Nno1Y5aXk7yTL9tjSGHZeLvZGualULqCnhlX3snaJnWuU0JRzvxQu2cK On Mon, Jul 30, 2012 at 03:07:24PM +0100, Russell King - ARM Linux wrote: [....] > Now the thing here is that even if we did preserve SPSR_svc, with the > above exit sequence, there is _no_ way to preserve the value of SPSR_svc. > Normally, this doesn't matter because we know that the regions we care > about this have IRQs disabled. Wow, that is quite subtle. Indeed, now I clearly see that we do mangle SVC's SPSR. Thanks! [...] > So, maybe something like this for the svc return path: > > cpsid f > ldr r1, [saved_spsr_svc] > mov r0, sp > mrs spsr_cxsf, r1 > ldmib r0, {r1 - r14} > msr cpsr_c, #FIQ_MODE | PSR_I_BIT | PSR_F_BIT ... > ldmia r7, {pc}^ Yup, I got the idea: we have to restore the SPSR in SVC mode, but then we switch to FIQ mode and exit the exception while being in the FIQ mode, that way CPU won't change our restored SPSR_svc. As for "saved_spsr_svc", I think the easiest way to get it, is to switch to FIQ mode temporary, and read it from the stack. (Plus, cpsid is not available for older CPUs, but the thing is that we don't touch global enable/disable FIQs/IRQs flags, so I guess I don't actually need it.) So, that's what I've applied on top: @@ -33,7 +33,20 @@ __fiq_svc: svc_entry fiq_handler - svc_exit r5 @ return from exception + mrs r4, cpsr + msr cpsr_c, #FIQ_MODE | PSR_I_BIT | PSR_F_BIT + ldr r1, [sp, #8] + msr cpsr_c, r4 + msr spsr_cxsf, r1 + 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}^ And the whole fixed up patch is down below: - - - - From: Anton Vorontsov Subject: ARM: Add KGDB/KDB FIQ debugger generic code 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 | 101 ++++++++++++++++++++++++++++++++++++++ arch/arm/kernel/kgdb_fiq_entry.S | 92 ++++++++++++++++++++++++++++++++++ 5 files changed, 220 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 a91009c..ae6ddf1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -172,6 +172,24 @@ config GENERIC_ISA_DMA config FIQ bool +config ARCH_MIGHT_HAVE_FIQ + bool + +config KGDB_FIQ + bool "KGDB/KDB FIQ debugger" + depends on KGDB_KDB && ARCH_MIGHT_HAVE_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..72a62c7 --- /dev/null +++ b/arch/arm/kernel/kgdb_fiq.c @@ -0,0 +1,101 @@ +/* + * KGDB FIQ entry + * + * 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 + +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 void (*kgdb_enable_fiq)(unsigned int irq, bool on); +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; + dbg_io_ops->clear_irqs(); + + 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; +} + +int kgdb_arch_enable_nmi(bool on) +{ + static int cnt; + + if (cnt > 0 && on) + return cnt; + cnt += on ? 1 : -1; + kgdb_enable_fiq(kgdb_fiq, cnt > 0); + return cnt; +} + +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); + + kgdb_arch_enable_nmi(1); + 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..a6a1ad1 --- /dev/null +++ b/arch/arm/kernel/kgdb_fiq_entry.S @@ -0,0 +1,92 @@ +/* + * 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 + mrs r4, cpsr + msr cpsr_c, #FIQ_MODE | PSR_I_BIT | PSR_F_BIT + ldr r1, [sp, #8] + msr cpsr_c, r4 + msr spsr_cxsf, r1 + 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: