aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/kernel/process.c12
-rw-r--r--arch/sh/kernel/traps.c124
2 files changed, 75 insertions, 61 deletions
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 91516dca4a85..a52b13ac6b7f 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -105,7 +105,7 @@ void show_regs(struct pt_regs * regs)
105{ 105{
106 printk("\n"); 106 printk("\n");
107 printk("Pid : %d, Comm: %20s\n", current->pid, current->comm); 107 printk("Pid : %d, Comm: %20s\n", current->pid, current->comm);
108 print_symbol("PC is at %s\n", regs->pc); 108 print_symbol("PC is at %s\n", instruction_pointer(regs));
109 printk("PC : %08lx SP : %08lx SR : %08lx ", 109 printk("PC : %08lx SP : %08lx SR : %08lx ",
110 regs->pc, regs->regs[15], regs->sr); 110 regs->pc, regs->regs[15], regs->sr);
111#ifdef CONFIG_MMU 111#ifdef CONFIG_MMU
@@ -130,15 +130,7 @@ void show_regs(struct pt_regs * regs)
130 printk("MACH: %08lx MACL: %08lx GBR : %08lx PR : %08lx\n", 130 printk("MACH: %08lx MACL: %08lx GBR : %08lx PR : %08lx\n",
131 regs->mach, regs->macl, regs->gbr, regs->pr); 131 regs->mach, regs->macl, regs->gbr, regs->pr);
132 132
133 /* 133 show_trace(NULL, (unsigned long *)regs->regs[15], regs);
134 * If we're in kernel mode, dump the stack too..
135 */
136 if (!user_mode(regs)) {
137 extern void show_task(unsigned long *sp);
138 unsigned long sp = regs->regs[15];
139
140 show_task((unsigned long *)sp);
141 }
142} 134}
143 135
144/* 136/*
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index c2c597e09482..ffe127f09f3e 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -1,16 +1,15 @@
1/* $Id: traps.c,v 1.17 2004/05/02 01:46:30 sugioka Exp $ 1/*
2 * 2 * 'traps.c' handles hardware traps and faults after we have saved some
3 * linux/arch/sh/traps.c 3 * state in 'entry.S'.
4 * 4 *
5 * SuperH version: Copyright (C) 1999 Niibe Yutaka 5 * SuperH version: Copyright (C) 1999 Niibe Yutaka
6 * Copyright (C) 2000 Philipp Rumpf 6 * Copyright (C) 2000 Philipp Rumpf
7 * Copyright (C) 2000 David Howells 7 * Copyright (C) 2000 David Howells
8 * Copyright (C) 2002, 2003 Paul Mundt 8 * Copyright (C) 2002 - 2006 Paul Mundt
9 */ 9 *
10 10 * This file is subject to the terms and conditions of the GNU General Public
11/* 11 * License. See the file "COPYING" in the main directory of this archive
12 * 'Traps.c' handles hardware traps and faults after we have saved some 12 * for more details.
13 * state in 'entry.S'.
14 */ 13 */
15#include <linux/sched.h> 14#include <linux/sched.h>
16#include <linux/kernel.h> 15#include <linux/kernel.h>
@@ -53,13 +52,32 @@
53#define TRAP_ILLEGAL_SLOT_INST 13 52#define TRAP_ILLEGAL_SLOT_INST 13
54#endif 53#endif
55 54
56/* 55static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
57 * These constants are for searching for possible module text 56{
58 * segments. VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is 57 unsigned long p;
59 * a guess of how much space is likely to be vmalloced. 58 int i;
60 */ 59
61#define VMALLOC_OFFSET (8*1024*1024) 60 printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
62#define MODULE_RANGE (8*1024*1024) 61
62 for (p = bottom & ~31; p < top; ) {
63 printk("%04lx: ", p & 0xffff);
64
65 for (i = 0; i < 8; i++, p += 4) {
66 unsigned int val;
67
68 if (p < bottom || p >= top)
69 printk(" ");
70 else {
71 if (__get_user(val, (unsigned int __user *)p)) {
72 printk("\n");
73 return;
74 }
75 printk("%08x ", val);
76 }
77 }
78 printk("\n");
79 }
80}
63 81
64DEFINE_SPINLOCK(die_lock); 82DEFINE_SPINLOCK(die_lock);
65 83
@@ -69,14 +87,28 @@ void die(const char * str, struct pt_regs * regs, long err)
69 87
70 console_verbose(); 88 console_verbose();
71 spin_lock_irq(&die_lock); 89 spin_lock_irq(&die_lock);
90 bust_spinlocks(1);
91
72 printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); 92 printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
93
73 CHK_REMOTE_DEBUG(regs); 94 CHK_REMOTE_DEBUG(regs);
95 print_modules();
74 show_regs(regs); 96 show_regs(regs);
97
98 printk("Process: %s (pid: %d, stack limit = %p)\n",
99 current->comm, current->pid, task_stack_page(current) + 1);
100
101 if (!user_mode(regs) || in_interrupt())
102 dump_mem("Stack: ", regs->regs[15], THREAD_SIZE +
103 (unsigned long)task_stack_page(current));
104
105 bust_spinlocks(0);
75 spin_unlock_irq(&die_lock); 106 spin_unlock_irq(&die_lock);
76 do_exit(SIGSEGV); 107 do_exit(SIGSEGV);
77} 108}
78 109
79static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err) 110static inline void die_if_kernel(const char *str, struct pt_regs *regs,
111 long err)
80{ 112{
81 if (!user_mode(regs)) 113 if (!user_mode(regs))
82 die(str, regs, err); 114 die(str, regs, err);
@@ -93,8 +125,7 @@ static int handle_unaligned_notify_count = 10;
93 */ 125 */
94static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err) 126static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
95{ 127{
96 if (!user_mode(regs)) 128 if (!user_mode(regs)) {
97 {
98 const struct exception_table_entry *fixup; 129 const struct exception_table_entry *fixup;
99 fixup = search_exception_tables(regs->pc); 130 fixup = search_exception_tables(regs->pc);
100 if (fixup) { 131 if (fixup) {
@@ -734,52 +765,43 @@ void __init trap_init(void)
734 per_cpu_trap_init(); 765 per_cpu_trap_init();
735} 766}
736 767
737void show_stack(struct task_struct *tsk, unsigned long *sp) 768void show_trace(struct task_struct *tsk, unsigned long *sp,
769 struct pt_regs *regs)
738{ 770{
739 unsigned long *stack, addr; 771 unsigned long addr;
740 unsigned long module_start = VMALLOC_START;
741 unsigned long module_end = VMALLOC_END;
742 int i = 1;
743 772
744 if (!tsk) 773 if (regs && user_mode(regs))
745 tsk = current; 774 return;
746 if (tsk == current)
747 sp = (unsigned long *)current_stack_pointer;
748 else
749 sp = (unsigned long *)tsk->thread.sp;
750
751 stack = sp;
752 775
753 printk("\nCall trace: "); 776 printk("\nCall trace: ");
754#ifdef CONFIG_KALLSYMS 777#ifdef CONFIG_KALLSYMS
755 printk("\n"); 778 printk("\n");
756#endif 779#endif
757 780
758 while (!kstack_end(stack)) { 781 while (!kstack_end(sp)) {
759 addr = *stack++; 782 addr = *sp++;
760 if (((addr >= (unsigned long)_text) && 783 if (kernel_text_address(addr))
761 (addr <= (unsigned long)_etext)) || 784 print_ip_sym(addr);
762 ((addr >= module_start) && (addr <= module_end))) {
763 /*
764 * For 80-columns display, 6 entry is maximum.
765 * NOTE: '[<8c00abcd>] ' consumes 13 columns .
766 */
767#ifndef CONFIG_KALLSYMS
768 if (i && ((i % 6) == 0))
769 printk("\n ");
770#endif
771 printk("[<%08lx>] ", addr);
772 print_symbol("%s\n", addr);
773 i++;
774 }
775 } 785 }
776 786
777 printk("\n"); 787 printk("\n");
778} 788}
779 789
780void show_task(unsigned long *sp) 790void show_stack(struct task_struct *tsk, unsigned long *sp)
781{ 791{
782 show_stack(NULL, sp); 792 unsigned long stack;
793
794 if (!tsk)
795 tsk = current;
796 if (tsk == current)
797 sp = (unsigned long *)current_stack_pointer;
798 else
799 sp = (unsigned long *)tsk->thread.sp;
800
801 stack = (unsigned long)sp;
802 dump_mem("Stack: ", stack, THREAD_SIZE +
803 (unsigned long)task_stack_page(tsk));
804 show_trace(tsk, sp, NULL);
783} 805}
784 806
785void dump_stack(void) 807void dump_stack(void)