aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/cris/arch-v10/kernel/traps.c198
1 files changed, 95 insertions, 103 deletions
diff --git a/arch/cris/arch-v10/kernel/traps.c b/arch/cris/arch-v10/kernel/traps.c
index 4becc1bcced9..9eada5d8893b 100644
--- a/arch/cris/arch-v10/kernel/traps.c
+++ b/arch/cris/arch-v10/kernel/traps.c
@@ -1,13 +1,10 @@
1/* $Id: traps.c,v 1.4 2005/04/24 18:47:55 starvik Exp $ 1/*
2 * Helper functions for trap handlers
2 * 3 *
3 * linux/arch/cris/arch-v10/traps.c 4 * Copyright (C) 2000-2007, Axis Communications AB.
4 * 5 *
5 * Heler functions for trap handlers 6 * Authors: Bjorn Wesen
6 * 7 * Hans-Peter Nilsson
7 * Copyright (C) 2000-2002 Axis Communications AB
8 *
9 * Authors: Bjorn Wesen
10 * Hans-Peter Nilsson
11 * 8 *
12 */ 9 */
13 10
@@ -15,124 +12,119 @@
15#include <asm/uaccess.h> 12#include <asm/uaccess.h>
16#include <asm/arch/sv_addr_ag.h> 13#include <asm/arch/sv_addr_ag.h>
17 14
18extern int raw_printk(const char *fmt, ...); 15void
19 16show_registers(struct pt_regs *regs)
20void
21show_registers(struct pt_regs * regs)
22{ 17{
23 /* We either use rdusp() - the USP register, which might not 18 /*
24 correspond to the current process for all cases we're called, 19 * It's possible to use either the USP register or current->thread.usp.
25 or we use the current->thread.usp, which is not up to date for 20 * USP might not correspond to the current process for all cases this
26 the current process. Experience shows we want the USP 21 * function is called, and current->thread.usp isn't up to date for the
27 register. */ 22 * current process. Experience shows that using USP is the way to go.
23 */
28 unsigned long usp = rdusp(); 24 unsigned long usp = rdusp();
29 25
30 raw_printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n", 26 printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n",
31 regs->irp, regs->srp, regs->dccr, usp, regs->mof ); 27 regs->irp, regs->srp, regs->dccr, usp, regs->mof);
32 raw_printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n", 28
29 printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n",
33 regs->r0, regs->r1, regs->r2, regs->r3); 30 regs->r0, regs->r1, regs->r2, regs->r3);
34 raw_printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n", 31
32 printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n",
35 regs->r4, regs->r5, regs->r6, regs->r7); 33 regs->r4, regs->r5, regs->r6, regs->r7);
36 raw_printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n", 34
35 printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n",
37 regs->r8, regs->r9, regs->r10, regs->r11); 36 regs->r8, regs->r9, regs->r10, regs->r11);
38 raw_printk("r12: %08lx r13: %08lx oR10: %08lx sp: %08lx\n", 37
39 regs->r12, regs->r13, regs->orig_r10, regs); 38 printk("r12: %08lx r13: %08lx oR10: %08lx sp: %08lx\n",
40 raw_printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE); 39 regs->r12, regs->r13, regs->orig_r10, (long unsigned)regs);
41 raw_printk("Process %s (pid: %d, stackpage=%08lx)\n", 40
41 printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE);
42
43 printk("Process %s (pid: %d, stackpage=%08lx)\n",
42 current->comm, current->pid, (unsigned long)current); 44 current->comm, current->pid, (unsigned long)current);
43 45
44 /* 46 /*
45 * When in-kernel, we also print out the stack and code at the 47 * When in-kernel, we also print out the stack and code at the
46 * time of the fault.. 48 * time of the fault..
47 */ 49 */
48 if (! user_mode(regs)) { 50 if (!user_mode(regs)) {
49 int i; 51 int i;
50 52
51 show_stack(NULL, (unsigned long*)usp); 53 show_stack(NULL, (unsigned long *)usp);
52 54
53 /* Dump kernel stack if the previous dump wasn't one. */ 55 /*
56 * If the previous stack-dump wasn't a kernel one, dump the
57 * kernel stack now.
58 */
54 if (usp != 0) 59 if (usp != 0)
55 show_stack (NULL, NULL); 60 show_stack(NULL, NULL);
56 61
57 raw_printk("\nCode: "); 62 printk("\nCode: ");
58 if(regs->irp < PAGE_OFFSET) 63
59 goto bad; 64 if (regs->irp < PAGE_OFFSET)
60 65 goto bad_value;
61 /* Often enough the value at regs->irp does not point to 66
62 the interesting instruction, which is most often the 67 /*
63 _previous_ instruction. So we dump at an offset large 68 * Quite often the value at regs->irp doesn't point to the
64 enough that instruction decoding should be in sync at 69 * interesting instruction, which often is the previous
65 the interesting point, but small enough to fit on a row 70 * instruction. So dump at an offset large enough that the
66 (sort of). We point out the regs->irp location in a 71 * instruction decoding should be in sync at the interesting
67 ksymoops-friendly way by wrapping the byte for that 72 * point, but small enough to fit on a row. The regs->irp
68 address in parentheses. */ 73 * location is pointed out in a ksymoops-friendly way by
69 for(i = -12; i < 12; i++) 74 * wrapping the byte for that address in parenthesises.
70 { 75 */
71 unsigned char c; 76 for (i = -12; i < 12; i++) {
72 if(__get_user(c, &((unsigned char*)regs->irp)[i])) { 77 unsigned char c;
73bad: 78
74 raw_printk(" Bad IP value."); 79 if (__get_user(c, &((unsigned char *)regs->irp)[i])) {
75 break; 80bad_value:
76 } 81 printk(" Bad IP value.");
82 break;
83 }
77 84
78 if (i == 0) 85 if (i == 0)
79 raw_printk("(%02x) ", c); 86 printk("(%02x) ", c);
80 else 87 else
81 raw_printk("%02x ", c); 88 printk("%02x ", c);
82 } 89 }
83 raw_printk("\n"); 90 printk("\n");
84 } 91 }
85} 92}
86 93
87/* Called from entry.S when the watchdog has bitten
88 * We print out something resembling an oops dump, and if
89 * we have the nice doggy development flag set, we halt here
90 * instead of rebooting.
91 */
92
93extern void reset_watchdog(void);
94extern void stop_watchdog(void);
95
96
97void 94void
98watchdog_bite_hook(struct pt_regs *regs) 95arch_enable_nmi(void)
99{ 96{
100#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY 97 asm volatile ("setf m");
101 local_irq_disable();
102 stop_watchdog();
103 show_registers(regs);
104 while(1) /* nothing */;
105#else
106 show_registers(regs);
107#endif
108} 98}
109 99
110/* This is normally the 'Oops' routine */ 100extern void (*nmi_handler)(struct pt_regs *);
111void 101void handle_nmi(struct pt_regs *regs)
112die_if_kernel(const char * str, struct pt_regs * regs, long err)
113{ 102{
114 if(user_mode(regs)) 103 if (nmi_handler)
115 return; 104 nmi_handler(regs);
116 105
117#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY 106 /* Wait until nmi is no longer active. (We enable NMI immediately after
118 /* This printout might take too long and trigger the 107 returning from this function, and we don't want it happening while
119 * watchdog normally. If we're in the nice doggy 108 exiting from the NMI interrupt handler.) */
120 * development mode, stop the watchdog during printout. 109 while (*R_IRQ_MASK0_RD & IO_STATE(R_IRQ_MASK0_RD, nmi_pin, active))
121 */ 110 ;
122 stop_watchdog();
123#endif
124
125 raw_printk("%s: %04lx\n", str, err & 0xffff);
126
127 show_registers(regs);
128
129#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
130 reset_watchdog();
131#endif
132 do_exit(SIGSEGV);
133} 111}
134 112
135void arch_enable_nmi(void) 113#ifdef CONFIG_DEBUG_BUGVERBOSE
114void
115handle_BUG(struct pt_regs *regs)
136{ 116{
137 asm volatile("setf m"); 117 struct bug_frame f;
118 unsigned char c;
119 unsigned long irp = regs->irp;
120
121 if (__copy_from_user(&f, (const void __user *)(irp - 8), sizeof f))
122 return;
123 if (f.prefix != BUG_PREFIX || f.magic != BUG_MAGIC)
124 return;
125 if (__get_user(c, f.filename))
126 f.filename = "<bad filename>";
127
128 printk("kernel BUG at %s:%d!\n", f.filename, f.line);
138} 129}
130#endif