aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r--arch/powerpc/kernel/traps.c97
1 files changed, 52 insertions, 45 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index d8502e377518..bf9e39c6e296 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -172,11 +172,21 @@ int die(const char *str, struct pt_regs *regs, long err)
172void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) 172void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
173{ 173{
174 siginfo_t info; 174 siginfo_t info;
175 const char fmt32[] = KERN_INFO "%s[%d]: unhandled signal %d " \
176 "at %08lx nip %08lx lr %08lx code %x\n";
177 const char fmt64[] = KERN_INFO "%s[%d]: unhandled signal %d " \
178 "at %016lx nip %016lx lr %016lx code %x\n";
175 179
176 if (!user_mode(regs)) { 180 if (!user_mode(regs)) {
177 if (die("Exception in kernel mode", regs, signr)) 181 if (die("Exception in kernel mode", regs, signr))
178 return; 182 return;
179 } 183 } else if (show_unhandled_signals &&
184 unhandled_signal(current, signr) &&
185 printk_ratelimit()) {
186 printk(regs->msr & MSR_SF ? fmt64 : fmt32,
187 current->comm, current->pid, signr,
188 addr, regs->nip, regs->link, code);
189 }
180 190
181 memset(&info, 0, sizeof(info)); 191 memset(&info, 0, sizeof(info));
182 info.si_signo = signr; 192 info.si_signo = signr;
@@ -324,47 +334,10 @@ static inline int check_io_access(struct pt_regs *regs)
324#define clear_single_step(regs) ((regs)->msr &= ~MSR_SE) 334#define clear_single_step(regs) ((regs)->msr &= ~MSR_SE)
325#endif 335#endif
326 336
327/* 337static int generic_machine_check_exception(struct pt_regs *regs)
328 * This is "fall-back" implementation for configurations
329 * which don't provide platform-specific machine check info
330 */
331void __attribute__ ((weak))
332platform_machine_check(struct pt_regs *regs)
333{
334}
335
336void machine_check_exception(struct pt_regs *regs)
337{ 338{
338 int recover = 0;
339 unsigned long reason = get_mc_reason(regs); 339 unsigned long reason = get_mc_reason(regs);
340 340
341 /* See if any machine dependent calls */
342 if (ppc_md.machine_check_exception)
343 recover = ppc_md.machine_check_exception(regs);
344
345 if (recover)
346 return;
347
348 if (user_mode(regs)) {
349 regs->msr |= MSR_RI;
350 _exception(SIGBUS, regs, BUS_ADRERR, regs->nip);
351 return;
352 }
353
354#if defined(CONFIG_8xx) && defined(CONFIG_PCI)
355 /* the qspan pci read routines can cause machine checks -- Cort */
356 bad_page_fault(regs, regs->dar, SIGBUS);
357 return;
358#endif
359
360 if (debugger_fault_handler(regs)) {
361 regs->msr |= MSR_RI;
362 return;
363 }
364
365 if (check_io_access(regs))
366 return;
367
368#if defined(CONFIG_4xx) && !defined(CONFIG_440A) 341#if defined(CONFIG_4xx) && !defined(CONFIG_440A)
369 if (reason & ESR_IMCP) { 342 if (reason & ESR_IMCP) {
370 printk("Instruction"); 343 printk("Instruction");
@@ -480,11 +453,41 @@ void machine_check_exception(struct pt_regs *regs)
480 } 453 }
481#endif /* CONFIG_4xx */ 454#endif /* CONFIG_4xx */
482 455
483 /* 456 return 0;
484 * Optional platform-provided routine to print out 457}
485 * additional info, e.g. bus error registers. 458
486 */ 459void machine_check_exception(struct pt_regs *regs)
487 platform_machine_check(regs); 460{
461 int recover = 0;
462
463 /* See if any machine dependent calls */
464 if (ppc_md.machine_check_exception)
465 recover = ppc_md.machine_check_exception(regs);
466 else
467 recover = generic_machine_check_exception(regs);
468
469 if (recover)
470 return;
471
472 if (user_mode(regs)) {
473 regs->msr |= MSR_RI;
474 _exception(SIGBUS, regs, BUS_ADRERR, regs->nip);
475 return;
476 }
477
478#if defined(CONFIG_8xx) && defined(CONFIG_PCI)
479 /* the qspan pci read routines can cause machine checks -- Cort */
480 bad_page_fault(regs, regs->dar, SIGBUS);
481 return;
482#endif
483
484 if (debugger_fault_handler(regs)) {
485 regs->msr |= MSR_RI;
486 return;
487 }
488
489 if (check_io_access(regs))
490 return;
488 491
489 if (debugger_fault_handler(regs)) 492 if (debugger_fault_handler(regs))
490 return; 493 return;
@@ -913,7 +916,9 @@ void SoftwareEmulation(struct pt_regs *regs)
913{ 916{
914 extern int do_mathemu(struct pt_regs *); 917 extern int do_mathemu(struct pt_regs *);
915 extern int Soft_emulate_8xx(struct pt_regs *); 918 extern int Soft_emulate_8xx(struct pt_regs *);
919#if defined(CONFIG_MATH_EMULATION) || defined(CONFIG_8XX_MINIMAL_FPEMU)
916 int errcode; 920 int errcode;
921#endif
917 922
918 CHECK_FULL_REGS(regs); 923 CHECK_FULL_REGS(regs);
919 924
@@ -943,7 +948,7 @@ void SoftwareEmulation(struct pt_regs *regs)
943 return; 948 return;
944 } 949 }
945 950
946#else 951#elif defined(CONFIG_8XX_MINIMAL_FPEMU)
947 errcode = Soft_emulate_8xx(regs); 952 errcode = Soft_emulate_8xx(regs);
948 switch (errcode) { 953 switch (errcode) {
949 case 0: 954 case 0:
@@ -956,6 +961,8 @@ void SoftwareEmulation(struct pt_regs *regs)
956 _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); 961 _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
957 return; 962 return;
958 } 963 }
964#else
965 _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
959#endif 966#endif
960} 967}
961#endif /* CONFIG_8xx */ 968#endif /* CONFIG_8xx */