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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
|
/*
* linux/arch/ppc/kernel/traps.c
*
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Modified by Cort Dougan (cort@cs.nmt.edu)
* and Paul Mackerras (paulus@cs.anu.edu.au)
*/
/*
* This file handles the architecture-dependent parts of hardware exceptions
*/
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/malloc.h>
#include <linux/user.h>
#include <linux/a.out.h>
#include <linux/interrupt.h>
#include <linux/config.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/processor.h>
extern int fix_alignment(struct pt_regs *);
extern void bad_page_fault(struct pt_regs *, unsigned long);
#ifdef CONFIG_XMON
extern int xmon_bpt(struct pt_regs *regs);
extern int xmon_sstep(struct pt_regs *regs);
extern void xmon(struct pt_regs *regs);
extern int xmon_iabr_match(struct pt_regs *regs);
extern void (*xmon_fault_handler)(struct pt_regs *regs);
#endif
/*
* Trap & Exception support
*/
void
trap_init(void)
{
}
void
_exception(int signr, struct pt_regs *regs)
{
if (!user_mode(regs))
{
show_regs(regs);
print_backtrace((unsigned long *)regs->gpr[1]);
#ifdef CONFIG_XMON
xmon(regs);
#endif
panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
}
force_sig(signr, current);
}
void
MachineCheckException(struct pt_regs *regs)
{
if ( !user_mode(regs) )
{
#ifdef CONFIG_XMON
if (xmon_fault_handler) {
xmon_fault_handler(regs);
return;
}
#endif
printk("Machine check in kernel mode.\n");
printk("Caused by (from msr): ");
printk("regs %p ",regs);
switch( regs->msr & 0x0000F000)
{
case (1<<12) :
printk("Machine check signal - probably due to mm fault\n"
"with mmu off\n");
break;
case (1<<13) :
printk("Transfer error ack signal\n");
break;
case (1<<14) :
printk("Data parity signal\n");
break;
case (1<<15) :
printk("Address parity signal\n");
break;
default:
printk("Unknown values in msr\n");
}
show_regs(regs);
print_backtrace((unsigned long *)regs->gpr[1]);
#ifdef CONFIG_XMON
xmon(regs);
#endif
panic("machine check");
}
_exception(SIGSEGV, regs);
}
void
UnknownException(struct pt_regs *regs)
{
printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
regs->nip, regs->msr, regs->trap);
_exception(SIGTRAP, regs);
}
void
InstructionBreakpoint(struct pt_regs *regs)
{
#ifdef CONFIG_XMON
if (xmon_iabr_match(regs))
return;
#endif
_exception(SIGTRAP, regs);
}
void
RunModeException(struct pt_regs *regs)
{
_exception(SIGTRAP, regs);
}
void
ProgramCheckException(struct pt_regs *regs)
{
if (regs->msr & 0x100000) {
/* IEEE FP exception */
_exception(SIGFPE, regs);
} else if (regs->msr & 0x20000) {
/* trap exception */
#ifdef CONFIG_XMON
if (xmon_bpt(regs))
return;
#endif
_exception(SIGTRAP, regs);
} else {
_exception(SIGILL, regs);
}
}
void
SingleStepException(struct pt_regs *regs)
{
regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */
#ifdef CONFIG_XMON
if (xmon_sstep(regs))
return;
#endif
_exception(SIGTRAP, regs);
}
void
AlignmentException(struct pt_regs *regs)
{
int fixed;
if (last_task_used_math == current)
giveup_fpu();
fixed = fix_alignment(regs);
if (fixed == 1) {
regs->nip += 4; /* skip over emulated instruction */
return;
}
if (fixed == -EFAULT) {
/* fixed == -EFAULT means the operand address was bad */
bad_page_fault(regs, regs->dar);
return;
}
_exception(SIGBUS, regs);
}
void
PromException(struct pt_regs *regs, int trap)
{
regs->trap = trap;
#ifdef CONFIG_XMON
xmon(regs);
#endif
printk("Exception %lx in prom at PC: %lx, SR: %lx\n",
regs->trap, regs->nip, regs->msr);
/* probably should turn up the toes here */
}
void
trace_syscall(struct pt_regs *regs)
{
printk("Task: %p(%d), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld\n",
current, current->pid, regs->nip, regs->link, regs->gpr[0],
regs->ccr&0x10000000?"Error=":"", regs->gpr[3]);
}
|