commented early_printk patch because of rejects.
[linux-flexiantxendom0-3.2.10.git] / arch / ppc64 / kernel / traps.c
1 /*
2  *  linux/arch/ppc64/kernel/traps.c
3  *
4  *  Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
5  *
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.
10  *
11  *  Modified by Cort Dougan (cort@cs.nmt.edu)
12  *  and Paul Mackerras (paulus@cs.anu.edu.au)
13  */
14
15 /*
16  * This file handles the architecture-dependent parts of hardware exceptions
17  */
18
19 #include <linux/errno.h>
20 #include <linux/sched.h>
21 #include <linux/kernel.h>
22 #include <linux/mm.h>
23 #include <linux/stddef.h>
24 #include <linux/unistd.h>
25 #include <linux/slab.h>
26 #include <linux/user.h>
27 #include <linux/a.out.h>
28 #include <linux/interrupt.h>
29 #include <linux/config.h>
30 #include <linux/init.h>
31 #include <linux/module.h>
32
33 #include <asm/pgtable.h>
34 #include <asm/uaccess.h>
35 #include <asm/system.h>
36 #include <asm/io.h>
37 #include <asm/processor.h>
38 #include <asm/ppcdebug.h>
39
40 extern int fix_alignment(struct pt_regs *);
41 extern void bad_page_fault(struct pt_regs *, unsigned long, int);
42
43 /* This is true if we are using the firmware NMI handler (typically LPAR) */
44 extern int fwnmi_active;
45
46 #ifdef CONFIG_DEBUG_KERNEL
47 void (*debugger)(struct pt_regs *regs);
48 int (*debugger_bpt)(struct pt_regs *regs);
49 int (*debugger_sstep)(struct pt_regs *regs);
50 int (*debugger_iabr_match)(struct pt_regs *regs);
51 int (*debugger_dabr_match)(struct pt_regs *regs);
52 void (*debugger_fault_handler)(struct pt_regs *regs);
53 #endif
54
55 /*
56  * Trap & Exception support
57  */
58
59 static spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
60
61 void die(const char *str, struct pt_regs *regs, long err)
62 {
63         static int die_counter;
64
65         console_verbose();
66         spin_lock_irq(&die_lock);
67         bust_spinlocks(1);
68         printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
69         show_regs(regs);
70         bust_spinlocks(0);
71         spin_unlock_irq(&die_lock);
72
73         if (in_interrupt())
74                 panic("Fatal exception in interrupt");
75
76         if (panic_on_oops) {
77                 printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
78                 set_current_state(TASK_UNINTERRUPTIBLE);
79                 schedule_timeout(5 * HZ);
80                 panic("Fatal exception");
81         }
82         do_exit(SIGSEGV);
83 }
84
85 static void
86 _exception(int signr, siginfo_t *info, struct pt_regs *regs)
87 {
88         if (!user_mode(regs)) {
89 #ifdef CONFIG_DEBUG_KERNEL
90                 if (debugger)
91                         debugger(regs);
92 #endif
93                 die("Exception in kernel mode\n", regs, signr);
94         }
95
96         force_sig_info(signr, info, current);
97 }
98
99 /* Get the error information for errors coming through the
100  * FWNMI vectors.  The pt_regs' r3 will be updated to reflect
101  * the actual r3 if possible, and a ptr to the error log entry
102  * will be returned if found.
103  */
104 static struct rtas_error_log *FWNMI_get_errinfo(struct pt_regs *regs)
105 {
106         unsigned long errdata = regs->gpr[3];
107         struct rtas_error_log *errhdr = NULL;
108         unsigned long *savep;
109
110         if ((errdata >= 0x7000 && errdata < 0x7fff0) ||
111             (errdata >= rtas.base && errdata < rtas.base + rtas.size - 16)) {
112                 savep = __va(errdata);
113                 regs->gpr[3] = savep[0];        /* restore original r3 */
114                 errhdr = (struct rtas_error_log *)(savep + 1);
115         } else {
116                 printk("FWNMI: corrupt r3\n");
117         }
118         return errhdr;
119 }
120
121 /* Call this when done with the data returned by FWNMI_get_errinfo.
122  * It will release the saved data area for other CPUs in the
123  * partition to receive FWNMI errors.
124  */
125 static void FWNMI_release_errinfo(void)
126 {
127         unsigned long ret = rtas_call(rtas_token("ibm,nmi-interlock"), 0, 1, NULL);
128         if (ret != 0)
129                 printk("FWNMI: nmi-interlock failed: %ld\n", ret);
130 }
131
132 void
133 SystemResetException(struct pt_regs *regs)
134 {
135         if (fwnmi_active) {
136                 struct rtas_error_log *errhdr = FWNMI_get_errinfo(regs);
137                 if (errhdr) {
138                         /* XXX Should look at FWNMI information */
139                 }
140                 FWNMI_release_errinfo();
141         }
142
143 #ifdef CONFIG_DEBUG_KERNEL
144         if (debugger)
145                 debugger(regs);
146         else
147 #endif
148                 panic("System Reset");
149
150         /* Must die if the interrupt is not recoverable */
151         if (!(regs->msr & MSR_RI))
152                 panic("Unrecoverable System Reset");
153
154         /* What should we do here? We could issue a shutdown or hard reset. */
155 }
156
157 /* 
158  * See if we can recover from a machine check exception.
159  * This is only called on power4 (or above) and only via
160  * the Firmware Non-Maskable Interrupts (fwnmi) handler
161  * which provides the error analysis for us.
162  *
163  * Return 1 if corrected (or delivered a signal).
164  * Return 0 if there is nothing we can do.
165  */
166 static int recover_mce(struct pt_regs *regs, struct rtas_error_log err)
167 {
168         siginfo_t info;
169
170         if (err.disposition == DISP_FULLY_RECOVERED) {
171                 /* Platform corrected itself */
172                 return 1;
173         } else if ((regs->msr & MSR_RI) &&
174                    user_mode(regs) &&
175                    err.severity == SEVERITY_ERROR_SYNC &&
176                    err.disposition == DISP_NOT_RECOVERED &&
177                    err.target == TARGET_MEMORY &&
178                    err.type == TYPE_ECC_UNCORR &&
179                    !(current->pid == 0 || current->pid == 1)) {
180                 /* Kill off a user process with an ECC error */
181                 info.si_signo = SIGBUS;
182                 info.si_errno = 0;
183                 /* XXX something better for ECC error? */
184                 info.si_code = BUS_ADRERR;
185                 info.si_addr = (void *)regs->nip;
186                 printk(KERN_ERR "MCE: uncorrectable ecc error for pid %d\n",
187                        current->pid);
188                 _exception(SIGBUS, &info, regs);
189                 return 1;
190         }
191         return 0;
192 }
193
194 /*
195  * Handle a machine check.
196  *
197  * Note that on Power 4 and beyond Firmware Non-Maskable Interrupts (fwnmi)
198  * should be present.  If so the handler which called us tells us if the
199  * error was recovered (never true if RI=0).
200  *
201  * On hardware prior to Power 4 these exceptions were asynchronous which
202  * means we can't tell exactly where it occurred and so we can't recover.
203  *
204  * Note that the debugger should test RI=0 and warn the user that system
205  * state has been corrupted.
206  */
207 void
208 MachineCheckException(struct pt_regs *regs)
209 {
210         struct rtas_error_log err, *errp;
211
212         if (fwnmi_active) {
213                 errp = FWNMI_get_errinfo(regs);
214                 if (errp)
215                         err = *errp;
216                 FWNMI_release_errinfo();        /* frees errp */
217                 if (errp && recover_mce(regs, err))
218                         return;
219         }
220
221 #ifdef CONFIG_DEBUG_KERNEL
222         if (debugger_fault_handler) {
223                 debugger_fault_handler(regs);
224                 return;
225         }
226         if (debugger)
227                 debugger(regs);
228 #endif
229         console_verbose();
230         spin_lock_irq(&die_lock);
231         bust_spinlocks(1);
232         printk("Machine check in kernel mode.\n");
233         printk("Caused by (from SRR1=%lx): ", regs->msr);
234         show_regs(regs);
235         bust_spinlocks(0);
236         spin_unlock_irq(&die_lock);
237         panic("Unrecoverable Machine Check");
238 }
239
240 void
241 UnknownException(struct pt_regs *regs)
242 {
243         siginfo_t info;
244
245         printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
246                regs->nip, regs->msr, regs->trap);
247
248         info.si_signo = SIGTRAP;
249         info.si_errno = 0;
250         info.si_code = 0;
251         info.si_addr = 0;
252         _exception(SIGTRAP, &info, regs);       
253 }
254
255 void
256 InstructionBreakpointException(struct pt_regs *regs)
257 {
258         siginfo_t info;
259
260 #ifdef CONFIG_DEBUG_KERNEL
261         if (debugger_iabr_match && debugger_iabr_match(regs))
262                 return;
263 #endif
264         info.si_signo = SIGTRAP;
265         info.si_errno = 0;
266         info.si_code = TRAP_BRKPT;
267         info.si_addr = (void *)regs->nip;
268         _exception(SIGTRAP, &info, regs);
269 }
270
271 static void parse_fpe(struct pt_regs *regs)
272 {
273         siginfo_t info;
274         unsigned long fpscr;
275
276         if (regs->msr & MSR_FP)
277                 giveup_fpu(current);
278
279         fpscr = current->thread.fpscr;
280
281         /* Invalid operation */
282         if ((fpscr & FPSCR_VE) && (fpscr & FPSCR_VX))
283                 info.si_code = FPE_FLTINV;
284
285         /* Overflow */
286         else if ((fpscr & FPSCR_OE) && (fpscr & FPSCR_OX))
287                 info.si_code = FPE_FLTOVF;
288
289         /* Underflow */
290         else if ((fpscr & FPSCR_UE) && (fpscr & FPSCR_UX))
291                 info.si_code = FPE_FLTUND;
292
293         /* Divide by zero */
294         else if ((fpscr & FPSCR_ZE) && (fpscr & FPSCR_ZX))
295                 info.si_code = FPE_FLTDIV;
296
297         /* Inexact result */
298         else if ((fpscr & FPSCR_XE) && (fpscr & FPSCR_XX))
299                 info.si_code = FPE_FLTRES;
300
301         else
302                 info.si_code = 0;
303
304         info.si_signo = SIGFPE;
305         info.si_errno = 0;
306         info.si_addr = (void *)regs->nip;
307         _exception(SIGFPE, &info, regs);
308 }
309
310 /*
311  * Look through the list of trap instructions that are used for BUG(),
312  * BUG_ON() and WARN_ON() and see if we hit one.  At this point we know
313  * that the exception was caused by a trap instruction of some kind.
314  * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0
315  * otherwise.
316  */
317 extern struct bug_entry __start___bug_table[], __stop___bug_table[];
318
319 #ifndef CONFIG_MODULES
320 #define module_find_bug(x)      NULL
321 #endif
322
323 static struct bug_entry *find_bug(unsigned long bugaddr)
324 {
325         struct bug_entry *bug;
326
327         for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
328                 if (bugaddr == bug->bug_addr)
329                         return bug;
330         return module_find_bug(bugaddr);
331 }
332
333 int
334 check_bug_trap(struct pt_regs *regs)
335 {
336         struct bug_entry *bug;
337         unsigned long addr;
338
339         if (regs->msr & MSR_PR)
340                 return 0;       /* not in kernel */
341         addr = regs->nip;       /* address of trap instruction */
342         if (addr < PAGE_OFFSET)
343                 return 0;
344         bug = find_bug(regs->nip);
345         if (bug == NULL)
346                 return 0;
347         if (bug->line & BUG_WARNING_TRAP) {
348                 /* this is a WARN_ON rather than BUG/BUG_ON */
349                 printk(KERN_ERR "Badness in %s at %s:%d\n",
350                        bug->function, bug->file,
351                       (unsigned int)bug->line & ~BUG_WARNING_TRAP);
352                 dump_stack();
353                 return 1;
354         }
355         printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n",
356                bug->function, bug->file, (unsigned int)bug->line);
357         return 0;
358 }
359
360 void
361 ProgramCheckException(struct pt_regs *regs)
362 {
363         siginfo_t info;
364
365         if (regs->msr & 0x100000) {
366                 /* IEEE FP exception */
367
368                 parse_fpe(regs);
369         } else if (regs->msr & 0x40000) {
370                 /* Privileged instruction */
371
372                 info.si_signo = SIGILL;
373                 info.si_errno = 0;
374                 info.si_code = ILL_PRVOPC;
375                 info.si_addr = (void *)regs->nip;
376                 _exception(SIGILL, &info, regs);
377         } else if (regs->msr & 0x20000) {
378                 /* trap exception */
379
380 #ifdef CONFIG_DEBUG_KERNEL
381                 if (debugger_bpt && debugger_bpt(regs))
382                         return;
383 #endif
384                 if (check_bug_trap(regs)) {
385                         regs->nip += 4;
386                         return;
387                 }
388                 info.si_signo = SIGTRAP;
389                 info.si_errno = 0;
390                 info.si_code = TRAP_BRKPT;
391                 info.si_addr = (void *)regs->nip;
392                 _exception(SIGTRAP, &info, regs);
393         } else {
394                 /* Illegal instruction */
395
396                 info.si_signo = SIGILL;
397                 info.si_errno = 0;
398                 info.si_code = ILL_ILLTRP;
399                 info.si_addr = (void *)regs->nip;
400                 _exception(SIGILL, &info, regs);
401         }
402 }
403
404 void
405 KernelFPUnavailableException(struct pt_regs *regs)
406 {
407         printk("Illegal floating point used in kernel (task=0x%p, "
408                 "pc=0x%016lx, trap=0x%lx)\n", current, regs->nip, regs->trap);
409         panic("Unrecoverable FP Unavailable Exception in Kernel");
410 }
411
412 void
413 SingleStepException(struct pt_regs *regs)
414 {
415         siginfo_t info;
416
417         regs->msr &= ~MSR_SE;  /* Turn off 'trace' bit */
418
419 #ifdef CONFIG_DEBUG_KERNEL
420         if (debugger_sstep && debugger_sstep(regs))
421                 return;
422 #endif
423         info.si_signo = SIGTRAP;
424         info.si_errno = 0;
425         info.si_code = TRAP_TRACE;
426         info.si_addr = (void *)regs->nip;
427         _exception(SIGTRAP, &info, regs);       
428 }
429
430 void
431 PerformanceMonitorException(struct pt_regs *regs)
432 {
433         siginfo_t info;
434
435         info.si_signo = SIGTRAP;
436         info.si_errno = 0;
437         info.si_code = TRAP_BRKPT;
438         info.si_addr = 0;
439         _exception(SIGTRAP, &info, regs);
440 }
441
442 void
443 AlignmentException(struct pt_regs *regs)
444 {
445         int fixed;
446         siginfo_t info;
447
448         fixed = fix_alignment(regs);
449
450         if (fixed == 1) {
451                 if (!user_mode(regs))
452                         PPCDBG(PPCDBG_ALIGNFIXUP, "fix alignment at %lx\n",
453                                regs->nip);
454                 regs->nip += 4; /* skip over emulated instruction */
455                 return;
456         }
457
458         /* Operand address was bad */   
459         if (fixed == -EFAULT) {
460                 if (user_mode(regs)) {
461                         info.si_signo = SIGSEGV;
462                         info.si_errno = 0;
463                         info.si_code = SEGV_MAPERR;
464                         info.si_addr = (void *)regs->dar;
465                         force_sig_info(SIGSEGV, &info, current);
466                 } else {
467                         /* Search exception table */
468                         bad_page_fault(regs, regs->dar, SIGSEGV);
469                 }
470
471                 return;
472         }
473
474         info.si_signo = SIGBUS;
475         info.si_errno = 0;
476         info.si_code = BUS_ADRALN;
477         info.si_addr = (void *)regs->nip;
478         _exception(SIGBUS, &info, regs);        
479 }
480
481 void __init trap_init(void)
482 {
483 }