2 * linux/arch/ppc/kernel/traps.c
4 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
11 * Modified by Cort Dougan (cort@cs.nmt.edu)
12 * and Paul Mackerras (paulus@cs.anu.edu.au)
16 * This file handles the architecture-dependent parts of hardware exceptions
19 #include <linux/errno.h>
20 #include <linux/sched.h>
21 #include <linux/kernel.h>
23 #include <linux/stddef.h>
24 #include <linux/unistd.h>
25 #include <linux/ptrace.h>
26 #include <linux/malloc.h>
27 #include <linux/user.h>
28 #include <linux/a.out.h>
29 #include <linux/interrupt.h>
30 #include <linux/config.h>
31 #include <linux/init.h>
33 #include <asm/pgtable.h>
34 #include <asm/uaccess.h>
35 #include <asm/system.h>
37 #include <asm/processor.h>
39 extern int fix_alignment(struct pt_regs
*);
40 extern void bad_page_fault(struct pt_regs
*, unsigned long);
43 extern void xmon(struct pt_regs
*regs
);
44 extern int xmon_bpt(struct pt_regs
*regs
);
45 extern int xmon_sstep(struct pt_regs
*regs
);
46 extern int xmon_iabr_match(struct pt_regs
*regs
);
47 extern int xmon_dabr_match(struct pt_regs
*regs
);
48 extern void (*xmon_fault_handler
)(struct pt_regs
*regs
);
52 void (*debugger
)(struct pt_regs
*regs
) = xmon
;
53 int (*debugger_bpt
)(struct pt_regs
*regs
) = xmon_bpt
;
54 int (*debugger_sstep
)(struct pt_regs
*regs
) = xmon_sstep
;
55 int (*debugger_iabr_match
)(struct pt_regs
*regs
) = xmon_iabr_match
;
56 int (*debugger_dabr_match
)(struct pt_regs
*regs
) = xmon_dabr_match
;
57 void (*debugger_fault_handler
)(struct pt_regs
*regs
);
60 void (*debugger
)(struct pt_regs
*regs
);
61 int (*debugger_bpt
)(struct pt_regs
*regs
);
62 int (*debugger_sstep
)(struct pt_regs
*regs
);
63 int (*debugger_iabr_match
)(struct pt_regs
*regs
);
64 int (*debugger_dabr_match
)(struct pt_regs
*regs
);
65 void (*debugger_fault_handler
)(struct pt_regs
*regs
);
69 * Trap & Exception support
73 _exception(int signr
, struct pt_regs
*regs
)
78 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
81 print_backtrace((unsigned long *)regs
->gpr
[1]);
82 panic("Exception in kernel pc %lx signal %d",regs
->nip
,signr
);
84 force_sig(signr
, current
);
88 MachineCheckException(struct pt_regs
*regs
)
92 #endif /* CONFIG_ALL_PPC */
94 if (user_mode(regs
)) {
95 _exception(SIGSEGV
, regs
);
99 #if defined(CONFIG_8xx) && defined(CONFIG_PCI)
100 /* the qspan pci read routines can cause machine checks -- Cort */
101 bad_page_fault(regs
, regs
->dar
);
104 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
105 if (debugger_fault_handler
) {
106 debugger_fault_handler(regs
);
111 #ifdef CONFIG_ALL_PPC
113 * I/O accesses can cause machine checks on powermacs.
114 * Check if the NIP corresponds to the address of a sync
115 * instruction for which there is an entry in the exception
118 if (regs
->msr
& (0x80000 | 0x40000)
119 && (fixup
= search_exception_table(regs
->nip
)) != 0) {
121 * Check that it's a sync instruction.
122 * As the address is in the exception table
123 * we should be able to read the instr there.
125 if (*(unsigned int *)regs
->nip
== 0x7c0004ac) {
126 unsigned int lsi
= ((unsigned int *)regs
->nip
)[-1];
127 int rb
= (lsi
>> 11) & 0x1f;
128 printk(KERN_DEBUG
"%s bad port %lx at %lx\n",
129 (lsi
& 0x100)? "OUT to": "IN from",
130 regs
->gpr
[rb
] - _IO_BASE
, regs
->nip
);
135 #endif /* CONFIG_ALL_PPC */
136 printk("Machine check in kernel mode.\n");
137 printk("Caused by (from SRR1=%lx): ", regs
->msr
);
138 switch (regs
->msr
& 0xF0000) {
140 printk("Machine check signal\n");
143 printk("Transfer error ack signal\n");
146 printk("Data parity error signal\n");
149 printk("Address parity error signal\n");
152 printk("Unknown values in msr\n");
155 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
158 print_backtrace((unsigned long *)regs
->gpr
[1]);
159 panic("machine check");
163 SMIException(struct pt_regs
*regs
)
165 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
172 print_backtrace((unsigned long *)regs
->gpr
[1]);
173 panic("System Management Interrupt");
177 UnknownException(struct pt_regs
*regs
)
179 printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
180 regs
->nip
, regs
->msr
, regs
->trap
);
181 _exception(SIGTRAP
, regs
);
185 InstructionBreakpoint(struct pt_regs
*regs
)
187 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
188 if (debugger_iabr_match(regs
))
191 _exception(SIGTRAP
, regs
);
195 RunModeException(struct pt_regs
*regs
)
197 _exception(SIGTRAP
, regs
);
200 /* Illegal instruction emulation support. Originally written to
201 * provide the PVR to user applications using the mfspr rd, PVR.
202 * Return non-zero if we can't emulate, or EFAULT if the associated
203 * memory access caused an access fault. Return zero on success.
205 * There are a couple of ways to do this, either "decode" the instruction
206 * or directly match lots of bits. In this case, matching lots of
207 * bits is faster and easier.
210 #define INST_MFSPR_PVR 0x7c1f42a6
211 #define INST_MFSPR_PVR_MASK 0xfc1fffff
214 emulate_instruction(struct pt_regs
*regs
)
222 if (!user_mode(regs
))
225 if (get_user(instword
, (uint
*)(regs
->nip
)))
228 /* Emulate the mfspr rD, PVR.
230 if ((instword
& INST_MFSPR_PVR_MASK
) == INST_MFSPR_PVR
) {
231 rd
= (instword
>> 21) & 0x1f;
232 regs
->gpr
[rd
] = _get_PVR();
241 ProgramCheckException(struct pt_regs
*regs
)
243 #if defined(CONFIG_4xx)
244 unsigned int esr
= mfspr(SPRN_ESR
);
247 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
248 if (debugger_bpt(regs
))
251 _exception(SIGTRAP
, regs
);
253 _exception(SIGILL
, regs
);
256 if (regs
->msr
& 0x100000) {
257 /* IEEE FP exception */
258 _exception(SIGFPE
, regs
);
259 } else if (regs
->msr
& 0x20000) {
261 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
262 if (debugger_bpt(regs
))
265 _exception(SIGTRAP
, regs
);
267 /* Try to emulate it if we should. */
269 if ((errcode
= emulate_instruction(regs
))) {
270 if (errcode
== EFAULT
)
271 _exception(SIGBUS
, regs
);
273 _exception(SIGILL
, regs
);
280 SingleStepException(struct pt_regs
*regs
)
282 regs
->msr
&= ~MSR_SE
; /* Turn off 'trace' bit */
283 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
284 if (debugger_sstep(regs
))
287 _exception(SIGTRAP
, regs
);
291 AlignmentException(struct pt_regs
*regs
)
295 fixed
= fix_alignment(regs
);
297 regs
->nip
+= 4; /* skip over emulated instruction */
300 if (fixed
== -EFAULT
) {
301 /* fixed == -EFAULT means the operand address was bad */
303 force_sig(SIGSEGV
, current
);
305 bad_page_fault(regs
, regs
->dar
);
308 _exception(SIGBUS
, regs
);
312 StackOverflow(struct pt_regs
*regs
)
314 printk(KERN_CRIT
"Kernel stack overflow in process %p, r1=%lx\n",
315 current
, regs
->gpr
[1]);
316 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
320 print_backtrace((unsigned long *)regs
->gpr
[1]);
321 panic("kernel stack overflow");
325 trace_syscall(struct pt_regs
*regs
)
327 printk("Task: %p(%d), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld\n",
328 current
, current
->pid
, regs
->nip
, regs
->link
, regs
->gpr
[0],
329 regs
->ccr
&0x10000000?"Error=":"", regs
->gpr
[3]);
334 SoftwareEmulation(struct pt_regs
*regs
)
336 extern int do_mathemu(struct pt_regs
*);
339 if (!user_mode(regs
)) {
341 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
344 print_backtrace((unsigned long *)regs
->gpr
[1]);
345 panic("Kernel Mode Software FPU Emulation");
348 #ifdef CONFIG_MATH_EMULATION
349 if ((errcode
= do_mathemu(regs
))) {
351 if ((errcode
= Soft_emulate_8xx(regs
))) {
354 _exception(SIGFPE
, regs
);
355 else if (errcode
== -EFAULT
)
356 _exception(SIGSEGV
, regs
);
358 _exception(SIGILL
, regs
);
364 TAUException(struct pt_regs
*regs
)
366 printk("TAU trap at PC: %lx, SR: %lx, vector=%lx\n",
367 regs
->nip
, regs
->msr
, regs
->trap
);
370 void __init
trap_init(void)