diff options
| author | Andrew Morton <akpm@osdl.org> | 2004-04-11 22:49:46 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-04-11 22:49:46 -0700 |
| commit | c3a85f1fb88cfa30ab4af65348eaf4290233cac8 (patch) | |
| tree | 9b0a3ea3802089b1008cfa5c456a05a81daca173 | |
| parent | fbe3e9b6ef357ffbb02b9976ae3b6181c12344ed (diff) | |
[PATCH] ppc64: Oops cleanup
From: Anton Blanchard <anton@samba.org>
Oops cleanup:
- Move prototypes into system.h
- Move the debugger hooks into die, all the calls sites were calling them.
- Handle bad values passed to prregs
| -rw-r--r-- | arch/ppc64/kernel/traps.c | 50 | ||||
| -rw-r--r-- | arch/ppc64/mm/fault.c | 8 | ||||
| -rw-r--r-- | arch/ppc64/xmon/xmon.c | 34 | ||||
| -rw-r--r-- | include/asm-ppc64/system.h | 5 |
4 files changed, 50 insertions, 47 deletions
diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c index 6074cae369e9..82d9b8b24e61 100644 --- a/arch/ppc64/kernel/traps.c +++ b/arch/ppc64/kernel/traps.c @@ -37,9 +37,6 @@ #include <asm/processor.h> #include <asm/ppcdebug.h> -extern int fix_alignment(struct pt_regs *); -extern void bad_page_fault(struct pt_regs *, unsigned long, int); - #ifdef CONFIG_PPC_PSERIES /* This is true if we are using the firmware NMI handler (typically LPAR) */ extern int fwnmi_active; @@ -67,11 +64,17 @@ EXPORT_SYMBOL(__debugger_fault_handler); static spinlock_t die_lock = SPIN_LOCK_UNLOCKED; -void die(const char *str, struct pt_regs *regs, long err) +int die(const char *str, struct pt_regs *regs, long err) { static int die_counter; int nl = 0; + if (debugger_fault_handler(regs)) + return 1; + + if (debugger(regs)) + return 1; + console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); @@ -126,15 +129,16 @@ void die(const char *str, struct pt_regs *regs, long err) panic("Fatal exception"); } do_exit(SIGSEGV); + + return 0; } static void _exception(int signr, siginfo_t *info, struct pt_regs *regs) { if (!user_mode(regs)) { - if (debugger(regs)) + if (die("Exception in kernel mode", regs, signr)) return; - die("Exception in kernel mode", regs, signr); } force_sig_info(signr, info, current); @@ -188,8 +192,7 @@ SystemResetException(struct pt_regs *regs) } #endif - if (!debugger(regs)) - die("System Reset", regs, 0); + die("System Reset", regs, 0); /* Must die if the interrupt is not recoverable */ if (!(regs->msr & MSR_RI)) @@ -246,9 +249,6 @@ static int recover_mce(struct pt_regs *regs, struct rtas_error_log err) * * On hardware prior to Power 4 these exceptions were asynchronous which * means we can't tell exactly where it occurred and so we can't recover. - * - * Note that the debugger should test RI=0 and warn the user that system - * state has been corrupted. */ void MachineCheckException(struct pt_regs *regs) @@ -266,12 +266,11 @@ MachineCheckException(struct pt_regs *regs) } #endif - if (debugger_fault_handler(regs)) - return; - if (debugger(regs)) - return; + die("Machine check", regs, 0); - die("Machine check in kernel mode", regs, 0); + /* Must die if the interrupt is not recoverable */ + if (!(regs->msr & MSR_RI)) + panic("Unrecoverable Machine check"); } void @@ -397,9 +396,6 @@ ProgramCheckException(struct pt_regs *regs) { siginfo_t info; - if (debugger_fault_handler(regs)) - return; - if (regs->msr & 0x100000) { /* IEEE FP exception */ @@ -438,16 +434,18 @@ ProgramCheckException(struct pt_regs *regs) } } -void -KernelFPUnavailableException(struct pt_regs *regs) +void KernelFPUnavailableException(struct pt_regs *regs) { - die("Unrecoverable FP Unavailable Exception in Kernel", regs, 0); + printk(KERN_EMERG "Unrecoverable FP Unavailable Exception " + "%lx at %lx\n", regs->trap, regs->nip); + die("Unrecoverable FP Unavailable Exception", regs, SIGABRT); } -void -KernelAltivecUnavailableException(struct pt_regs *regs) +void KernelAltivecUnavailableException(struct pt_regs *regs) { - die("Unrecoverable VMX/Altivec Unavailable Exception in Kernel", regs, 0); + printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception " + "%lx at %lx\n", regs->trap, regs->nip); + die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); } void @@ -539,7 +537,6 @@ void unrecoverable_exception(struct pt_regs *regs) { printk(KERN_EMERG "Unrecoverable exception %lx at %lx\n", regs->trap, regs->nip); - debugger(regs); die("Unrecoverable exception", regs, SIGABRT); } @@ -551,7 +548,6 @@ void kernel_bad_stack(struct pt_regs *regs) { printk(KERN_EMERG "Bad kernel stack pointer %lx at %lx\n", regs->gpr[1], regs->nip); - debugger(regs); die("Bad kernel stack pointer", regs, SIGABRT); } diff --git a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c index 4fd5100acff1..73712c143825 100644 --- a/arch/ppc64/mm/fault.c +++ b/arch/ppc64/mm/fault.c @@ -37,8 +37,6 @@ #include <asm/system.h> #include <asm/uaccess.h> -void bad_page_fault(struct pt_regs *, unsigned long, int); - /* * The error_code parameter is * - DSISR for a non-SLB data access fault, @@ -177,10 +175,8 @@ do_sigbus: * It is called from do_page_fault above and from some of the procedures * in traps.c. */ -void -bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) +void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) { - extern void die(const char *, struct pt_regs *, long); const struct exception_table_entry *entry; /* Are we prepared to handle this fault? */ @@ -190,7 +186,5 @@ bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) } /* kernel has accessed a bad area */ - if (debugger(regs)) - return; die("Kernel access of bad area", regs, sig); } diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c index 8bf490b348f1..90fe14bacc59 100644 --- a/arch/ppc64/xmon/xmon.c +++ b/arch/ppc64/xmon/xmon.c @@ -542,8 +542,7 @@ cmds(struct pt_regs *excp) symbol_lookup(); break; case 'r': - if (excp != NULL) - prregs(excp); /* print regs */ + prregs(excp); /* print regs */ break; case 'e': if (excp == NULL) @@ -966,8 +965,7 @@ static void backtrace(struct pt_regs *excp) spinlock_t exception_print_lock = SPIN_LOCK_UNLOCKED; -void -excprint(struct pt_regs *fp) +void excprint(struct pt_regs *fp) { unsigned long flags; @@ -1002,21 +1000,31 @@ excprint(struct pt_regs *fp) spin_unlock_irqrestore(&exception_print_lock, flags); } -void -prregs(struct pt_regs *fp) +void prregs(struct pt_regs *fp) { int n; unsigned long base; if (scanhex((void *)&base)) fp = (struct pt_regs *) base; - for (n = 0; n < 16; ++n) - printf("R%.2ld = %.16lx R%.2ld = %.16lx\n", n, fp->gpr[n], - n+16, fp->gpr[n+16]); - printf("pc = %.16lx msr = %.16lx\nlr = %.16lx cr = %.16lx\n", - fp->nip, fp->msr, fp->link, fp->ccr); - printf("ctr = %.16lx xer = %.16lx trap = %8lx\n", - fp->ctr, fp->xer, fp->trap); + + if (setjmp(bus_error_jmp) == 0) { + __debugger_fault_handler = handle_fault; + sync(); + for (n = 0; n < 16; ++n) + printf("R%.2ld = %.16lx R%.2ld = %.16lx\n", n, + fp->gpr[n], n+16, fp->gpr[n+16]); + printf("pc = %.16lx msr = %.16lx\nlr = %.16lx " + "cr = %.16lx\n", fp->nip, fp->msr, fp->link, fp->ccr); + printf("ctr = %.16lx xer = %.16lx trap = %8lx\n", + fp->ctr, fp->xer, fp->trap); + + sync(); + /* wait a little while to see if we get a machine check */ + __delay(200); + } else { + printf("*** Error reading regs\n"); + } } void diff --git a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h index 9d732aa1256e..152a59acbc35 100644 --- a/include/asm-ppc64/system.h +++ b/include/asm-ppc64/system.h @@ -94,7 +94,12 @@ static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; } static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; } #endif +extern int fix_alignment(struct pt_regs *regs); +extern void bad_page_fault(struct pt_regs *regs, unsigned long address, + int sig); extern void show_regs(struct pt_regs * regs); +extern int die(const char *str, struct pt_regs *regs, long err); + extern void flush_instruction_cache(void); extern int _get_PVR(void); extern void giveup_fpu(struct task_struct *); |
