diff options
Diffstat (limited to 'arch/sh/kernel/traps.c')
-rw-r--r-- | arch/sh/kernel/traps.c | 73 |
1 files changed, 37 insertions, 36 deletions
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index e9f168f60f95..7b40f0ff3dfc 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c | |||
@@ -5,7 +5,7 @@ | |||
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 - 2006 Paul Mundt | 8 | * Copyright (C) 2002 - 2007 Paul Mundt |
9 | * | 9 | * |
10 | * This file is subject to the terms and conditions of the GNU General Public | 10 | * This file is subject to the terms and conditions of the GNU General Public |
11 | * License. See the file "COPYING" in the main directory of this archive | 11 | * License. See the file "COPYING" in the main directory of this archive |
@@ -18,10 +18,12 @@ | |||
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/kallsyms.h> | 19 | #include <linux/kallsyms.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/bug.h> | ||
21 | #include <linux/debug_locks.h> | 22 | #include <linux/debug_locks.h> |
22 | #include <linux/limits.h> | 23 | #include <linux/limits.h> |
23 | #include <asm/system.h> | 24 | #include <asm/system.h> |
24 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
26 | #include <asm/kdebug.h> | ||
25 | 27 | ||
26 | #ifdef CONFIG_SH_KGDB | 28 | #ifdef CONFIG_SH_KGDB |
27 | #include <asm/kgdb.h> | 29 | #include <asm/kgdb.h> |
@@ -74,7 +76,21 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top) | |||
74 | } | 76 | } |
75 | } | 77 | } |
76 | 78 | ||
77 | DEFINE_SPINLOCK(die_lock); | 79 | ATOMIC_NOTIFIER_HEAD(shdie_chain); |
80 | |||
81 | int register_die_notifier(struct notifier_block *nb) | ||
82 | { | ||
83 | return atomic_notifier_chain_register(&shdie_chain, nb); | ||
84 | } | ||
85 | EXPORT_SYMBOL(register_die_notifier); | ||
86 | |||
87 | int unregister_die_notifier(struct notifier_block *nb) | ||
88 | { | ||
89 | return atomic_notifier_chain_unregister(&shdie_chain, nb); | ||
90 | } | ||
91 | EXPORT_SYMBOL(unregister_die_notifier); | ||
92 | |||
93 | static DEFINE_SPINLOCK(die_lock); | ||
78 | 94 | ||
79 | void die(const char * str, struct pt_regs * regs, long err) | 95 | void die(const char * str, struct pt_regs * regs, long err) |
80 | { | 96 | { |
@@ -130,40 +146,6 @@ static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err) | |||
130 | return -EFAULT; | 146 | return -EFAULT; |
131 | } | 147 | } |
132 | 148 | ||
133 | #ifdef CONFIG_BUG | ||
134 | #ifdef CONFIG_DEBUG_BUGVERBOSE | ||
135 | static inline void do_bug_verbose(struct pt_regs *regs) | ||
136 | { | ||
137 | struct bug_frame f; | ||
138 | long len; | ||
139 | |||
140 | if (__copy_from_user(&f, (const void __user *)regs->pc, | ||
141 | sizeof(struct bug_frame))) | ||
142 | return; | ||
143 | |||
144 | len = __strnlen_user(f.file, PATH_MAX) - 1; | ||
145 | if (unlikely(len < 0 || len >= PATH_MAX)) | ||
146 | f.file = "<bad filename>"; | ||
147 | len = __strnlen_user(f.func, PATH_MAX) - 1; | ||
148 | if (unlikely(len < 0 || len >= PATH_MAX)) | ||
149 | f.func = "<bad function>"; | ||
150 | |||
151 | printk(KERN_ALERT "kernel BUG in %s() at %s:%d!\n", | ||
152 | f.func, f.file, f.line); | ||
153 | } | ||
154 | #else | ||
155 | static inline void do_bug_verbose(struct pt_regs *regs) | ||
156 | { | ||
157 | } | ||
158 | #endif /* CONFIG_DEBUG_BUGVERBOSE */ | ||
159 | |||
160 | void handle_BUG(struct pt_regs *regs) | ||
161 | { | ||
162 | do_bug_verbose(regs); | ||
163 | die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff); | ||
164 | } | ||
165 | #endif /* CONFIG_BUG */ | ||
166 | |||
167 | /* | 149 | /* |
168 | * handle an instruction that does an unaligned memory access by emulating the | 150 | * handle an instruction that does an unaligned memory access by emulating the |
169 | * desired behaviour | 151 | * desired behaviour |
@@ -888,6 +870,25 @@ void __init trap_init(void) | |||
888 | per_cpu_trap_init(); | 870 | per_cpu_trap_init(); |
889 | } | 871 | } |
890 | 872 | ||
873 | #ifdef CONFIG_BUG | ||
874 | void handle_BUG(struct pt_regs *regs) | ||
875 | { | ||
876 | enum bug_trap_type tt; | ||
877 | tt = report_bug(regs->pc); | ||
878 | if (tt == BUG_TRAP_TYPE_WARN) { | ||
879 | regs->pc += 2; | ||
880 | return; | ||
881 | } | ||
882 | |||
883 | die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff); | ||
884 | } | ||
885 | |||
886 | int is_valid_bugaddr(unsigned long addr) | ||
887 | { | ||
888 | return addr >= PAGE_OFFSET; | ||
889 | } | ||
890 | #endif | ||
891 | |||
891 | void show_trace(struct task_struct *tsk, unsigned long *sp, | 892 | void show_trace(struct task_struct *tsk, unsigned long *sp, |
892 | struct pt_regs *regs) | 893 | struct pt_regs *regs) |
893 | { | 894 | { |