#ifdef CONFIG_PMAC_BACKLIGHT
#include <asm/backlight.h>
#endif
+#include <asm/perfmon.h>
#ifdef CONFIG_XMON
void (*debugger)(struct pt_regs *regs) = xmon;
* Trap & Exception support
*/
-
-spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(die_lock);
void die(const char * str, struct pt_regs * fp, long err)
{
#define clear_single_step(regs) ((regs)->msr &= ~MSR_SE)
#endif
+/*
+ * This is "fall-back" implementation for configurations
+ * which don't provide platform-specific machine check info
+ */
+void __attribute__ ((weak))
+platform_machine_check(struct pt_regs *regs)
+{
+}
+
void MachineCheckException(struct pt_regs *regs)
{
unsigned long reason = get_mc_reason(regs);
}
#endif /* CONFIG_4xx */
+ /*
+ * Optional platform-provided routine to print out
+ * additional info, e.g. bus error registers.
+ */
+ platform_machine_check(regs);
+
debugger(regs);
die("machine check", regs, SIGBUS);
}
/* Illegal instruction emulation support. Originally written to
* provide the PVR to user applications using the mfspr rd, PVR.
- * Return non-zero if we can't emulate, or EFAULT if the associated
+ * Return non-zero if we can't emulate, or -EFAULT if the associated
* memory access caused an access fault. Return zero on success.
*
* There are a couple of ways to do this, either "decode" the instruction
#define INST_MFSPR_PVR 0x7c1f42a6
#define INST_MFSPR_PVR_MASK 0xfc1fffff
+#define INST_DCBA 0x7c0005ec
+#define INST_DCBA_MASK 0x7c0007fe
+
+#define INST_MCRXR 0x7c000400
+#define INST_MCRXR_MASK 0x7c0007fe
+
static int emulate_instruction(struct pt_regs *regs)
{
u32 instword;
u32 rd;
- int retval;
-
- retval = -EINVAL;
if (!user_mode(regs))
- return retval;
+ return -EINVAL;
CHECK_FULL_REGS(regs);
if (get_user(instword, (u32 __user *)(regs->nip)))
if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
rd = (instword >> 21) & 0x1f;
regs->gpr[rd] = mfspr(PVR);
- retval = 0;
- regs->nip += 4;
+ return 0;
+ }
+
+ /* Emulating the dcba insn is just a no-op. */
+ if ((instword & INST_DCBA_MASK) == INST_DCBA)
+ return 0;
+
+ /* Emulate the mcrxr insn. */
+ if ((instword & INST_MCRXR_MASK) == INST_MCRXR) {
+ int shift = (instword >> 21) & 0x1c;
+ unsigned long msk = 0xf0000000UL >> shift;
+
+ regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk);
+ regs->xer &= ~0xf0000000UL;
+ return 0;
}
- return retval;
+
+ return -EINVAL;
}
/*
return;
}
- if (reason & REASON_PRIVILEGED) {
- /* Try to emulate it if we should. */
- if (emulate_instruction(regs) == 0) {
+ /* Try to emulate it if we should. */
+ if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) {
+ switch (emulate_instruction(regs)) {
+ case 0:
+ regs->nip += 4;
emulate_single_step(regs);
return;
+ case -EFAULT:
+ _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
+ return;
}
- _exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
- return;
}
- _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
+ if (reason & REASON_PRIVILEGED)
+ _exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
+ else
+ _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
}
void SingleStepException(struct pt_regs *regs)
{
- regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */
+ regs->msr &= ~(MSR_SE | MSR_BE); /* Turn off 'trace' bits */
if (debugger_sstep(regs))
return;
_exception(SIGTRAP, regs, TRAP_TRACE, 0);
}
#endif /* CONFIG_8xx */
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
void DebugException(struct pt_regs *regs, unsigned long debug_status)
{
-#if 0
- if (debug_status & DBSR_TIE) { /* trap instruction*/
- if (!user_mode(regs) && debugger_bpt(regs))
- return;
- _exception(SIGTRAP, regs, 0, 0);
-
- }
-#endif
if (debug_status & DBSR_IC) { /* instruction completion */
- if (!user_mode(regs) && debugger_sstep(regs))
- return;
- current->thread.dbcr0 &= ~DBCR0_IC;
+ regs->msr &= ~MSR_DE;
+ if (user_mode(regs)) {
+ current->thread.dbcr0 &= ~DBCR0_IC;
+ } else {
+ /* Disable instruction completion */
+ mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~DBCR0_IC);
+ /* Clear the instruction completion event */
+ mtspr(SPRN_DBSR, DBSR_IC);
+ if (debugger_sstep(regs))
+ return;
+ }
_exception(SIGTRAP, regs, TRAP_TRACE, 0);
}
}
}
#endif /* CONFIG_ALTIVEC */
+void PerformanceMonitorException(struct pt_regs *regs)
+{
+ perf_irq(regs);
+}
+
#ifdef CONFIG_FSL_BOOKE
void CacheLockingException(struct pt_regs *regs, unsigned long address,
unsigned long error_code)