diff options
-rw-r--r-- | arch/sh/kernel/process.c | 12 | ||||
-rw-r--r-- | arch/sh/kernel/traps.c | 124 | ||||
-rw-r--r-- | include/asm-sh/processor.h | 2 |
3 files changed, 77 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 | /* | 55 | static 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 | ||
64 | DEFINE_SPINLOCK(die_lock); | 82 | DEFINE_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 | ||
79 | static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err) | 110 | static 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 | */ |
94 | static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err) | 126 | static 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 | ||
737 | void show_stack(struct task_struct *tsk, unsigned long *sp) | 768 | void 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 | ||
780 | void show_task(unsigned long *sp) | 790 | void 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 | ||
785 | void dump_stack(void) | 807 | void dump_stack(void) |
diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h index 474773853cd1..45bb74e35d32 100644 --- a/include/asm-sh/processor.h +++ b/include/asm-sh/processor.h | |||
@@ -255,6 +255,8 @@ extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs); | |||
255 | */ | 255 | */ |
256 | #define thread_saved_pc(tsk) (tsk->thread.pc) | 256 | #define thread_saved_pc(tsk) (tsk->thread.pc) |
257 | 257 | ||
258 | void show_trace(struct task_struct *tsk, unsigned long *sp, | ||
259 | struct pt_regs *regs); | ||
258 | extern unsigned long get_wchan(struct task_struct *p); | 260 | extern unsigned long get_wchan(struct task_struct *p); |
259 | 261 | ||
260 | #define KSTK_EIP(tsk) ((tsk)->thread.pc) | 262 | #define KSTK_EIP(tsk) ((tsk)->thread.pc) |