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) |
