diff options
author | Helge Deller <deller@gmx.de> | 2006-12-16 10:16:50 -0500 |
---|---|---|
committer | Kyle McMartin <kyle@athena.road.mcmartin.ca> | 2007-02-17 00:51:46 -0500 |
commit | 6891f8a1135b964f8ef30521d1473d5d137af0fa (patch) | |
tree | d9b7d1e240107dc25fb864b81dbc6fc4bdc5895b /arch/parisc/kernel/traps.c | |
parent | 9f15c82686251cd2b97ac6859de62959d3c4afe1 (diff) |
[PARISC] Generic BUG
Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
Diffstat (limited to 'arch/parisc/kernel/traps.c')
-rw-r--r-- | arch/parisc/kernel/traps.c | 85 |
1 files changed, 38 insertions, 47 deletions
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 949722540864..ea0eff91db4e 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/console.h> | 27 | #include <linux/console.h> |
28 | #include <linux/kallsyms.h> | 28 | #include <linux/kallsyms.h> |
29 | #include <linux/bug.h> | ||
29 | 30 | ||
30 | #include <asm/assembly.h> | 31 | #include <asm/assembly.h> |
31 | #include <asm/system.h> | 32 | #include <asm/system.h> |
@@ -51,7 +52,7 @@ | |||
51 | DEFINE_SPINLOCK(pa_dbit_lock); | 52 | DEFINE_SPINLOCK(pa_dbit_lock); |
52 | #endif | 53 | #endif |
53 | 54 | ||
54 | int printbinary(char *buf, unsigned long x, int nbits) | 55 | static int printbinary(char *buf, unsigned long x, int nbits) |
55 | { | 56 | { |
56 | unsigned long mask = 1UL << (nbits - 1); | 57 | unsigned long mask = 1UL << (nbits - 1); |
57 | while (mask != 0) { | 58 | while (mask != 0) { |
@@ -207,6 +208,11 @@ HERE: | |||
207 | do_show_stack(&info); | 208 | do_show_stack(&info); |
208 | } | 209 | } |
209 | 210 | ||
211 | int is_valid_bugaddr(unsigned long iaoq) | ||
212 | { | ||
213 | return 1; | ||
214 | } | ||
215 | |||
210 | void die_if_kernel(char *str, struct pt_regs *regs, long err) | 216 | void die_if_kernel(char *str, struct pt_regs *regs, long err) |
211 | { | 217 | { |
212 | if (user_mode(regs)) { | 218 | if (user_mode(regs)) { |
@@ -225,7 +231,7 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) | |||
225 | oops_in_progress = 1; | 231 | oops_in_progress = 1; |
226 | 232 | ||
227 | /* Amuse the user in a SPARC fashion */ | 233 | /* Amuse the user in a SPARC fashion */ |
228 | printk( | 234 | if (err) printk( |
229 | " _______________________________ \n" | 235 | " _______________________________ \n" |
230 | " < Your System ate a SPARC! Gah! >\n" | 236 | " < Your System ate a SPARC! Gah! >\n" |
231 | " ------------------------------- \n" | 237 | " ------------------------------- \n" |
@@ -245,8 +251,9 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) | |||
245 | if (!console_drivers) | 251 | if (!console_drivers) |
246 | pdc_console_restart(); | 252 | pdc_console_restart(); |
247 | 253 | ||
248 | printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n", | 254 | if (err) |
249 | current->comm, current->pid, str, err); | 255 | printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n", |
256 | current->comm, current->pid, str, err); | ||
250 | show_regs(regs); | 257 | show_regs(regs); |
251 | 258 | ||
252 | if (in_interrupt()) | 259 | if (in_interrupt()) |
@@ -276,61 +283,45 @@ int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs) | |||
276 | 283 | ||
277 | /* gdb uses break 4,8 */ | 284 | /* gdb uses break 4,8 */ |
278 | #define GDB_BREAK_INSN 0x10004 | 285 | #define GDB_BREAK_INSN 0x10004 |
279 | void handle_gdb_break(struct pt_regs *regs, int wot) | 286 | static void handle_gdb_break(struct pt_regs *regs, int wot) |
280 | { | 287 | { |
281 | struct siginfo si; | 288 | struct siginfo si; |
282 | 289 | ||
283 | si.si_code = wot; | ||
284 | si.si_addr = (void __user *) (regs->iaoq[0] & ~3); | ||
285 | si.si_signo = SIGTRAP; | 290 | si.si_signo = SIGTRAP; |
286 | si.si_errno = 0; | 291 | si.si_errno = 0; |
292 | si.si_code = wot; | ||
293 | si.si_addr = (void __user *) (regs->iaoq[0] & ~3); | ||
287 | force_sig_info(SIGTRAP, &si, current); | 294 | force_sig_info(SIGTRAP, &si, current); |
288 | } | 295 | } |
289 | 296 | ||
290 | void handle_break(unsigned iir, struct pt_regs *regs) | 297 | static void handle_break(struct pt_regs *regs) |
291 | { | 298 | { |
292 | struct siginfo si; | 299 | unsigned iir = regs->iir; |
293 | 300 | ||
294 | switch(iir) { | 301 | if (unlikely(iir == PARISC_BUG_BREAK_INSN && !user_mode(regs))) { |
295 | case 0x00: | 302 | /* check if a BUG() or WARN() trapped here. */ |
296 | #ifdef PRINT_USER_FAULTS | 303 | enum bug_trap_type tt; |
297 | printk(KERN_DEBUG "break 0,0: pid=%d command='%s'\n", | 304 | tt = report_bug(regs->iaoq[0] & ~3); |
298 | current->pid, current->comm); | 305 | if (tt == BUG_TRAP_TYPE_WARN) { |
299 | #endif | 306 | regs->iaoq[0] += 4; |
300 | die_if_kernel("Breakpoint", regs, 0); | 307 | regs->iaoq[1] += 4; |
301 | #ifdef PRINT_USER_FAULTS | 308 | return; /* return to next instruction when WARN_ON(). */ |
302 | show_regs(regs); | 309 | } |
303 | #endif | 310 | die_if_kernel("Unknown kernel breakpoint", regs, |
304 | si.si_code = TRAP_BRKPT; | 311 | (tt == BUG_TRAP_TYPE_NONE) ? 9 : 0); |
305 | si.si_addr = (void __user *) (regs->iaoq[0] & ~3); | 312 | } |
306 | si.si_signo = SIGTRAP; | ||
307 | force_sig_info(SIGTRAP, &si, current); | ||
308 | break; | ||
309 | |||
310 | case GDB_BREAK_INSN: | ||
311 | die_if_kernel("Breakpoint", regs, 0); | ||
312 | handle_gdb_break(regs, TRAP_BRKPT); | ||
313 | break; | ||
314 | 313 | ||
315 | default: | ||
316 | #ifdef PRINT_USER_FAULTS | 314 | #ifdef PRINT_USER_FAULTS |
317 | printk(KERN_DEBUG "break %#08x: pid=%d command='%s'\n", | 315 | if (unlikely(iir != GDB_BREAK_INSN)) { |
318 | iir, current->pid, current->comm); | 316 | printk(KERN_DEBUG "break %d,%d: pid=%d command='%s'\n", |
317 | (iir>>13) & ((1<<13)-1), iir & 31, | ||
318 | current->pid, current->comm); | ||
319 | show_regs(regs); | 319 | show_regs(regs); |
320 | #endif | ||
321 | si.si_signo = SIGTRAP; | ||
322 | si.si_code = TRAP_BRKPT; | ||
323 | si.si_addr = (void __user *) (regs->iaoq[0] & ~3); | ||
324 | force_sig_info(SIGTRAP, &si, current); | ||
325 | return; | ||
326 | } | 320 | } |
327 | } | 321 | #endif |
328 | |||
329 | 322 | ||
330 | int handle_toc(void) | 323 | /* send standard GDB signal */ |
331 | { | 324 | handle_gdb_break(regs, TRAP_BRKPT); |
332 | printk(KERN_CRIT "TOC call.\n"); | ||
333 | return 0; | ||
334 | } | 325 | } |
335 | 326 | ||
336 | static void default_trap(int code, struct pt_regs *regs) | 327 | static void default_trap(int code, struct pt_regs *regs) |
@@ -339,7 +330,7 @@ static void default_trap(int code, struct pt_regs *regs) | |||
339 | show_regs(regs); | 330 | show_regs(regs); |
340 | } | 331 | } |
341 | 332 | ||
342 | void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap; | 333 | void (*cpu_lpmc) (int code, struct pt_regs *regs) __read_mostly = default_trap; |
343 | 334 | ||
344 | 335 | ||
345 | void transfer_pim_to_trap_frame(struct pt_regs *regs) | 336 | void transfer_pim_to_trap_frame(struct pt_regs *regs) |
@@ -576,7 +567,7 @@ void handle_interruption(int code, struct pt_regs *regs) | |||
576 | 567 | ||
577 | case 9: | 568 | case 9: |
578 | /* Break instruction trap */ | 569 | /* Break instruction trap */ |
579 | handle_break(regs->iir,regs); | 570 | handle_break(regs); |
580 | return; | 571 | return; |
581 | 572 | ||
582 | case 10: | 573 | case 10: |