summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2004-04-11 22:49:46 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-04-11 22:49:46 -0700
commitc3a85f1fb88cfa30ab4af65348eaf4290233cac8 (patch)
tree9b0a3ea3802089b1008cfa5c456a05a81daca173
parentfbe3e9b6ef357ffbb02b9976ae3b6181c12344ed (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.c50
-rw-r--r--arch/ppc64/mm/fault.c8
-rw-r--r--arch/ppc64/xmon/xmon.c34
-rw-r--r--include/asm-ppc64/system.h5
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 *);