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