Commit c3a85f1f authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[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
parent fbe3e9b6
...@@ -37,9 +37,6 @@ ...@@ -37,9 +37,6 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/ppcdebug.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 #ifdef CONFIG_PPC_PSERIES
/* This is true if we are using the firmware NMI handler (typically LPAR) */ /* This is true if we are using the firmware NMI handler (typically LPAR) */
extern int fwnmi_active; extern int fwnmi_active;
...@@ -67,11 +64,17 @@ EXPORT_SYMBOL(__debugger_fault_handler); ...@@ -67,11 +64,17 @@ EXPORT_SYMBOL(__debugger_fault_handler);
static spinlock_t die_lock = SPIN_LOCK_UNLOCKED; 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; static int die_counter;
int nl = 0; int nl = 0;
if (debugger_fault_handler(regs))
return 1;
if (debugger(regs))
return 1;
console_verbose(); console_verbose();
spin_lock_irq(&die_lock); spin_lock_irq(&die_lock);
bust_spinlocks(1); bust_spinlocks(1);
...@@ -126,15 +129,16 @@ void die(const char *str, struct pt_regs *regs, long err) ...@@ -126,15 +129,16 @@ void die(const char *str, struct pt_regs *regs, long err)
panic("Fatal exception"); panic("Fatal exception");
} }
do_exit(SIGSEGV); do_exit(SIGSEGV);
return 0;
} }
static void static void
_exception(int signr, siginfo_t *info, struct pt_regs *regs) _exception(int signr, siginfo_t *info, struct pt_regs *regs)
{ {
if (!user_mode(regs)) { if (!user_mode(regs)) {
if (debugger(regs)) if (die("Exception in kernel mode", regs, signr))
return; return;
die("Exception in kernel mode", regs, signr);
} }
force_sig_info(signr, info, current); force_sig_info(signr, info, current);
...@@ -188,8 +192,7 @@ SystemResetException(struct pt_regs *regs) ...@@ -188,8 +192,7 @@ SystemResetException(struct pt_regs *regs)
} }
#endif #endif
if (!debugger(regs)) die("System Reset", regs, 0);
die("System Reset", regs, 0);
/* Must die if the interrupt is not recoverable */ /* Must die if the interrupt is not recoverable */
if (!(regs->msr & MSR_RI)) if (!(regs->msr & MSR_RI))
...@@ -246,9 +249,6 @@ static int recover_mce(struct pt_regs *regs, struct rtas_error_log err) ...@@ -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 * 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. * 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 void
MachineCheckException(struct pt_regs *regs) MachineCheckException(struct pt_regs *regs)
...@@ -266,12 +266,11 @@ MachineCheckException(struct pt_regs *regs) ...@@ -266,12 +266,11 @@ MachineCheckException(struct pt_regs *regs)
} }
#endif #endif
if (debugger_fault_handler(regs)) die("Machine check", regs, 0);
return;
if (debugger(regs))
return;
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 void
...@@ -397,9 +396,6 @@ ProgramCheckException(struct pt_regs *regs) ...@@ -397,9 +396,6 @@ ProgramCheckException(struct pt_regs *regs)
{ {
siginfo_t info; siginfo_t info;
if (debugger_fault_handler(regs))
return;
if (regs->msr & 0x100000) { if (regs->msr & 0x100000) {
/* IEEE FP exception */ /* IEEE FP exception */
...@@ -438,16 +434,18 @@ ProgramCheckException(struct pt_regs *regs) ...@@ -438,16 +434,18 @@ ProgramCheckException(struct pt_regs *regs)
} }
} }
void void KernelFPUnavailableException(struct pt_regs *regs)
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 void KernelAltivecUnavailableException(struct pt_regs *regs)
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 void
...@@ -539,7 +537,6 @@ void unrecoverable_exception(struct pt_regs *regs) ...@@ -539,7 +537,6 @@ void unrecoverable_exception(struct pt_regs *regs)
{ {
printk(KERN_EMERG "Unrecoverable exception %lx at %lx\n", printk(KERN_EMERG "Unrecoverable exception %lx at %lx\n",
regs->trap, regs->nip); regs->trap, regs->nip);
debugger(regs);
die("Unrecoverable exception", regs, SIGABRT); die("Unrecoverable exception", regs, SIGABRT);
} }
...@@ -551,7 +548,6 @@ void kernel_bad_stack(struct pt_regs *regs) ...@@ -551,7 +548,6 @@ void kernel_bad_stack(struct pt_regs *regs)
{ {
printk(KERN_EMERG "Bad kernel stack pointer %lx at %lx\n", printk(KERN_EMERG "Bad kernel stack pointer %lx at %lx\n",
regs->gpr[1], regs->nip); regs->gpr[1], regs->nip);
debugger(regs);
die("Bad kernel stack pointer", regs, SIGABRT); die("Bad kernel stack pointer", regs, SIGABRT);
} }
......
...@@ -37,8 +37,6 @@ ...@@ -37,8 +37,6 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
void bad_page_fault(struct pt_regs *, unsigned long, int);
/* /*
* The error_code parameter is * The error_code parameter is
* - DSISR for a non-SLB data access fault, * - DSISR for a non-SLB data access fault,
...@@ -177,10 +175,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -177,10 +175,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
* It is called from do_page_fault above and from some of the procedures * It is called from do_page_fault above and from some of the procedures
* in traps.c. * in traps.c.
*/ */
void void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
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; const struct exception_table_entry *entry;
/* Are we prepared to handle this fault? */ /* Are we prepared to handle this fault? */
...@@ -190,7 +186,5 @@ bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) ...@@ -190,7 +186,5 @@ bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
} }
/* kernel has accessed a bad area */ /* kernel has accessed a bad area */
if (debugger(regs))
return;
die("Kernel access of bad area", regs, sig); die("Kernel access of bad area", regs, sig);
} }
...@@ -542,8 +542,7 @@ cmds(struct pt_regs *excp) ...@@ -542,8 +542,7 @@ cmds(struct pt_regs *excp)
symbol_lookup(); symbol_lookup();
break; break;
case 'r': case 'r':
if (excp != NULL) prregs(excp); /* print regs */
prregs(excp); /* print regs */
break; break;
case 'e': case 'e':
if (excp == NULL) if (excp == NULL)
...@@ -966,8 +965,7 @@ static void backtrace(struct pt_regs *excp) ...@@ -966,8 +965,7 @@ static void backtrace(struct pt_regs *excp)
spinlock_t exception_print_lock = SPIN_LOCK_UNLOCKED; spinlock_t exception_print_lock = SPIN_LOCK_UNLOCKED;
void void excprint(struct pt_regs *fp)
excprint(struct pt_regs *fp)
{ {
unsigned long flags; unsigned long flags;
...@@ -1002,21 +1000,31 @@ excprint(struct pt_regs *fp) ...@@ -1002,21 +1000,31 @@ excprint(struct pt_regs *fp)
spin_unlock_irqrestore(&exception_print_lock, flags); spin_unlock_irqrestore(&exception_print_lock, flags);
} }
void void prregs(struct pt_regs *fp)
prregs(struct pt_regs *fp)
{ {
int n; int n;
unsigned long base; unsigned long base;
if (scanhex((void *)&base)) if (scanhex((void *)&base))
fp = (struct pt_regs *) base; fp = (struct pt_regs *) base;
for (n = 0; n < 16; ++n)
printf("R%.2ld = %.16lx R%.2ld = %.16lx\n", n, fp->gpr[n], if (setjmp(bus_error_jmp) == 0) {
n+16, fp->gpr[n+16]); __debugger_fault_handler = handle_fault;
printf("pc = %.16lx msr = %.16lx\nlr = %.16lx cr = %.16lx\n", sync();
fp->nip, fp->msr, fp->link, fp->ccr); for (n = 0; n < 16; ++n)
printf("ctr = %.16lx xer = %.16lx trap = %8lx\n", printf("R%.2ld = %.16lx R%.2ld = %.16lx\n", n,
fp->ctr, fp->xer, fp->trap); 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 void
......
...@@ -94,7 +94,12 @@ static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; } ...@@ -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; } static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
#endif #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 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 void flush_instruction_cache(void);
extern int _get_PVR(void); extern int _get_PVR(void);
extern void giveup_fpu(struct task_struct *); extern void giveup_fpu(struct task_struct *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment