diff options
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r-- | arch/powerpc/kernel/traps.c | 97 |
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) | |||
172 | void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) | 172 | void _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 | /* | 337 | static 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 | */ | ||
331 | void __attribute__ ((weak)) | ||
332 | platform_machine_check(struct pt_regs *regs) | ||
333 | { | ||
334 | } | ||
335 | |||
336 | void 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 | */ | 459 | void 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 */ |