summaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2007-03-02 15:01:36 +0000
committerRussell King <rmk+kernel@arm.linux.org.uk>2007-04-21 20:34:34 +0100
commit7ab3f8d595a1b1e5cf8d726b72fd476fe0d0226c (patch)
treed37cf7290d5df5927ff870bfbb40673bead8f00d /arch/arm/kernel
parent46fcc86dd71d70211e965102fb69414c90381880 (diff)
[ARM] Add ability to dump exception stacks to kernel backtraces
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/irq.c2
-rw-r--r--arch/arm/kernel/traps.c18
-rw-r--r--arch/arm/kernel/vmlinux.lds.S3
3 files changed, 20 insertions, 3 deletions
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index e101846ab7d..a72b82e727f 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -109,7 +109,7 @@ static struct irq_desc bad_irq_desc = {
* come via this function. Instead, they should provide their
* own 'handler'
*/
-asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
+asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
struct irq_desc *desc = irq_desc + irq;
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 24095601359..ba1c1884e68 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -45,7 +45,18 @@ static int __init user_debug_setup(char *str)
__setup("user_debug=", user_debug_setup);
#endif
-void dump_backtrace_entry(unsigned long where, unsigned long from)
+static void dump_mem(const char *str, unsigned long bottom, unsigned long top);
+
+static inline int in_exception_text(unsigned long ptr)
+{
+ extern char __exception_text_start[];
+ extern char __exception_text_end[];
+
+ return ptr >= (unsigned long)&__exception_text_start &&
+ ptr < (unsigned long)&__exception_text_end;
+}
+
+void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)
{
#ifdef CONFIG_KALLSYMS
printk("[<%08lx>] ", where);
@@ -55,6 +66,9 @@ void dump_backtrace_entry(unsigned long where, unsigned long from)
#else
printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from);
#endif
+
+ if (in_exception_text(where))
+ dump_mem("Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs));
}
/*
@@ -266,7 +280,7 @@ void unregister_undef_hook(struct undef_hook *hook)
spin_unlock_irqrestore(&undef_lock, flags);
}
-asmlinkage void do_undefinstr(struct pt_regs *regs)
+asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
{
unsigned int correction = thumb_mode(regs) ? 2 : 4;
unsigned int instr;
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index ddbdad48f5b..b295f6a85cf 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -83,6 +83,9 @@ SECTIONS
.text : { /* Real text segment */
_text = .; /* Text and read-only data */
+ __exception_text_start = .;
+ *(.exception.text)
+ __exception_text_end = .;
*(.text)
SCHED_TEXT
LOCK_TEXT