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