Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[sfrench/cifs-2.6.git] / arch / cris / arch-v32 / kernel / traps.c
1 /*
2  * Copyright (C) 2003, Axis Communications AB.
3  */
4
5 #include <linux/config.h>
6 #include <linux/ptrace.h>
7 #include <asm/uaccess.h>
8
9 #include <asm/arch/hwregs/supp_reg.h>
10
11 extern void reset_watchdog(void);
12 extern void stop_watchdog(void);
13
14 extern int raw_printk(const char *fmt, ...);
15
16 void
17 show_registers(struct pt_regs *regs)
18 {
19         /*
20          * It's possible to use either the USP register or current->thread.usp.
21          * USP might not correspond to the current proccess for all cases this
22          * function is called, and current->thread.usp isn't up to date for the
23          * current proccess. Experience shows that using USP is the way to go.
24          */
25         unsigned long usp;
26         unsigned long d_mmu_cause;
27         unsigned long i_mmu_cause;
28
29         usp = rdusp();
30
31         raw_printk("CPU: %d\n", smp_processor_id());
32
33         raw_printk("ERP: %08lx SRP: %08lx  CCS: %08lx USP: %08lx MOF: %08lx\n",
34                 regs->erp, regs->srp, regs->ccs, usp, regs->mof);
35
36         raw_printk(" r0: %08lx  r1: %08lx   r2: %08lx  r3: %08lx\n",
37                 regs->r0, regs->r1, regs->r2, regs->r3);
38
39         raw_printk(" r4: %08lx  r5: %08lx   r6: %08lx  r7: %08lx\n",
40                 regs->r4, regs->r5, regs->r6, regs->r7);
41
42         raw_printk(" r8: %08lx  r9: %08lx  r10: %08lx r11: %08lx\n",
43                 regs->r8, regs->r9, regs->r10, regs->r11);
44
45         raw_printk("r12: %08lx r13: %08lx oR10: %08lx acr: %08lx\n",
46                 regs->r12, regs->r13, regs->orig_r10, regs->acr);
47
48         raw_printk("sp: %08lx\n", regs);
49
50         SUPP_BANK_SEL(BANK_IM);
51         SUPP_REG_RD(RW_MM_CAUSE, i_mmu_cause);
52
53         SUPP_BANK_SEL(BANK_DM);
54         SUPP_REG_RD(RW_MM_CAUSE, d_mmu_cause);
55
56         raw_printk("       Data MMU Cause: %08lx\n", d_mmu_cause);
57         raw_printk("Instruction MMU Cause: %08lx\n", i_mmu_cause);
58
59         raw_printk("Process %s (pid: %d, stackpage: %08lx)\n",
60                 current->comm, current->pid, (unsigned long) current);
61
62         /* Show additional info if in kernel-mode. */
63         if (!user_mode(regs)) {
64                 int i;
65                 unsigned char c;
66
67                 show_stack(NULL, (unsigned long *) usp);
68
69                 /*
70                  * If the previous stack-dump wasn't a kernel one, dump the
71                  * kernel stack now.
72                  */
73                 if (usp != 0)
74                         show_stack(NULL, NULL);
75
76                 raw_printk("\nCode: ");
77
78                 if (regs->erp < PAGE_OFFSET)
79                         goto bad_value;
80
81                 /*
82                  * Quite often the value at regs->erp doesn't point to the
83                  * interesting instruction, which often is the previous
84                  * instruction. So dump at an offset large enough that the
85                  * instruction decoding should be in sync at the interesting
86                  * point, but small enough to fit on a row. The regs->erp
87                  * location is pointed out in a ksymoops-friendly way by
88                  * wrapping the byte for that address in parenthesis.
89                  */
90                 for (i = -12; i < 12; i++) {
91                         if (__get_user(c, &((unsigned char *) regs->erp)[i])) {
92 bad_value:
93                                 raw_printk(" Bad IP value.");
94                                 break;
95                         }
96
97                         if (i == 0)
98                                 raw_printk("(%02x) ", c);
99                         else
100                                 raw_printk("%02x ", c);
101                 }
102
103                 raw_printk("\n");
104         }
105 }
106
107 /*
108  * This gets called from entry.S when the watchdog has bitten. Show something
109  * similiar to an Oops dump, and if the kernel if configured to be a nice doggy;
110  * halt instead of reboot.
111  */
112 void
113 watchdog_bite_hook(struct pt_regs *regs)
114 {
115 #ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
116         local_irq_disable();
117         stop_watchdog();
118         show_registers(regs);
119
120         while (1)
121                 ; /* Do nothing. */
122 #else
123         show_registers(regs);
124 #endif
125 }
126
127 /* This is normally the Oops function. */
128 void
129 die_if_kernel(const char *str, struct pt_regs *regs, long err)
130 {
131         if (user_mode(regs))
132                 return;
133
134 #ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
135         /*
136          * This printout might take too long and could trigger
137          * the watchdog normally. If NICE_DOGGY is set, simply
138          * stop the watchdog during the printout.
139          */
140         stop_watchdog();
141 #endif
142
143         raw_printk("%s: %04lx\n", str, err & 0xffff);
144
145         show_registers(regs);
146
147 #ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
148         reset_watchdog();
149 #endif
150
151         do_exit(SIGSEGV);
152 }
153
154 void arch_enable_nmi(void)
155 {
156         unsigned long flags;
157         local_save_flags(flags);
158         flags |= (1<<30); /* NMI M flag is at bit 30 */
159         local_irq_restore(flags);
160 }