File: /usr/src/linux/arch/ppc/kernel/traps.c
1 /*
2 * BK Id: SCCS/s.traps.c 1.19 08/24/01 20:07:37 paulus
3 */
4 /*
5 * linux/arch/ppc/kernel/traps.c
6 *
7 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 *
14 * Modified by Cort Dougan (cort@cs.nmt.edu)
15 * and Paul Mackerras (paulus@cs.anu.edu.au)
16 */
17
18 /*
19 * This file handles the architecture-dependent parts of hardware exceptions
20 */
21
22 #include <linux/errno.h>
23 #include <linux/sched.h>
24 #include <linux/kernel.h>
25 #include <linux/mm.h>
26 #include <linux/stddef.h>
27 #include <linux/unistd.h>
28 #include <linux/ptrace.h>
29 #include <linux/slab.h>
30 #include <linux/user.h>
31 #include <linux/a.out.h>
32 #include <linux/interrupt.h>
33 #include <linux/config.h>
34 #include <linux/init.h>
35
36 #include <asm/pgtable.h>
37 #include <asm/uaccess.h>
38 #include <asm/system.h>
39 #include <asm/io.h>
40 #include <asm/processor.h>
41
42 extern int fix_alignment(struct pt_regs *);
43 extern void bad_page_fault(struct pt_regs *, unsigned long, int sig);
44
45 #ifdef CONFIG_XMON
46 extern void xmon(struct pt_regs *regs);
47 extern int xmon_bpt(struct pt_regs *regs);
48 extern int xmon_sstep(struct pt_regs *regs);
49 extern int xmon_iabr_match(struct pt_regs *regs);
50 extern int xmon_dabr_match(struct pt_regs *regs);
51 extern void (*xmon_fault_handler)(struct pt_regs *regs);
52 #endif
53
54 #ifdef CONFIG_XMON
55 void (*debugger)(struct pt_regs *regs) = xmon;
56 int (*debugger_bpt)(struct pt_regs *regs) = xmon_bpt;
57 int (*debugger_sstep)(struct pt_regs *regs) = xmon_sstep;
58 int (*debugger_iabr_match)(struct pt_regs *regs) = xmon_iabr_match;
59 int (*debugger_dabr_match)(struct pt_regs *regs) = xmon_dabr_match;
60 void (*debugger_fault_handler)(struct pt_regs *regs);
61 #else
62 #ifdef CONFIG_KGDB
63 void (*debugger)(struct pt_regs *regs);
64 int (*debugger_bpt)(struct pt_regs *regs);
65 int (*debugger_sstep)(struct pt_regs *regs);
66 int (*debugger_iabr_match)(struct pt_regs *regs);
67 int (*debugger_dabr_match)(struct pt_regs *regs);
68 void (*debugger_fault_handler)(struct pt_regs *regs);
69 #endif
70 #endif
71
72 /*
73 * Trap & Exception support
74 */
75
76
77 spinlock_t oops_lock = SPIN_LOCK_UNLOCKED;
78
79 void die(const char * str, struct pt_regs * fp, long err)
80 {
81 console_verbose();
82 spin_lock_irq(&oops_lock);
83 printk("Oops: %s, sig: %ld\n", str, err);
84 show_regs(fp);
85 spin_unlock_irq(&oops_lock);
86 /* do_exit() should take care of panic'ing from an interrupt
87 * context so we don't handle it here
88 */
89 do_exit(err);
90 }
91
92 void
93 _exception(int signr, struct pt_regs *regs)
94 {
95 if (!user_mode(regs))
96 {
97 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
98 debugger(regs);
99 #endif
100 die("Exception in kernel mode", regs, signr);
101 }
102 force_sig(signr, current);
103 }
104
105 void
106 MachineCheckException(struct pt_regs *regs)
107 {
108 #ifdef CONFIG_ALL_PPC
109 unsigned long fixup;
110 #endif /* CONFIG_ALL_PPC */
111
112 if (user_mode(regs)) {
113 _exception(SIGSEGV, regs);
114 return;
115 }
116
117 #if defined(CONFIG_8xx) && defined(CONFIG_PCI)
118 /* the qspan pci read routines can cause machine checks -- Cort */
119 bad_page_fault(regs, regs->dar, SIGBUS);
120 return;
121 #endif
122 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
123 if (debugger_fault_handler) {
124 debugger_fault_handler(regs);
125 return;
126 }
127 #endif
128
129 #ifdef CONFIG_ALL_PPC
130 /*
131 * I/O accesses can cause machine checks on powermacs.
132 * Check if the NIP corresponds to the address of a sync
133 * instruction for which there is an entry in the exception
134 * table.
135 */
136 if (regs->msr & (0x80000 | 0x40000)
137 && (fixup = search_exception_table(regs->nip)) != 0) {
138 /*
139 * Check that it's a sync instruction.
140 * As the address is in the exception table
141 * we should be able to read the instr there.
142 */
143 if (*(unsigned int *)regs->nip == 0x7c0004ac) {
144 unsigned int lsi = ((unsigned int *)regs->nip)[-1];
145 int rb = (lsi >> 11) & 0x1f;
146 printk(KERN_DEBUG "%s bad port %lx at %lx\n",
147 (lsi & 0x100)? "OUT to": "IN from",
148 regs->gpr[rb] - _IO_BASE, regs->nip);
149 regs->nip = fixup;
150 return;
151 }
152 }
153 #endif /* CONFIG_ALL_PPC */
154 printk("Machine check in kernel mode.\n");
155 printk("Caused by (from SRR1=%lx): ", regs->msr);
156 switch (regs->msr & 0xF0000) {
157 case 0x80000:
158 printk("Machine check signal\n");
159 break;
160 case 0x40000:
161 printk("Transfer error ack signal\n");
162 break;
163 case 0x20000:
164 printk("Data parity error signal\n");
165 break;
166 case 0x10000:
167 printk("Address parity error signal\n");
168 break;
169 default:
170 printk("Unknown values in msr\n");
171 }
172 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
173 debugger(regs);
174 #endif
175 die("machine check", regs, SIGBUS);
176 }
177
178 void
179 SMIException(struct pt_regs *regs)
180 {
181 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
182 {
183 debugger(regs);
184 return;
185 }
186 #endif
187 show_regs(regs);
188 panic("System Management Interrupt");
189 }
190
191 void
192 UnknownException(struct pt_regs *regs)
193 {
194 printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
195 regs->nip, regs->msr, regs->trap);
196 _exception(SIGTRAP, regs);
197 }
198
199 void
200 InstructionBreakpoint(struct pt_regs *regs)
201 {
202 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
203 if (debugger_iabr_match(regs))
204 return;
205 #endif
206 _exception(SIGTRAP, regs);
207 }
208
209 void
210 RunModeException(struct pt_regs *regs)
211 {
212 _exception(SIGTRAP, regs);
213 }
214
215 /* Illegal instruction emulation support. Originally written to
216 * provide the PVR to user applications using the mfspr rd, PVR.
217 * Return non-zero if we can't emulate, or EFAULT if the associated
218 * memory access caused an access fault. Return zero on success.
219 *
220 * There are a couple of ways to do this, either "decode" the instruction
221 * or directly match lots of bits. In this case, matching lots of
222 * bits is faster and easier.
223 *
224 */
225 #define INST_MFSPR_PVR 0x7c1f42a6
226 #define INST_MFSPR_PVR_MASK 0xfc1fffff
227
228 static int
229 emulate_instruction(struct pt_regs *regs)
230 {
231 uint instword;
232 uint rd;
233 uint retval;
234
235 retval = EINVAL;
236
237 if (!user_mode(regs))
238 return retval;
239
240 if (get_user(instword, (uint *)(regs->nip)))
241 return -EFAULT;
242
243 /* Emulate the mfspr rD, PVR.
244 */
245 if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
246 rd = (instword >> 21) & 0x1f;
247 regs->gpr[rd] = mfspr(PVR);
248 retval = 0;
249 }
250 if (retval == 0)
251 regs->nip += 4;
252 return(retval);
253 }
254
255 void
256 ProgramCheckException(struct pt_regs *regs)
257 {
258 #if defined(CONFIG_4xx)
259 unsigned int esr = mfspr(SPRN_ESR);
260
261 if (esr & ESR_PTR) {
262 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
263 if (debugger_bpt(regs))
264 return;
265 #endif
266 _exception(SIGTRAP, regs);
267 } else {
268 _exception(SIGILL, regs);
269 }
270 #else
271 if (regs->msr & 0x100000) {
272 /* IEEE FP exception */
273 _exception(SIGFPE, regs);
274 } else if (regs->msr & 0x20000) {
275 /* trap exception */
276 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
277 if (debugger_bpt(regs))
278 return;
279 #endif
280 _exception(SIGTRAP, regs);
281 } else {
282 /* Try to emulate it if we should. */
283 int errcode;
284 if ((errcode = emulate_instruction(regs))) {
285 if (errcode == -EFAULT)
286 _exception(SIGBUS, regs);
287 else
288 _exception(SIGILL, regs);
289 }
290 }
291 #endif
292 }
293
294 void
295 SingleStepException(struct pt_regs *regs)
296 {
297 regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */
298 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
299 if (debugger_sstep(regs))
300 return;
301 #endif
302 _exception(SIGTRAP, regs);
303 }
304
305 void
306 AlignmentException(struct pt_regs *regs)
307 {
308 int fixed;
309
310 fixed = fix_alignment(regs);
311 if (fixed == 1) {
312 regs->nip += 4; /* skip over emulated instruction */
313 return;
314 }
315 if (fixed == -EFAULT) {
316 /* fixed == -EFAULT means the operand address was bad */
317 if (user_mode(regs))
318 force_sig(SIGSEGV, current);
319 else
320 bad_page_fault(regs, regs->dar, SIGSEGV);
321 return;
322 }
323 _exception(SIGBUS, regs);
324 }
325
326 void
327 StackOverflow(struct pt_regs *regs)
328 {
329 printk(KERN_CRIT "Kernel stack overflow in process %p, r1=%lx\n",
330 current, regs->gpr[1]);
331 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
332 debugger(regs);
333 #endif
334 show_regs(regs);
335 panic("kernel stack overflow");
336 }
337
338 void
339 trace_syscall(struct pt_regs *regs)
340 {
341 printk("Task: %p(%d), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld\n",
342 current, current->pid, regs->nip, regs->link, regs->gpr[0],
343 regs->ccr&0x10000000?"Error=":"", regs->gpr[3]);
344 }
345
346 #ifdef CONFIG_8xx
347 void
348 SoftwareEmulation(struct pt_regs *regs)
349 {
350 extern int do_mathemu(struct pt_regs *);
351 int errcode;
352
353 if (!user_mode(regs)) {
354 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
355 debugger(regs);
356 #endif
357 die("Kernel Mode Software FPU Emulation", regs, SIGFPE);
358 }
359
360 #ifdef CONFIG_MATH_EMULATION
361 if ((errcode = do_mathemu(regs))) {
362 #else
363 if ((errcode = Soft_emulate_8xx(regs))) {
364 #endif
365 if (errcode > 0)
366 _exception(SIGFPE, regs);
367 else if (errcode == -EFAULT)
368 _exception(SIGSEGV, regs);
369 else
370 _exception(SIGILL, regs);
371 }
372 }
373 #endif
374
375 #if !defined(CONFIG_TAU_INT)
376 void
377 TAUException(struct pt_regs *regs)
378 {
379 printk("TAU trap at PC: %lx, SR: %lx, vector=%lx\n",
380 regs->nip, regs->msr, regs->trap);
381 }
382 #endif /* CONFIG_INT_TAU */
383
384 void __init trap_init(void)
385 {
386 }
387