diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/kernel/traps.c | 66 |
1 files changed, 37 insertions, 29 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index ccfc99dad061..5a49eabd492e 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -324,38 +324,10 @@ static inline int check_io_access(struct pt_regs *regs) | |||
324 | #define clear_single_step(regs) ((regs)->msr &= ~MSR_SE) | 324 | #define clear_single_step(regs) ((regs)->msr &= ~MSR_SE) |
325 | #endif | 325 | #endif |
326 | 326 | ||
327 | void machine_check_exception(struct pt_regs *regs) | 327 | static int generic_machine_check_exception(struct pt_regs *regs) |
328 | { | 328 | { |
329 | int recover = 0; | ||
330 | unsigned long reason = get_mc_reason(regs); | 329 | unsigned long reason = get_mc_reason(regs); |
331 | 330 | ||
332 | /* See if any machine dependent calls */ | ||
333 | if (ppc_md.machine_check_exception) | ||
334 | recover = ppc_md.machine_check_exception(regs); | ||
335 | |||
336 | if (recover) | ||
337 | return; | ||
338 | |||
339 | if (user_mode(regs)) { | ||
340 | regs->msr |= MSR_RI; | ||
341 | _exception(SIGBUS, regs, BUS_ADRERR, regs->nip); | ||
342 | return; | ||
343 | } | ||
344 | |||
345 | #if defined(CONFIG_8xx) && defined(CONFIG_PCI) | ||
346 | /* the qspan pci read routines can cause machine checks -- Cort */ | ||
347 | bad_page_fault(regs, regs->dar, SIGBUS); | ||
348 | return; | ||
349 | #endif | ||
350 | |||
351 | if (debugger_fault_handler(regs)) { | ||
352 | regs->msr |= MSR_RI; | ||
353 | return; | ||
354 | } | ||
355 | |||
356 | if (check_io_access(regs)) | ||
357 | return; | ||
358 | |||
359 | #if defined(CONFIG_4xx) && !defined(CONFIG_440A) | 331 | #if defined(CONFIG_4xx) && !defined(CONFIG_440A) |
360 | if (reason & ESR_IMCP) { | 332 | if (reason & ESR_IMCP) { |
361 | printk("Instruction"); | 333 | printk("Instruction"); |
@@ -471,6 +443,42 @@ void machine_check_exception(struct pt_regs *regs) | |||
471 | } | 443 | } |
472 | #endif /* CONFIG_4xx */ | 444 | #endif /* CONFIG_4xx */ |
473 | 445 | ||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | void machine_check_exception(struct pt_regs *regs) | ||
450 | { | ||
451 | int recover = 0; | ||
452 | |||
453 | /* See if any machine dependent calls */ | ||
454 | if (ppc_md.machine_check_exception) | ||
455 | recover = ppc_md.machine_check_exception(regs); | ||
456 | else | ||
457 | recover = generic_machine_check_exception(regs); | ||
458 | |||
459 | if (recover) | ||
460 | return; | ||
461 | |||
462 | if (user_mode(regs)) { | ||
463 | regs->msr |= MSR_RI; | ||
464 | _exception(SIGBUS, regs, BUS_ADRERR, regs->nip); | ||
465 | return; | ||
466 | } | ||
467 | |||
468 | #if defined(CONFIG_8xx) && defined(CONFIG_PCI) | ||
469 | /* the qspan pci read routines can cause machine checks -- Cort */ | ||
470 | bad_page_fault(regs, regs->dar, SIGBUS); | ||
471 | return; | ||
472 | #endif | ||
473 | |||
474 | if (debugger_fault_handler(regs)) { | ||
475 | regs->msr |= MSR_RI; | ||
476 | return; | ||
477 | } | ||
478 | |||
479 | if (check_io_access(regs)) | ||
480 | return; | ||
481 | |||
474 | if (debugger_fault_handler(regs)) | 482 | if (debugger_fault_handler(regs)) |
475 | return; | 483 | return; |
476 | die("Machine check", regs, SIGBUS); | 484 | die("Machine check", regs, SIGBUS); |