traps_64.c revision 56fb4df6da76c35dca22036174e2d1edef83ff1f
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* $Id: traps.c,v 1.85 2002/02/09 19:49:31 davem Exp $
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * arch/sparc64/kernel/traps.c
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1997,1999,2000 Jakub Jelinek (jakub@redhat.com)
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * I like traps on v9, :))))
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/config.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h>  /* for jiffies */
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kallsyms.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/signal.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/smp.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/smp_lock.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/delay.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/ptrace.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/oplib.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/page.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pgtable.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/unistd.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/fpumacro.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/lsu.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/dcu.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/estate.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/chafsr.h>
366c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller#include <asm/sfafsr.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/psrcompat.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/processor.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/timer.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/kdebug.h>
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_KMOD
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kmod.h>
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct notifier_block *sparc64die_chain;
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(die_notifier_lock);
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint register_die_notifier(struct notifier_block *nb)
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = 0;
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&die_notifier_lock, flags);
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = notifier_chain_register(&sparc64die_chain, nb);
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&die_notifier_lock, flags);
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* When an irrecoverable trap occurs at tl > 0, the trap entry
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * code logs the trap state registers at every level in the trap
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * stack.  It is found at (pt_regs + sizeof(pt_regs)) and the layout
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is as follows:
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct tl1_traplog {
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct {
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long tstate;
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long tpc;
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long tnpc;
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long tt;
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} trapstack[4];
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long tl;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void dump_tl1_traplog(struct tl1_traplog *p)
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("TRAPLOG: Error at trap level 0x%lx, dumping track stack.\n",
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       p->tl);
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 4; i++) {
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_CRIT
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       "TRAPLOG: Trap level %d TSTATE[%016lx] TPC[%016lx] "
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       "TNPC[%016lx] TT[%lx]\n",
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       i + 1,
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       p->trapstack[i].tstate, p->trapstack[i].tpc,
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       p->trapstack[i].tnpc, p->trapstack[i].tt);
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_call_debug(struct pt_regs *regs)
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT);
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid bad_trap(struct pt_regs *regs, long lvl)
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char buffer[32];
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	siginfo_t info;
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (notify_die(DIE_TRAP, "bad trap", regs,
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       0, lvl, SIGTRAP) == NOTIFY_STOP)
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lvl < 0x100) {
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sprintf(buffer, "Bad hw trap %lx at tl0\n", lvl);
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		die_if_kernel(buffer, regs);
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lvl -= 0x100;
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (regs->tstate & TSTATE_PRIV) {
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sprintf(buffer, "Kernel bad sw trap %lx", lvl);
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		die_if_kernel(buffer, regs);
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_thread_flag(TIF_32BIT)) {
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->tpc &= 0xffffffff;
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->tnpc &= 0xffffffff;
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_signo = SIGILL;
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_errno = 0;
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_code = ILL_ILLTRP;
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_addr = (void __user *)regs->tpc;
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_trapno = lvl;
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	force_sig_info(SIGILL, &info, current);
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid bad_trap_tl1(struct pt_regs *regs, long lvl)
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char buffer[32];
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs,
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       0, lvl, SIGTRAP) == NOTIFY_STOP)
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sprintf (buffer, "Bad trap %lx at tl>0", lvl);
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel (buffer, regs);
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_DEBUG_BUGVERBOSE
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_BUG(const char *file, int line)
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bust_spinlocks(1);
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("kernel BUG at %s:%d!\n", file, line);
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1476c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Millervoid spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	siginfo_t info;
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (notify_die(DIE_TRAP, "instruction access exception", regs,
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       0, 0x8, SIGTRAP) == NOTIFY_STOP)
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (regs->tstate & TSTATE_PRIV) {
1566c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		printk("spitfire_insn_access_exception: SFSR[%016lx] "
1576c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		       "SFAR[%016lx], going.\n", sfsr, sfar);
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		die_if_kernel("Iax", regs);
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_thread_flag(TIF_32BIT)) {
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->tpc &= 0xffffffff;
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->tnpc &= 0xffffffff;
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_signo = SIGSEGV;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_errno = 0;
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_code = SEGV_MAPERR;
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_addr = (void __user *)regs->tpc;
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_trapno = 0;
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	force_sig_info(SIGSEGV, &info, current);
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1726c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Millervoid spitfire_insn_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs,
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       0, 0x8, SIGTRAP) == NOTIFY_STOP)
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
1796c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	spitfire_insn_access_exception(regs, sfsr, sfar);
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1826c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Millervoid spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	siginfo_t info;
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (notify_die(DIE_TRAP, "data access exception", regs,
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       0, 0x30, SIGTRAP) == NOTIFY_STOP)
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (regs->tstate & TSTATE_PRIV) {
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Test if this comes from uaccess places. */
1928cf14af0a740fb7e9f94a203b5a989beb875d58fDavid S. Miller		const struct exception_table_entry *entry;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1948cf14af0a740fb7e9f94a203b5a989beb875d58fDavid S. Miller		entry = search_exception_tables(regs->tpc);
1958cf14af0a740fb7e9f94a203b5a989beb875d58fDavid S. Miller		if (entry) {
1968cf14af0a740fb7e9f94a203b5a989beb875d58fDavid S. Miller			/* Ouch, somebody is trying VM hole tricks on us... */
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_EXCEPTIONS
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc);
1998cf14af0a740fb7e9f94a203b5a989beb875d58fDavid S. Miller			printk("EX_TABLE: insn<%016lx> fixup<%016lx>\n",
2008cf14af0a740fb7e9f94a203b5a989beb875d58fDavid S. Miller			       regs->tpc, entry->fixup);
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2028cf14af0a740fb7e9f94a203b5a989beb875d58fDavid S. Miller			regs->tpc = entry->fixup;
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			regs->tnpc = regs->tpc + 4;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Shit... */
2076c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		printk("spitfire_data_access_exception: SFSR[%016lx] "
2086c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		       "SFAR[%016lx], going.\n", sfsr, sfar);
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		die_if_kernel("Dax", regs);
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_signo = SIGSEGV;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_errno = 0;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_code = SEGV_MAPERR;
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_addr = (void __user *)sfar;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_trapno = 0;
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	force_sig_info(SIGSEGV, &info, current);
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2206c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Millervoid spitfire_data_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
221bde4e4ee9f90142d550e2684dec2c8df302f5f8eDavid S. Miller{
222bde4e4ee9f90142d550e2684dec2c8df302f5f8eDavid S. Miller	if (notify_die(DIE_TRAP_TL1, "data access exception tl1", regs,
223bde4e4ee9f90142d550e2684dec2c8df302f5f8eDavid S. Miller		       0, 0x30, SIGTRAP) == NOTIFY_STOP)
224bde4e4ee9f90142d550e2684dec2c8df302f5f8eDavid S. Miller		return;
225bde4e4ee9f90142d550e2684dec2c8df302f5f8eDavid S. Miller
226bde4e4ee9f90142d550e2684dec2c8df302f5f8eDavid S. Miller	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
2276c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	spitfire_data_access_exception(regs, sfsr, sfar);
228bde4e4ee9f90142d550e2684dec2c8df302f5f8eDavid S. Miller}
229bde4e4ee9f90142d550e2684dec2c8df302f5f8eDavid S. Miller
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This is really pathetic... */
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern volatile int pci_poke_in_progress;
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern volatile int pci_poke_cpu;
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern volatile int pci_poke_faulted;
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* When access exceptions happen, we must do this. */
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void spitfire_clean_and_reenable_l1_caches(void)
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long va;
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tlb_type != spitfire)
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BUG();
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Clean 'em. */
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (va =  0; va < (PAGE_SIZE << 1); va += 32) {
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spitfire_put_icache_tag(va, 0x0);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spitfire_put_dcache_tag(va, 0x0);
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Re-enable in LSU. */
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("flush %%g6\n\t"
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "membar #Sync\n\t"
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "stxa %0, [%%g0] %1\n\t"
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "membar #Sync"
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : /* no outputs */
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "r" (LSU_CONTROL_IC | LSU_CONTROL_DC |
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    LSU_CONTROL_IM | LSU_CONTROL_DM),
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "i" (ASI_LSU_CONTROL)
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "memory");
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2636c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Millerstatic void spitfire_enable_estate_errors(void)
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2656c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	__asm__ __volatile__("stxa	%0, [%%g0] %1\n\t"
2666c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller			     "membar	#Sync"
2676c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller			     : /* no outputs */
2686c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller			     : "r" (ESTATE_ERR_ALL),
2696c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller			       "i" (ASI_ESTATE_ERROR_EN));
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char ecc_syndrome_table[] = {
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x4c, 0x40, 0x41, 0x48, 0x42, 0x48, 0x48, 0x49,
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x43, 0x48, 0x48, 0x49, 0x48, 0x49, 0x49, 0x4a,
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x44, 0x48, 0x48, 0x20, 0x48, 0x39, 0x4b, 0x48,
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x48, 0x25, 0x31, 0x48, 0x28, 0x48, 0x48, 0x2c,
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x45, 0x48, 0x48, 0x21, 0x48, 0x3d, 0x04, 0x48,
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x48, 0x4b, 0x35, 0x48, 0x2d, 0x48, 0x48, 0x29,
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x48, 0x00, 0x01, 0x48, 0x0a, 0x48, 0x48, 0x4b,
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x0f, 0x48, 0x48, 0x4b, 0x48, 0x49, 0x49, 0x48,
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x46, 0x48, 0x48, 0x2a, 0x48, 0x3b, 0x27, 0x48,
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x48, 0x4b, 0x33, 0x48, 0x22, 0x48, 0x48, 0x2e,
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x48, 0x19, 0x1d, 0x48, 0x1b, 0x4a, 0x48, 0x4b,
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x1f, 0x48, 0x4a, 0x4b, 0x48, 0x4b, 0x4b, 0x48,
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x48, 0x4b, 0x24, 0x48, 0x07, 0x48, 0x48, 0x36,
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x4b, 0x48, 0x48, 0x3e, 0x48, 0x30, 0x38, 0x48,
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x49, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x16, 0x48,
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x48, 0x12, 0x4b, 0x48, 0x49, 0x48, 0x48, 0x4b,
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x47, 0x48, 0x48, 0x2f, 0x48, 0x3f, 0x4b, 0x48,
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x48, 0x06, 0x37, 0x48, 0x23, 0x48, 0x48, 0x2b,
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x48, 0x05, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x32,
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x26, 0x48, 0x48, 0x3a, 0x48, 0x34, 0x3c, 0x48,
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x48, 0x11, 0x15, 0x48, 0x13, 0x4a, 0x48, 0x4b,
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x17, 0x48, 0x4a, 0x4b, 0x48, 0x4b, 0x4b, 0x48,
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x49, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x1e, 0x48,
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x48, 0x1a, 0x4b, 0x48, 0x49, 0x48, 0x48, 0x4b,
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x48, 0x08, 0x0d, 0x48, 0x02, 0x48, 0x48, 0x49,
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x03, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x4b, 0x48,
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x49, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x10, 0x48,
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x48, 0x14, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x4b,
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x49, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x18, 0x48,
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x48, 0x1c, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x4b,
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x4a, 0x0c, 0x09, 0x48, 0x0e, 0x48, 0x48, 0x4b,
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0x0b, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x4b, 0x4a
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *syndrome_unknown = "<Unknown>";
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3096c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Millerstatic void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, unsigned long udbl, unsigned long bit)
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3116c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	unsigned short scode;
3126c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	char memmod_str[64], *p;
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3146c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	if (udbl & bit) {
3156c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		scode = ecc_syndrome_table[udbl & 0xff];
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (prom_getunumber(scode, afar,
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    memmod_str, sizeof(memmod_str)) == -1)
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			p = syndrome_unknown;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			p = memmod_str;
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "CPU[%d]: UDBL Syndrome[%x] "
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       "Memory Module \"%s\"\n",
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       smp_processor_id(), scode, p);
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3266c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	if (udbh & bit) {
3276c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		scode = ecc_syndrome_table[udbh & 0xff];
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (prom_getunumber(scode, afar,
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    memmod_str, sizeof(memmod_str)) == -1)
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			p = syndrome_unknown;
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			p = memmod_str;
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "CPU[%d]: UDBH Syndrome[%x] "
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       "Memory Module \"%s\"\n",
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       smp_processor_id(), scode, p);
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3376c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
3386c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller}
3396c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
3406c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Millerstatic void spitfire_cee_log(unsigned long afsr, unsigned long afar, unsigned long udbh, unsigned long udbl, int tl1, struct pt_regs *regs)
3416c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller{
3426c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
3436c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	printk(KERN_WARNING "CPU[%d]: Correctable ECC Error "
3446c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	       "AFSR[%lx] AFAR[%016lx] UDBL[%lx] UDBH[%lx] TL>1[%d]\n",
3456c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	       smp_processor_id(), afsr, afar, udbl, udbh, tl1);
3466c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
3476c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	spitfire_log_udb_syndrome(afar, udbh, udbl, UDBE_CE);
3486c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
3496c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	/* We always log it, even if someone is listening for this
3506c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	 * trap.
3516c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	 */
3526c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	notify_die(DIE_TRAP, "Correctable ECC Error", regs,
3536c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		   0, TRAP_TYPE_CEE, SIGTRAP);
3546c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
3556c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	/* The Correctable ECC Error trap does not disable I/D caches.  So
3566c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	 * we only have to restore the ESTATE Error Enable register.
3576c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	 */
3586c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	spitfire_enable_estate_errors();
3596c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller}
3606c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
3616c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Millerstatic void spitfire_ue_log(unsigned long afsr, unsigned long afar, unsigned long udbh, unsigned long udbl, unsigned long tt, int tl1, struct pt_regs *regs)
3626c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller{
3636c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	siginfo_t info;
3646c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
3656c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	printk(KERN_WARNING "CPU[%d]: Uncorrectable Error AFSR[%lx] "
3666c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	       "AFAR[%lx] UDBL[%lx] UDBH[%ld] TT[%lx] TL>1[%d]\n",
3676c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	       smp_processor_id(), afsr, afar, udbl, udbh, tt, tl1);
3686c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
3696c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	/* XXX add more human friendly logging of the error status
3706c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	 * XXX as is implemented for cheetah
3716c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	 */
3726c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
3736c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	spitfire_log_udb_syndrome(afar, udbh, udbl, UDBE_UE);
3746c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
3756c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	/* We always log it, even if someone is listening for this
3766c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	 * trap.
3776c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	 */
3786c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	notify_die(DIE_TRAP, "Uncorrectable Error", regs,
3796c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		   0, tt, SIGTRAP);
3806c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
3816c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	if (regs->tstate & TSTATE_PRIV) {
3826c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		if (tl1)
3836c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller			dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
3846c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		die_if_kernel("UE", regs);
3856c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	}
3866c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
3876c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	/* XXX need more intelligent processing here, such as is implemented
3886c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	 * XXX for cheetah errors, in fact if the E-cache still holds the
3896c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	 * XXX line with bad parity this will loop
3906c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	 */
3916c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
3926c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	spitfire_clean_and_reenable_l1_caches();
3936c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	spitfire_enable_estate_errors();
3946c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
3956c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	if (test_thread_flag(TIF_32BIT)) {
3966c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		regs->tpc &= 0xffffffff;
3976c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		regs->tnpc &= 0xffffffff;
3986c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	}
3996c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	info.si_signo = SIGBUS;
4006c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	info.si_errno = 0;
4016c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	info.si_code = BUS_OBJERR;
4026c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	info.si_addr = (void *)0;
4036c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	info.si_trapno = 0;
4046c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	force_sig_info(SIGBUS, &info, current);
4056c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller}
4066c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
4076c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Millervoid spitfire_access_error(struct pt_regs *regs, unsigned long status_encoded, unsigned long afar)
4086c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller{
4096c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	unsigned long afsr, tt, udbh, udbl;
4106c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	int tl1;
4116c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
4126c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	afsr = (status_encoded & SFSTAT_AFSR_MASK) >> SFSTAT_AFSR_SHIFT;
4136c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	tt = (status_encoded & SFSTAT_TRAP_TYPE) >> SFSTAT_TRAP_TYPE_SHIFT;
4146c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	tl1 = (status_encoded & SFSTAT_TL_GT_ONE) ? 1 : 0;
4156c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	udbl = (status_encoded & SFSTAT_UDBL_MASK) >> SFSTAT_UDBL_SHIFT;
4166c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	udbh = (status_encoded & SFSTAT_UDBH_MASK) >> SFSTAT_UDBH_SHIFT;
4176c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
4186c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller#ifdef CONFIG_PCI
4196c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	if (tt == TRAP_TYPE_DAE &&
4206c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	    pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {
4216c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		spitfire_clean_and_reenable_l1_caches();
4226c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		spitfire_enable_estate_errors();
4236c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
4246c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		pci_poke_faulted = 1;
4256c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		regs->tnpc = regs->tpc + 4;
4266c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		return;
4276c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	}
4286c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller#endif
4296c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
4306c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	if (afsr & SFAFSR_UE)
4316c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		spitfire_ue_log(afsr, afar, udbh, udbl, tt, tl1, regs);
4326c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
4336c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	if (tt == TRAP_TYPE_CEE) {
4346c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		/* Handle the case where we took a CEE trap, but ACK'd
4356c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		 * only the UE state in the UDB error registers.
4366c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		 */
4376c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		if (afsr & SFAFSR_UE) {
4386c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller			if (udbh & UDBE_CE) {
4396c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller				__asm__ __volatile__(
4406c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller					"stxa	%0, [%1] %2\n\t"
4416c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller					"membar	#Sync"
4426c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller					: /* no outputs */
4436c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller					: "r" (udbh & UDBE_CE),
4446c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller					  "r" (0x0), "i" (ASI_UDB_ERROR_W));
4456c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller			}
4466c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller			if (udbl & UDBE_CE) {
4476c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller				__asm__ __volatile__(
4486c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller					"stxa	%0, [%1] %2\n\t"
4496c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller					"membar	#Sync"
4506c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller					: /* no outputs */
4516c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller					: "r" (udbl & UDBE_CE),
4526c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller					  "r" (0x18), "i" (ASI_UDB_ERROR_W));
4536c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller			}
4546c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		}
4556c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller
4566c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller		spitfire_cee_log(afsr, afar, udbh, udbl, tl1, regs);
4576c52a96e6cacb35403b85c3b42db0faf26f3ed85David S. Miller	}
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
460816242da3735957bee99aeba40aa60c4f120a101David S. Millerint cheetah_pcache_forced_on;
461816242da3735957bee99aeba40aa60c4f120a101David S. Miller
462816242da3735957bee99aeba40aa60c4f120a101David S. Millervoid cheetah_enable_pcache(void)
463816242da3735957bee99aeba40aa60c4f120a101David S. Miller{
464816242da3735957bee99aeba40aa60c4f120a101David S. Miller	unsigned long dcr;
465816242da3735957bee99aeba40aa60c4f120a101David S. Miller
466816242da3735957bee99aeba40aa60c4f120a101David S. Miller	printk("CHEETAH: Enabling P-Cache on cpu %d.\n",
467816242da3735957bee99aeba40aa60c4f120a101David S. Miller	       smp_processor_id());
468816242da3735957bee99aeba40aa60c4f120a101David S. Miller
469816242da3735957bee99aeba40aa60c4f120a101David S. Miller	__asm__ __volatile__("ldxa [%%g0] %1, %0"
470816242da3735957bee99aeba40aa60c4f120a101David S. Miller			     : "=r" (dcr)
471816242da3735957bee99aeba40aa60c4f120a101David S. Miller			     : "i" (ASI_DCU_CONTROL_REG));
472816242da3735957bee99aeba40aa60c4f120a101David S. Miller	dcr |= (DCU_PE | DCU_HPE | DCU_SPE | DCU_SL);
473816242da3735957bee99aeba40aa60c4f120a101David S. Miller	__asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
474816242da3735957bee99aeba40aa60c4f120a101David S. Miller			     "membar #Sync"
475816242da3735957bee99aeba40aa60c4f120a101David S. Miller			     : /* no outputs */
476816242da3735957bee99aeba40aa60c4f120a101David S. Miller			     : "r" (dcr), "i" (ASI_DCU_CONTROL_REG));
477816242da3735957bee99aeba40aa60c4f120a101David S. Miller}
478816242da3735957bee99aeba40aa60c4f120a101David S. Miller
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Cheetah error trap handling. */
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long ecache_flush_physbase;
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long ecache_flush_linesize;
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long ecache_flush_size;
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* WARNING: The error trap handlers in assembly know the precise
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	    layout of the following structure.
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * C-level handlers below use this information to log the error
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and then determine how to recover (if possible).
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct cheetah_err_info {
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0x00*/u64 afsr;
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0x08*/u64 afar;
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* D-cache state */
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0x10*/u64 dcache_data[4];	/* The actual data	*/
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0x30*/u64 dcache_index;	/* D-cache index	*/
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0x38*/u64 dcache_tag;		/* D-cache tag/valid	*/
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0x40*/u64 dcache_utag;	/* D-cache microtag	*/
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0x48*/u64 dcache_stag;	/* D-cache snooptag	*/
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* I-cache state */
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0x50*/u64 icache_data[8];	/* The actual insns + predecode	*/
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0x90*/u64 icache_index;	/* I-cache index	*/
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0x98*/u64 icache_tag;		/* I-cache phys tag	*/
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0xa0*/u64 icache_utag;	/* I-cache microtag	*/
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0xa8*/u64 icache_stag;	/* I-cache snooptag	*/
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0xb0*/u64 icache_upper;	/* I-cache upper-tag	*/
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0xb8*/u64 icache_lower;	/* I-cache lower-tag	*/
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* E-cache state */
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0xc0*/u64 ecache_data[4];	/* 32 bytes from staging registers */
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0xe0*/u64 ecache_index;	/* E-cache index	*/
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0xe8*/u64 ecache_tag;		/* E-cache tag/state	*/
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0xf0*/u64 __pad[32 - 30];
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CHAFSR_INVALID		((u64)-1L)
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This table is ordered in priority of errors and matches the
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * AFAR overwrite policy as well.
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct afsr_error_table {
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mask;
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *name;
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_PERR_msg[] =
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"System interface protocol error";
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_IERR_msg[] =
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Internal processor error";
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_ISAP_msg[] =
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"System request parity error on incoming addresss";
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_UCU_msg[] =
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Uncorrectable E-cache ECC error for ifetch/data";
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_UCC_msg[] =
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"SW Correctable E-cache ECC error for ifetch/data";
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_UE_msg[] =
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Uncorrectable system bus data ECC error for read";
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_EDU_msg[] =
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Uncorrectable E-cache ECC error for stmerge/blkld";
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_EMU_msg[] =
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Uncorrectable system bus MTAG error";
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_WDU_msg[] =
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Uncorrectable E-cache ECC error for writeback";
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_CPU_msg[] =
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Uncorrectable ECC error for copyout";
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_CE_msg[] =
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"HW corrected system bus data ECC error for read";
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_EDC_msg[] =
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"HW corrected E-cache ECC error for stmerge/blkld";
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_EMC_msg[] =
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"HW corrected system bus MTAG ECC error";
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_WDC_msg[] =
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"HW corrected E-cache ECC error for writeback";
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_CPC_msg[] =
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"HW corrected ECC error for copyout";
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_TO_msg[] =
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Unmapped error from system bus";
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_BERR_msg[] =
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Bus error response from system bus";
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_IVC_msg[] =
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"HW corrected system bus data ECC error for ivec read";
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHAFSR_IVU_msg[] =
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Uncorrectable system bus data ECC error for ivec read";
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct afsr_error_table __cheetah_error_table[] = {
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_PERR,	CHAFSR_PERR_msg		},
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_IERR,	CHAFSR_IERR_msg		},
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_ISAP,	CHAFSR_ISAP_msg		},
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_UCU,	CHAFSR_UCU_msg		},
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_UCC,	CHAFSR_UCC_msg		},
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_UE,	CHAFSR_UE_msg		},
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_EDU,	CHAFSR_EDU_msg		},
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_EMU,	CHAFSR_EMU_msg		},
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_WDU,	CHAFSR_WDU_msg		},
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_CPU,	CHAFSR_CPU_msg		},
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_CE,	CHAFSR_CE_msg		},
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_EDC,	CHAFSR_EDC_msg		},
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_EMC,	CHAFSR_EMC_msg		},
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_WDC,	CHAFSR_WDC_msg		},
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_CPC,	CHAFSR_CPC_msg		},
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_TO,	CHAFSR_TO_msg		},
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_BERR,	CHAFSR_BERR_msg		},
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* These two do not update the AFAR. */
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_IVC,	CHAFSR_IVC_msg		},
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_IVU,	CHAFSR_IVU_msg		},
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	0,		NULL			},
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHPAFSR_DTO_msg[] =
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"System bus unmapped error for prefetch/storequeue-read";
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHPAFSR_DBERR_msg[] =
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"System bus error for prefetch/storequeue-read";
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHPAFSR_THCE_msg[] =
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Hardware corrected E-cache Tag ECC error";
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHPAFSR_TSCE_msg[] =
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"SW handled correctable E-cache Tag ECC error";
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHPAFSR_TUE_msg[] =
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Uncorrectable E-cache Tag ECC error";
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char CHPAFSR_DUE_msg[] =
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"System bus uncorrectable data ECC error due to prefetch/store-fill";
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct afsr_error_table __cheetah_plus_error_table[] = {
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_PERR,	CHAFSR_PERR_msg		},
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_IERR,	CHAFSR_IERR_msg		},
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_ISAP,	CHAFSR_ISAP_msg		},
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_UCU,	CHAFSR_UCU_msg		},
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_UCC,	CHAFSR_UCC_msg		},
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_UE,	CHAFSR_UE_msg		},
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_EDU,	CHAFSR_EDU_msg		},
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_EMU,	CHAFSR_EMU_msg		},
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_WDU,	CHAFSR_WDU_msg		},
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_CPU,	CHAFSR_CPU_msg		},
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_CE,	CHAFSR_CE_msg		},
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_EDC,	CHAFSR_EDC_msg		},
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_EMC,	CHAFSR_EMC_msg		},
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_WDC,	CHAFSR_WDC_msg		},
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_CPC,	CHAFSR_CPC_msg		},
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_TO,	CHAFSR_TO_msg		},
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_BERR,	CHAFSR_BERR_msg		},
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHPAFSR_DTO,	CHPAFSR_DTO_msg		},
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHPAFSR_DBERR,	CHPAFSR_DBERR_msg	},
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHPAFSR_THCE,	CHPAFSR_THCE_msg	},
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHPAFSR_TSCE,	CHPAFSR_TSCE_msg	},
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHPAFSR_TUE,	CHPAFSR_TUE_msg		},
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHPAFSR_DUE,	CHPAFSR_DUE_msg		},
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* These two do not update the AFAR. */
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_IVC,	CHAFSR_IVC_msg		},
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_IVU,	CHAFSR_IVU_msg		},
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	0,		NULL			},
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char JPAFSR_JETO_msg[] =
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"System interface protocol error, hw timeout caused";
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char JPAFSR_SCE_msg[] =
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Parity error on system snoop results";
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char JPAFSR_JEIC_msg[] =
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"System interface protocol error, illegal command detected";
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char JPAFSR_JEIT_msg[] =
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"System interface protocol error, illegal ADTYPE detected";
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char JPAFSR_OM_msg[] =
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Out of range memory error has occurred";
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char JPAFSR_ETP_msg[] =
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Parity error on L2 cache tag SRAM";
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char JPAFSR_UMS_msg[] =
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Error due to unsupported store";
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char JPAFSR_RUE_msg[] =
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Uncorrectable ECC error from remote cache/memory";
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char JPAFSR_RCE_msg[] =
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Correctable ECC error from remote cache/memory";
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char JPAFSR_BP_msg[] =
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"JBUS parity error on returned read data";
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char JPAFSR_WBP_msg[] =
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"JBUS parity error on data for writeback or block store";
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char JPAFSR_FRC_msg[] =
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Foreign read to DRAM incurring correctable ECC error";
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char JPAFSR_FRU_msg[] =
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"Foreign read to DRAM incurring uncorrectable ECC error";
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct afsr_error_table __jalapeno_error_table[] = {
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	JPAFSR_JETO,	JPAFSR_JETO_msg		},
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	JPAFSR_SCE,	JPAFSR_SCE_msg		},
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	JPAFSR_JEIC,	JPAFSR_JEIC_msg		},
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	JPAFSR_JEIT,	JPAFSR_JEIT_msg		},
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_PERR,	CHAFSR_PERR_msg		},
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_IERR,	CHAFSR_IERR_msg		},
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_ISAP,	CHAFSR_ISAP_msg		},
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_UCU,	CHAFSR_UCU_msg		},
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_UCC,	CHAFSR_UCC_msg		},
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_UE,	CHAFSR_UE_msg		},
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_EDU,	CHAFSR_EDU_msg		},
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	JPAFSR_OM,	JPAFSR_OM_msg		},
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_WDU,	CHAFSR_WDU_msg		},
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_CPU,	CHAFSR_CPU_msg		},
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_CE,	CHAFSR_CE_msg		},
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_EDC,	CHAFSR_EDC_msg		},
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	JPAFSR_ETP,	JPAFSR_ETP_msg		},
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_WDC,	CHAFSR_WDC_msg		},
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_CPC,	CHAFSR_CPC_msg		},
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_TO,	CHAFSR_TO_msg		},
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_BERR,	CHAFSR_BERR_msg		},
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	JPAFSR_UMS,	JPAFSR_UMS_msg		},
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	JPAFSR_RUE,	JPAFSR_RUE_msg		},
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	JPAFSR_RCE,	JPAFSR_RCE_msg		},
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	JPAFSR_BP,	JPAFSR_BP_msg		},
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	JPAFSR_WBP,	JPAFSR_WBP_msg		},
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	JPAFSR_FRC,	JPAFSR_FRC_msg		},
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	JPAFSR_FRU,	JPAFSR_FRU_msg		},
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* These two do not update the AFAR. */
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	CHAFSR_IVU,	CHAFSR_IVU_msg		},
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{	0,		NULL			},
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct afsr_error_table *cheetah_error_table;
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long cheetah_afsr_errors;
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This is allocated at boot time based upon the largest hardware
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cpu ID in the system.  We allocate two entries per cpu, one for
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * TL==0 logging and one for TL >= 1 logging.
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct cheetah_err_info *cheetah_error_log;
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic __inline__ struct cheetah_err_info *cheetah_get_error_log(unsigned long afsr)
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cheetah_err_info *p;
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int cpu = smp_processor_id();
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!cheetah_error_log)
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p = cheetah_error_log + (cpu * 2);
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((afsr & CHAFSR_TL1) != 0UL)
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p++;
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return p;
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern unsigned int tl0_icpe[], tl1_icpe[];
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern unsigned int tl0_dcpe[], tl1_dcpe[];
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern unsigned int tl0_fecc[], tl1_fecc[];
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern unsigned int tl0_cee[], tl1_cee[];
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern unsigned int tl0_iae[], tl1_iae[];
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern unsigned int tl0_dae[], tl1_dae[];
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern unsigned int cheetah_plus_icpe_trap_vector[], cheetah_plus_icpe_trap_vector_tl1[];
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern unsigned int cheetah_plus_dcpe_trap_vector[], cheetah_plus_dcpe_trap_vector_tl1[];
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern unsigned int cheetah_fecc_trap_vector[], cheetah_fecc_trap_vector_tl1[];
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern unsigned int cheetah_cee_trap_vector[], cheetah_cee_trap_vector_tl1[];
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern unsigned int cheetah_deferred_trap_vector[], cheetah_deferred_trap_vector_tl1[];
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init cheetah_ecache_flush_init(void)
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long largest_size, smallest_linesize, order, ver;
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int node, i, instance;
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Scan all cpu device tree nodes, note two values:
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * 1) largest E-cache size
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * 2) smallest E-cache line size
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	largest_size = 0UL;
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smallest_linesize = ~0UL;
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	instance = 0;
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (!cpu_find_by_instance(instance, &node, NULL)) {
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long val;
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val = prom_getintdefault(node, "ecache-size",
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					 (2 * 1024 * 1024));
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val > largest_size)
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			largest_size = val;
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val = prom_getintdefault(node, "ecache-line-size", 64);
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val < smallest_linesize)
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			smallest_linesize = val;
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		instance++;
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (largest_size == 0UL || smallest_linesize == ~0UL) {
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_printf("cheetah_ecache_flush_init: Cannot probe cpu E-cache "
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    "parameters.\n");
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_halt();
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ecache_flush_size = (2 * largest_size);
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ecache_flush_linesize = smallest_linesize;
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
76010147570f9eaff3920f0c67bad7244c2eb958d4fDavid S. Miller	ecache_flush_physbase = find_ecache_flush_span(ecache_flush_size);
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
76210147570f9eaff3920f0c67bad7244c2eb958d4fDavid S. Miller	if (ecache_flush_physbase == ~0UL) {
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_printf("cheetah_ecache_flush_init: Cannot find %d byte "
76410147570f9eaff3920f0c67bad7244c2eb958d4fDavid S. Miller			    "contiguous physical memory.\n",
76510147570f9eaff3920f0c67bad7244c2eb958d4fDavid S. Miller			    ecache_flush_size);
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_halt();
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Now allocate error trap reporting scoreboard. */
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	node = NR_CPUS * (2 * sizeof(struct cheetah_err_info));
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (order = 0; order < MAX_ORDER; order++) {
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((PAGE_SIZE << order) >= node)
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cheetah_error_log = (struct cheetah_err_info *)
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__get_free_pages(GFP_KERNEL, order);
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!cheetah_error_log) {
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_printf("cheetah_ecache_flush_init: Failed to allocate "
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    "error logging scoreboard (%d bytes).\n", node);
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_halt();
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(cheetah_error_log, 0, PAGE_SIZE << order);
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Mark all AFSRs as invalid so that the trap handler will
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * log new new information there.
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 2 * NR_CPUS; i++)
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cheetah_error_log[i].afsr = CHAFSR_INVALID;
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ ("rdpr %%ver, %0" : "=r" (ver));
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((ver >> 32) == 0x003e0016) {
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cheetah_error_table = &__jalapeno_error_table[0];
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cheetah_afsr_errors = JPAFSR_ERRORS;
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if ((ver >> 32) == 0x003e0015) {
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cheetah_error_table = &__cheetah_plus_error_table[0];
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cheetah_afsr_errors = CHPAFSR_ERRORS;
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cheetah_error_table = &__cheetah_error_table[0];
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cheetah_afsr_errors = CHAFSR_ERRORS;
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Now patch trap tables. */
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(tl0_fecc, cheetah_fecc_trap_vector, (8 * 4));
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(tl1_fecc, cheetah_fecc_trap_vector_tl1, (8 * 4));
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(tl0_cee, cheetah_cee_trap_vector, (8 * 4));
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(tl1_cee, cheetah_cee_trap_vector_tl1, (8 * 4));
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(tl0_iae, cheetah_deferred_trap_vector, (8 * 4));
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(tl1_iae, cheetah_deferred_trap_vector_tl1, (8 * 4));
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(tl0_dae, cheetah_deferred_trap_vector, (8 * 4));
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(tl1_dae, cheetah_deferred_trap_vector_tl1, (8 * 4));
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tlb_type == cheetah_plus) {
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(tl0_dcpe, cheetah_plus_dcpe_trap_vector, (8 * 4));
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(tl1_dcpe, cheetah_plus_dcpe_trap_vector_tl1, (8 * 4));
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(tl0_icpe, cheetah_plus_icpe_trap_vector, (8 * 4));
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(tl1_icpe, cheetah_plus_icpe_trap_vector_tl1, (8 * 4));
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flushi(PAGE_OFFSET);
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void cheetah_flush_ecache(void)
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flush_base = ecache_flush_physbase;
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flush_linesize = ecache_flush_linesize;
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flush_size = ecache_flush_size;
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("1: subcc	%0, %4, %0\n\t"
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "   bne,pt	%%xcc, 1b\n\t"
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "    ldxa	[%2 + %0] %3, %%g0\n\t"
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "=&r" (flush_size)
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "0" (flush_size), "r" (flush_base),
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       "i" (ASI_PHYS_USE_EC), "r" (flush_linesize));
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void cheetah_flush_ecache_line(unsigned long physaddr)
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long alias;
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	physaddr &= ~(8UL - 1UL);
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	physaddr = (ecache_flush_physbase +
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    (physaddr & ((ecache_flush_size>>1UL) - 1UL)));
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	alias = physaddr + (ecache_flush_size >> 1UL);
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("ldxa [%0] %2, %%g0\n\t"
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "ldxa [%1] %2, %%g0\n\t"
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "membar #Sync"
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : /* no outputs */
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "r" (physaddr), "r" (alias),
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       "i" (ASI_PHYS_USE_EC));
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Unfortunately, the diagnostic access to the I-cache tags we need to
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * use to clear the thing interferes with I-cache coherency transactions.
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * So we must only flush the I-cache when it is disabled.
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __cheetah_flush_icache(void)
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
85780dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller	unsigned int icache_size, icache_line_size;
85880dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller	unsigned long addr;
85980dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller
86080dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller	icache_size = local_cpu_data().icache_size;
86180dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller	icache_line_size = local_cpu_data().icache_line_size;
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Clear the valid bits in all the tags. */
86480dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller	for (addr = 0; addr < icache_size; addr += icache_line_size) {
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "membar #Sync"
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     : /* no outputs */
86880dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller				     : "r" (addr | (2 << 3)),
86980dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller				       "i" (ASI_IC_TAG));
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void cheetah_flush_icache(void)
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long dcu_save;
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Save current DCU, disable I-cache. */
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("ldxa [%%g0] %1, %0\n\t"
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "or %0, %2, %%g1\n\t"
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "stxa %%g1, [%%g0] %1\n\t"
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "membar #Sync"
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "=r" (dcu_save)
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "i" (ASI_DCU_CONTROL_REG), "i" (DCU_IC)
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "g1");
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__cheetah_flush_icache();
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Restore DCU register */
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "membar #Sync"
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : /* no outputs */
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "r" (dcu_save), "i" (ASI_DCU_CONTROL_REG));
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void cheetah_flush_dcache(void)
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
89780dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller	unsigned int dcache_size, dcache_line_size;
89880dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller	unsigned long addr;
89980dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller
90080dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller	dcache_size = local_cpu_data().dcache_size;
90180dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller	dcache_line_size = local_cpu_data().dcache_line_size;
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
90380dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller	for (addr = 0; addr < dcache_size; addr += dcache_line_size) {
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "membar #Sync"
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     : /* no outputs */
90780dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller				     : "r" (addr), "i" (ASI_DCACHE_TAG));
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* In order to make the even parity correct we must do two things.
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * First, we clear DC_data_parity and set DC_utag to an appropriate value.
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Next, we clear out all 32-bytes of data for that line.  Data of
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * all-zero + tag parity value of zero == correct parity.
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void cheetah_plus_zap_dcache_parity(void)
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
91880dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller	unsigned int dcache_size, dcache_line_size;
91980dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller	unsigned long addr;
92080dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller
92180dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller	dcache_size = local_cpu_data().dcache_size;
92280dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller	dcache_line_size = local_cpu_data().dcache_line_size;
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
92480dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller	for (addr = 0; addr < dcache_size; addr += dcache_line_size) {
92580dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller		unsigned long tag = (addr >> 14);
92680dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller		unsigned long line;
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__asm__ __volatile__("membar	#Sync\n\t"
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "stxa	%0, [%1] %2\n\t"
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "membar	#Sync"
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     : /* no outputs */
93280dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller				     : "r" (tag), "r" (addr),
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       "i" (ASI_DCACHE_UTAG));
93480dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller		for (line = addr; line < addr + dcache_line_size; line += 8)
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__asm__ __volatile__("membar	#Sync\n\t"
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     "stxa	%%g0, [%0] %1\n\t"
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     "membar	#Sync"
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     : /* no outputs */
93980dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller					     : "r" (line),
94080dc0d6b44ce0f01df58d8899e46612690ed7d81David S. Miller					       "i" (ASI_DCACHE_DATA));
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Conversion tables used to frob Cheetah AFSR syndrome values into
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * something palatable to the memory controller driver get_unumber
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * routine.
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MT0	137
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MT1	138
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MT2	139
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NONE	254
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTC0	140
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTC1	141
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTC2	142
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTC3	143
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C0	128
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C1	129
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C2	130
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C3	131
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C4	132
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C5	133
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C6	134
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C7	135
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define C8	136
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M2	144
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M3	145
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M4	146
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M	147
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned char cheetah_ecc_syntab[] = {
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*00*/NONE, C0, C1, M2, C2, M2, M3, 47, C3, M2, M2, 53, M2, 41, 29, M,
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*01*/C4, M, M, 50, M2, 38, 25, M2, M2, 33, 24, M2, 11, M, M2, 16,
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*02*/C5, M, M, 46, M2, 37, 19, M2, M, 31, 32, M, 7, M2, M2, 10,
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*03*/M2, 40, 13, M2, 59, M, M2, 66, M, M2, M2, 0, M2, 67, 71, M,
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*04*/C6, M, M, 43, M, 36, 18, M, M2, 49, 15, M, 63, M2, M2, 6,
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*05*/M2, 44, 28, M2, M, M2, M2, 52, 68, M2, M2, 62, M2, M3, M3, M4,
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*06*/M2, 26, 106, M2, 64, M, M2, 2, 120, M, M2, M3, M, M3, M3, M4,
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*07*/116, M2, M2, M3, M2, M3, M, M4, M2, 58, 54, M2, M, M4, M4, M3,
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*08*/C7, M2, M, 42, M, 35, 17, M2, M, 45, 14, M2, 21, M2, M2, 5,
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*09*/M, 27, M, M, 99, M, M, 3, 114, M2, M2, 20, M2, M3, M3, M,
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0a*/M2, 23, 113, M2, 112, M2, M, 51, 95, M, M2, M3, M2, M3, M3, M2,
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0b*/103, M, M2, M3, M2, M3, M3, M4, M2, 48, M, M, 73, M2, M, M3,
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0c*/M2, 22, 110, M2, 109, M2, M, 9, 108, M2, M, M3, M2, M3, M3, M,
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0d*/102, M2, M, M, M2, M3, M3, M, M2, M3, M3, M2, M, M4, M, M3,
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0e*/98, M, M2, M3, M2, M, M3, M4, M2, M3, M3, M4, M3, M, M, M,
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*0f*/M2, M3, M3, M, M3, M, M, M, 56, M4, M, M3, M4, M, M, M,
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*10*/C8, M, M2, 39, M, 34, 105, M2, M, 30, 104, M, 101, M, M, 4,
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*11*/M, M, 100, M, 83, M, M2, 12, 87, M, M, 57, M2, M, M3, M,
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*12*/M2, 97, 82, M2, 78, M2, M2, 1, 96, M, M, M, M, M, M3, M2,
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*13*/94, M, M2, M3, M2, M, M3, M, M2, M, 79, M, 69, M, M4, M,
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*14*/M2, 93, 92, M, 91, M, M2, 8, 90, M2, M2, M, M, M, M, M4,
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*15*/89, M, M, M3, M2, M3, M3, M, M, M, M3, M2, M3, M2, M, M3,
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*16*/86, M, M2, M3, M2, M, M3, M, M2, M, M3, M, M3, M, M, M3,
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*17*/M, M, M3, M2, M3, M2, M4, M, 60, M, M2, M3, M4, M, M, M2,
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*18*/M2, 88, 85, M2, 84, M, M2, 55, 81, M2, M2, M3, M2, M3, M3, M4,
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*19*/77, M, M, M, M2, M3, M, M, M2, M3, M3, M4, M3, M2, M, M,
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*1a*/74, M, M2, M3, M, M, M3, M, M, M, M3, M, M3, M, M4, M3,
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*1b*/M2, 70, 107, M4, 65, M2, M2, M, 127, M, M, M, M2, M3, M3, M,
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*1c*/80, M2, M2, 72, M, 119, 118, M, M2, 126, 76, M, 125, M, M4, M3,
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*1d*/M2, 115, 124, M, 75, M, M, M3, 61, M, M4, M, M4, M, M, M,
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*1e*/M, 123, 122, M4, 121, M4, M, M3, 117, M2, M2, M3, M4, M3, M, M,
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*1f*/111, M, M, M, M4, M3, M3, M, M, M, M3, M, M3, M2, M, M
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned char cheetah_mtag_syntab[] = {
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       NONE, MTC0,
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       MTC1, NONE,
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       MTC2, NONE,
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       NONE, MT0,
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       MTC3, NONE,
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       NONE, MT1,
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       NONE, MT2,
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       NONE, NONE
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Return the highest priority error conditon mentioned. */
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic __inline__ unsigned long cheetah_get_hipri(unsigned long afsr)
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long tmp = 0;
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; cheetah_error_table[i].mask; i++) {
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((tmp = (afsr & cheetah_error_table[i].mask)) != 0UL)
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return tmp;
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return tmp;
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char *cheetah_get_string(unsigned long bit)
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; cheetah_error_table[i].mask; i++) {
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((bit & cheetah_error_table[i].mask) != 0UL)
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return cheetah_error_table[i].name;
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return "???";
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern int chmc_getunumber(int, unsigned long, char *, int);
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info,
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       unsigned long afsr, unsigned long afar, int recoverable)
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long hipri;
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char unum[256];
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s" "ERROR(%d): Cheetah error trap taken afsr[%016lx] afar[%016lx] TL1(%d)\n",
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       afsr, afar,
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (afsr & CHAFSR_TL1) ? 1 : 0);
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s" "ERROR(%d): TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n",
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       regs->tpc, regs->tnpc, regs->tstate);
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s" "ERROR(%d): M_SYND(%lx),  E_SYND(%lx)%s%s\n",
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT,
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT,
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (afsr & CHAFSR_ME) ? ", Multiple Errors" : "",
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (afsr & CHAFSR_PRIV) ? ", Privileged" : "");
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hipri = cheetah_get_hipri(afsr);
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s" "ERROR(%d): Highest priority error (%016lx) \"%s\"\n",
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       hipri, cheetah_get_string(hipri));
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Try to get unumber if relevant. */
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ESYND_ERRORS	(CHAFSR_IVC | CHAFSR_IVU | \
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 CHAFSR_CPC | CHAFSR_CPU | \
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 CHAFSR_UE  | CHAFSR_CE  | \
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 CHAFSR_EDC | CHAFSR_EDU  | \
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 CHAFSR_UCC | CHAFSR_UCU  | \
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 CHAFSR_WDU | CHAFSR_WDC)
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MSYND_ERRORS	(CHAFSR_EMC | CHAFSR_EMU)
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (afsr & ESYND_ERRORS) {
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int syndrome;
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int ret;
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		syndrome = (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT;
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		syndrome = cheetah_ecc_syntab[syndrome];
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum));
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ret != -1)
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("%s" "ERROR(%d): AFAR E-syndrome [%s]\n",
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       (recoverable ? KERN_WARNING : KERN_CRIT),
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       smp_processor_id(), unum);
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (afsr & MSYND_ERRORS) {
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int syndrome;
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int ret;
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		syndrome = (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT;
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		syndrome = cheetah_mtag_syntab[syndrome];
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum));
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ret != -1)
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("%s" "ERROR(%d): AFAR M-syndrome [%s]\n",
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       (recoverable ? KERN_WARNING : KERN_CRIT),
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       smp_processor_id(), unum);
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Now dump the cache snapshots. */
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s" "ERROR(%d): D-cache idx[%x] tag[%016lx] utag[%016lx] stag[%016lx]\n",
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (int) info->dcache_index,
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->dcache_tag,
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->dcache_utag,
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->dcache_stag);
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s" "ERROR(%d): D-cache data0[%016lx] data1[%016lx] data2[%016lx] data3[%016lx]\n",
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->dcache_data[0],
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->dcache_data[1],
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->dcache_data[2],
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->dcache_data[3]);
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s" "ERROR(%d): I-cache idx[%x] tag[%016lx] utag[%016lx] stag[%016lx] "
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       "u[%016lx] l[%016lx]\n",
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (int) info->icache_index,
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->icache_tag,
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->icache_utag,
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->icache_stag,
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->icache_upper,
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->icache_lower);
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s" "ERROR(%d): I-cache INSN0[%016lx] INSN1[%016lx] INSN2[%016lx] INSN3[%016lx]\n",
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->icache_data[0],
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->icache_data[1],
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->icache_data[2],
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->icache_data[3]);
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s" "ERROR(%d): I-cache INSN4[%016lx] INSN5[%016lx] INSN6[%016lx] INSN7[%016lx]\n",
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->icache_data[4],
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->icache_data[5],
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->icache_data[6],
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->icache_data[7]);
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s" "ERROR(%d): E-cache idx[%x] tag[%016lx]\n",
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (int) info->ecache_index, info->ecache_tag);
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s" "ERROR(%d): E-cache data0[%016lx] data1[%016lx] data2[%016lx] data3[%016lx]\n",
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->ecache_data[0],
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->ecache_data[1],
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->ecache_data[2],
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       info->ecache_data[3]);
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	afsr = (afsr & ~hipri) & cheetah_afsr_errors;
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (afsr != 0UL) {
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long bit = cheetah_get_hipri(afsr);
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("%s" "ERROR: Multiple-error (%016lx) \"%s\"\n",
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       (recoverable ? KERN_WARNING : KERN_CRIT),
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       bit, cheetah_get_string(bit));
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		afsr &= ~bit;
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!recoverable)
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_CRIT "ERROR: This condition is not recoverable.\n");
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cheetah_recheck_errors(struct cheetah_err_info *logp)
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long afsr, afar;
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("ldxa [%%g0] %1, %0\n\t"
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "=r" (afsr)
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "i" (ASI_AFSR));
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((afsr & cheetah_afsr_errors) != 0) {
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (logp != NULL) {
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__asm__ __volatile__("ldxa [%%g0] %1, %0\n\t"
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     : "=r" (afar)
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					     : "i" (ASI_AFAR));
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			logp->afsr = afsr;
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			logp->afar = afar;
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = 1;
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "membar #Sync\n\t"
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : : "r" (afsr), "i" (ASI_AFSR));
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid cheetah_fecc_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar)
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cheetah_err_info local_snapshot, *p;
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int recoverable;
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Flush E-cache */
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cheetah_flush_ecache();
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p = cheetah_get_error_log(afsr);
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!p) {
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_printf("ERROR: Early Fast-ECC error afsr[%016lx] afar[%016lx]\n",
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    afsr, afar);
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_printf("ERROR: CPU(%d) TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n",
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    smp_processor_id(), regs->tpc, regs->tnpc, regs->tstate);
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_halt();
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Grab snapshot of logged error. */
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(&local_snapshot, p, sizeof(local_snapshot));
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If the current trap snapshot does not match what the
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * trap handler passed along into our args, big trouble.
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * In such a case, mark the local copy as invalid.
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Else, it matches and we mark the afsr in the non-local
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * copy as invalid so we may log new error traps there.
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (p->afsr != afsr || p->afar != afar)
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		local_snapshot.afsr = CHAFSR_INVALID;
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p->afsr = CHAFSR_INVALID;
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cheetah_flush_icache();
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cheetah_flush_dcache();
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Re-enable I-cache/D-cache */
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "or %%g1, %1, %%g1\n\t"
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "stxa %%g1, [%%g0] %0\n\t"
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "membar #Sync"
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : /* no outputs */
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "i" (ASI_DCU_CONTROL_REG),
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       "i" (DCU_DC | DCU_IC)
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "g1");
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Re-enable error reporting */
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "or %%g1, %1, %%g1\n\t"
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "stxa %%g1, [%%g0] %0\n\t"
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "membar #Sync"
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : /* no outputs */
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "i" (ASI_ESTATE_ERROR_EN),
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       "i" (ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN)
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "g1");
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Decide if we can continue after handling this trap and
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * logging the error.
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	recoverable = 1;
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (afsr & (CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP))
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		recoverable = 0;
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Re-check AFSR/AFAR.  What we are looking for here is whether a new
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * error was logged while we had error reporting traps disabled.
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cheetah_recheck_errors(&local_snapshot)) {
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long new_afsr = local_snapshot.afsr;
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* If we got a new asynchronous error, die... */
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (new_afsr & (CHAFSR_EMU | CHAFSR_EDU |
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				CHAFSR_WDU | CHAFSR_CPU |
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				CHAFSR_IVU | CHAFSR_UE |
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				CHAFSR_BERR | CHAFSR_TO))
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			recoverable = 0;
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Log errors. */
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cheetah_log_errors(regs, &local_snapshot, afsr, afar, recoverable);
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!recoverable)
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		panic("Irrecoverable Fast-ECC error trap.\n");
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Flush E-cache to kick the error trap handlers out. */
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cheetah_flush_ecache();
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Try to fix a correctable error by pushing the line out from
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the E-cache.  Recheck error reporting registers to see if the
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * problem is intermittent.
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cheetah_fix_ce(unsigned long physaddr)
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long orig_estate;
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long alias1, alias2;
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure correctable error traps are disabled. */
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("ldxa	[%%g0] %2, %0\n\t"
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "andn	%0, %1, %%g1\n\t"
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "stxa	%%g1, [%%g0] %2\n\t"
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "membar	#Sync"
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "=&r" (orig_estate)
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "i" (ESTATE_ERROR_CEEN),
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       "i" (ASI_ESTATE_ERROR_EN)
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "g1");
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We calculate alias addresses that will force the
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * cache line in question out of the E-cache.  Then
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * we bring it back in with an atomic instruction so
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * that we get it in some modified/exclusive state,
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * then we displace it again to try and get proper ECC
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * pushed back into the system.
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	physaddr &= ~(8UL - 1UL);
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	alias1 = (ecache_flush_physbase +
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  (physaddr & ((ecache_flush_size >> 1) - 1)));
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	alias2 = alias1 + (ecache_flush_size >> 1);
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("ldxa	[%0] %3, %%g0\n\t"
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "ldxa	[%1] %3, %%g0\n\t"
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "casxa	[%2] %3, %%g0, %%g0\n\t"
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "membar	#StoreLoad | #StoreStore\n\t"
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "ldxa	[%0] %3, %%g0\n\t"
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "ldxa	[%1] %3, %%g0\n\t"
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "membar	#Sync"
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : /* no outputs */
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "r" (alias1), "r" (alias2),
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       "r" (physaddr), "i" (ASI_PHYS_USE_EC));
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Did that trigger another error? */
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cheetah_recheck_errors(NULL)) {
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Try one more time. */
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__asm__ __volatile__("ldxa [%0] %1, %%g0\n\t"
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "membar #Sync"
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     : : "r" (physaddr), "i" (ASI_PHYS_USE_EC));
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cheetah_recheck_errors(NULL))
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = 2;
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ret = 1;
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* No new error, intermittent problem. */
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = 0;
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Restore error enables. */
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("stxa	%0, [%%g0] %1\n\t"
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "membar	#Sync"
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : : "r" (orig_estate), "i" (ASI_ESTATE_ERROR_EN));
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Return non-zero if PADDR is a valid physical memory address. */
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cheetah_check_main_memory(unsigned long paddr)
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
133410147570f9eaff3920f0c67bad7244c2eb958d4fDavid S. Miller	unsigned long vaddr = PAGE_OFFSET + paddr;
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
133613edad7a5cef1c952459742482482a6b05e1a8a1David S. Miller	if (vaddr > (unsigned long) high_memory)
1337ed3ffaf7b5e0262cb860f106a6632933671cc88fDavid S. Miller		return 0;
1338ed3ffaf7b5e0262cb860f106a6632933671cc88fDavid S. Miller
133910147570f9eaff3920f0c67bad7244c2eb958d4fDavid S. Miller	return kern_addr_valid(vaddr);
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid cheetah_cee_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar)
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cheetah_err_info local_snapshot, *p;
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int recoverable, is_memory;
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p = cheetah_get_error_log(afsr);
13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!p) {
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_printf("ERROR: Early CEE error afsr[%016lx] afar[%016lx]\n",
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    afsr, afar);
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_printf("ERROR: CPU(%d) TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n",
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    smp_processor_id(), regs->tpc, regs->tnpc, regs->tstate);
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_halt();
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Grab snapshot of logged error. */
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(&local_snapshot, p, sizeof(local_snapshot));
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If the current trap snapshot does not match what the
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * trap handler passed along into our args, big trouble.
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * In such a case, mark the local copy as invalid.
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Else, it matches and we mark the afsr in the non-local
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * copy as invalid so we may log new error traps there.
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (p->afsr != afsr || p->afar != afar)
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		local_snapshot.afsr = CHAFSR_INVALID;
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p->afsr = CHAFSR_INVALID;
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	is_memory = cheetah_check_main_memory(afar);
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (is_memory && (afsr & CHAFSR_CE) != 0UL) {
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* XXX Might want to log the results of this operation
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * XXX somewhere... -DaveM
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cheetah_fix_ce(afar);
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int flush_all, flush_line;
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		flush_all = flush_line = 0;
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((afsr & CHAFSR_EDC) != 0UL) {
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((afsr & cheetah_afsr_errors) == CHAFSR_EDC)
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flush_line = 1;
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flush_all = 1;
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if ((afsr & CHAFSR_CPC) != 0UL) {
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((afsr & cheetah_afsr_errors) == CHAFSR_CPC)
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flush_line = 1;
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flush_all = 1;
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Trap handler only disabled I-cache, flush it. */
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cheetah_flush_icache();
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Re-enable I-cache */
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "or %%g1, %1, %%g1\n\t"
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "stxa %%g1, [%%g0] %0\n\t"
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "membar #Sync"
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     : /* no outputs */
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     : "i" (ASI_DCU_CONTROL_REG),
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "i" (DCU_IC)
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     : "g1");
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (flush_all)
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cheetah_flush_ecache();
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else if (flush_line)
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cheetah_flush_ecache_line(afar);
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Re-enable error reporting */
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "or %%g1, %1, %%g1\n\t"
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "stxa %%g1, [%%g0] %0\n\t"
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "membar #Sync"
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : /* no outputs */
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "i" (ASI_ESTATE_ERROR_EN),
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       "i" (ESTATE_ERROR_CEEN)
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "g1");
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Decide if we can continue after handling this trap and
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * logging the error.
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	recoverable = 1;
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (afsr & (CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP))
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		recoverable = 0;
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Re-check AFSR/AFAR */
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(void) cheetah_recheck_errors(&local_snapshot);
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Log errors. */
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cheetah_log_errors(regs, &local_snapshot, afsr, afar, recoverable);
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!recoverable)
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		panic("Irrecoverable Correctable-ECC error trap.\n");
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar)
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct cheetah_err_info local_snapshot, *p;
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int recoverable, is_memory;
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PCI
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Check for the special PCI poke sequence. */
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cheetah_flush_icache();
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cheetah_flush_dcache();
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Re-enable I-cache/D-cache */
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "or %%g1, %1, %%g1\n\t"
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "stxa %%g1, [%%g0] %0\n\t"
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "membar #Sync"
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     : /* no outputs */
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     : "i" (ASI_DCU_CONTROL_REG),
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       "i" (DCU_DC | DCU_IC)
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     : "g1");
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Re-enable error reporting */
14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "or %%g1, %1, %%g1\n\t"
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "stxa %%g1, [%%g0] %0\n\t"
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "membar #Sync"
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     : /* no outputs */
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     : "i" (ASI_ESTATE_ERROR_EN),
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       "i" (ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN)
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     : "g1");
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(void) cheetah_recheck_errors(NULL);
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_poke_faulted = 1;
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->tpc += 4;
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->tnpc = regs->tpc + 4;
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	p = cheetah_get_error_log(afsr);
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!p) {
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_printf("ERROR: Early deferred error afsr[%016lx] afar[%016lx]\n",
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    afsr, afar);
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_printf("ERROR: CPU(%d) TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n",
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    smp_processor_id(), regs->tpc, regs->tnpc, regs->tstate);
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_halt();
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Grab snapshot of logged error. */
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(&local_snapshot, p, sizeof(local_snapshot));
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If the current trap snapshot does not match what the
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * trap handler passed along into our args, big trouble.
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * In such a case, mark the local copy as invalid.
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Else, it matches and we mark the afsr in the non-local
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * copy as invalid so we may log new error traps there.
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (p->afsr != afsr || p->afar != afar)
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		local_snapshot.afsr = CHAFSR_INVALID;
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		p->afsr = CHAFSR_INVALID;
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	is_memory = cheetah_check_main_memory(afar);
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int flush_all, flush_line;
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		flush_all = flush_line = 0;
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((afsr & CHAFSR_EDU) != 0UL) {
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((afsr & cheetah_afsr_errors) == CHAFSR_EDU)
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flush_line = 1;
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flush_all = 1;
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if ((afsr & CHAFSR_BERR) != 0UL) {
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((afsr & cheetah_afsr_errors) == CHAFSR_BERR)
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flush_line = 1;
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				flush_all = 1;
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cheetah_flush_icache();
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cheetah_flush_dcache();
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Re-enable I/D caches */
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "or %%g1, %1, %%g1\n\t"
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "stxa %%g1, [%%g0] %0\n\t"
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "membar #Sync"
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     : /* no outputs */
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     : "i" (ASI_DCU_CONTROL_REG),
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     "i" (DCU_IC | DCU_DC)
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				     : "g1");
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (flush_all)
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cheetah_flush_ecache();
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else if (flush_line)
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cheetah_flush_ecache_line(afar);
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Re-enable error reporting */
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "or %%g1, %1, %%g1\n\t"
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "stxa %%g1, [%%g0] %0\n\t"
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "membar #Sync"
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : /* no outputs */
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "i" (ASI_ESTATE_ERROR_EN),
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "i" (ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN)
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "g1");
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Decide if we can continue after handling this trap and
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * logging the error.
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	recoverable = 1;
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (afsr & (CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP))
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		recoverable = 0;
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Re-check AFSR/AFAR.  What we are looking for here is whether a new
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * error was logged while we had error reporting traps disabled.
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cheetah_recheck_errors(&local_snapshot)) {
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long new_afsr = local_snapshot.afsr;
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* If we got a new asynchronous error, die... */
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (new_afsr & (CHAFSR_EMU | CHAFSR_EDU |
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				CHAFSR_WDU | CHAFSR_CPU |
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				CHAFSR_IVU | CHAFSR_UE |
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				CHAFSR_BERR | CHAFSR_TO))
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			recoverable = 0;
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Log errors. */
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cheetah_log_errors(regs, &local_snapshot, afsr, afar, recoverable);
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* "Recoverable" here means we try to yank the page from ever
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * being newly used again.  This depends upon a few things:
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * 1) Must be main memory, and AFAR must be valid.
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * 2) If we trapped from user, OK.
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * 3) Else, if we trapped from kernel we must find exception
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *    table entry (ie. we have to have been accessing user
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *    space).
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If AFAR is not in main memory, or we trapped from kernel
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * and cannot find an exception table entry, it is unacceptable
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * to try and continue.
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (recoverable && is_memory) {
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((regs->tstate & TSTATE_PRIV) == 0UL) {
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* OK, usermode access. */
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			recoverable = 1;
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
15948cf14af0a740fb7e9f94a203b5a989beb875d58fDavid S. Miller			const struct exception_table_entry *entry;
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15968cf14af0a740fb7e9f94a203b5a989beb875d58fDavid S. Miller			entry = search_exception_tables(regs->tpc);
15978cf14af0a740fb7e9f94a203b5a989beb875d58fDavid S. Miller			if (entry) {
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* OK, kernel access to userspace. */
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				recoverable = 1;
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* BAD, privileged state is corrupted. */
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				recoverable = 0;
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (recoverable) {
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (pfn_valid(afar >> PAGE_SHIFT))
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					get_page(pfn_to_page(afar >> PAGE_SHIFT));
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				else
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					recoverable = 0;
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Only perform fixup if we still have a
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 * recoverable condition.
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 */
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (recoverable) {
16168cf14af0a740fb7e9f94a203b5a989beb875d58fDavid S. Miller					regs->tpc = entry->fixup;
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					regs->tnpc = regs->tpc + 4;
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		recoverable = 0;
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!recoverable)
16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		panic("Irrecoverable deferred error trap.\n");
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Handle a D/I cache parity error trap.  TYPE is encoded as:
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bit0:	0=dcache,1=icache
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bit1:	0=recoverable,1=unrecoverable
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The hardware has disabled both the I-cache and D-cache in
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the %dcr register.
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid cheetah_plus_parity_error(int type, struct pt_regs *regs)
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (type & 0x1)
16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__cheetah_flush_icache();
16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cheetah_plus_zap_dcache_parity();
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cheetah_flush_dcache();
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Re-enable I-cache/D-cache */
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "or %%g1, %1, %%g1\n\t"
16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "stxa %%g1, [%%g0] %0\n\t"
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     "membar #Sync"
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : /* no outputs */
16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "i" (ASI_DCU_CONTROL_REG),
16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       "i" (DCU_DC | DCU_IC)
16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "g1");
16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (type & 0x2) {
16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_EMERG "CPU[%d]: Cheetah+ %c-cache parity error at TPC[%016lx]\n",
16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       smp_processor_id(),
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       (type & 0x1) ? 'I' : 'D',
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       regs->tpc);
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		panic("Irrecoverable Cheetah+ parity error.");
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_WARNING "CPU[%d]: Cheetah+ %c-cache parity error at TPC[%016lx]\n",
16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       smp_processor_id(),
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       (type & 0x1) ? 'I' : 'D',
16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       regs->tpc);
16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_fpe_common(struct pt_regs *regs)
16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (regs->tstate & TSTATE_PRIV) {
16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->tpc = regs->tnpc;
16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->tnpc += 4;
16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long fsr = current_thread_info()->xfsr[0];
16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		siginfo_t info;
16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (test_thread_flag(TIF_32BIT)) {
16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			regs->tpc &= 0xffffffff;
16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			regs->tnpc &= 0xffffffff;
16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		info.si_signo = SIGFPE;
16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		info.si_errno = 0;
16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		info.si_addr = (void __user *)regs->tpc;
16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		info.si_trapno = 0;
16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		info.si_code = __SI_FAULT;
16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((fsr & 0x1c000) == (1 << 14)) {
16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (fsr & 0x10)
16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				info.si_code = FPE_FLTINV;
16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (fsr & 0x08)
16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				info.si_code = FPE_FLTOVF;
16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (fsr & 0x04)
16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				info.si_code = FPE_FLTUND;
16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (fsr & 0x02)
16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				info.si_code = FPE_FLTDIV;
16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (fsr & 0x01)
16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				info.si_code = FPE_FLTRES;
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		force_sig_info(SIGFPE, &info, current);
17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_fpieee(struct pt_regs *regs)
17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (notify_die(DIE_TRAP, "fpu exception ieee", regs,
17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       0, 0x24, SIGFPE) == NOTIFY_STOP)
17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do_fpe_common(regs);
17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern int do_mathemu(struct pt_regs *, struct fpustate *);
17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_fpother(struct pt_regs *regs)
17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct fpustate *f = FPUSTATE;
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (notify_die(DIE_TRAP, "fpu exception other", regs,
17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       0, 0x25, SIGFPE) == NOTIFY_STOP)
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch ((current_thread_info()->xfsr[0] & 0x1c000)) {
17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case (2 << 14): /* unfinished_FPop */
17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case (3 << 14): /* unimplemented_FPop */
17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = do_mathemu(regs, f);
17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret)
17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do_fpe_common(regs);
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_tof(struct pt_regs *regs)
17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	siginfo_t info;
17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (notify_die(DIE_TRAP, "tagged arithmetic overflow", regs,
17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       0, 0x26, SIGEMT) == NOTIFY_STOP)
17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (regs->tstate & TSTATE_PRIV)
17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		die_if_kernel("Penguin overflow trap from kernel mode", regs);
17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_thread_flag(TIF_32BIT)) {
17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->tpc &= 0xffffffff;
17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->tnpc &= 0xffffffff;
17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_signo = SIGEMT;
17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_errno = 0;
17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_code = EMT_TAGOVF;
17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_addr = (void __user *)regs->tpc;
17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_trapno = 0;
17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	force_sig_info(SIGEMT, &info, current);
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_div0(struct pt_regs *regs)
17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	siginfo_t info;
17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (notify_die(DIE_TRAP, "integer division by zero", regs,
17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       0, 0x28, SIGFPE) == NOTIFY_STOP)
17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (regs->tstate & TSTATE_PRIV)
17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		die_if_kernel("TL0: Kernel divide by zero.", regs);
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_thread_flag(TIF_32BIT)) {
17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->tpc &= 0xffffffff;
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->tnpc &= 0xffffffff;
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_signo = SIGFPE;
17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_errno = 0;
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_code = FPE_INTDIV;
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_addr = (void __user *)regs->tpc;
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_trapno = 0;
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	force_sig_info(SIGFPE, &info, current);
17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid instruction_dump (unsigned int *pc)
17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((((unsigned long) pc) & 3))
17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("Instruction DUMP:");
17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = -3; i < 6; i++)
17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("%c%08x%c",i?' ':'<',pc[i],i?' ':'>');
17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("\n");
17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void user_instruction_dump (unsigned int __user *pc)
17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int buf[9];
17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((((unsigned long) pc) & 3))
17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (copy_from_user(buf, pc - 3, sizeof(buf)))
18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("Instruction DUMP:");
18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 9; i++)
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("%c%08x%c",i==3?' ':'<',buf[i],i==3?' ':'>');
18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("\n");
18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid show_stack(struct task_struct *tsk, unsigned long *_ksp)
18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long pc, fp, thread_base, ksp;
1811ee3eea165e706a3ce8a53693e810403f65239ebbAl Viro	void *tp = task_stack_page(tsk);
18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct reg_window *rw;
18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int count = 0;
18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ksp = (unsigned long) _ksp;
18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tp == current_thread_info())
18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		flushw_all();
18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fp = ksp + STACK_BIAS;
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	thread_base = (unsigned long) tp;
18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("Call Trace:");
18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_KALLSYMS
18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("\n");
18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Bogus frame pointer? */
18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (fp < (thread_base + sizeof(struct thread_info)) ||
18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    fp >= (thread_base + THREAD_SIZE))
18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rw = (struct reg_window *)fp;
18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pc = rw->ins[7];
18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(" [%016lx] ", pc);
18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		print_symbol("%s\n", pc);
18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fp = rw->ins[6] + STACK_BIAS;
18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (++count < 16);
18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_KALLSYMS
18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("\n");
18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid dump_stack(void)
18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long *ksp;
18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("mov	%%fp, %0"
18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			     : "=r" (ksp));
18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_stack(current, ksp);
18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(dump_stack);
18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int is_kernel_stack(struct task_struct *task,
18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  struct reg_window *rw)
18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long rw_addr = (unsigned long) rw;
18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long thread_base, thread_end;
18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rw_addr < PAGE_OFFSET) {
18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (task != &init_task)
18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1865ee3eea165e706a3ce8a53693e810403f65239ebbAl Viro	thread_base = (unsigned long) task_stack_page(task);
18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	thread_end = thread_base + sizeof(union thread_union);
18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rw_addr >= thread_base &&
18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    rw_addr < thread_end &&
18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    !(rw_addr & 0x7UL))
18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline struct reg_window *kernel_stack_up(struct reg_window *rw)
18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long fp = rw->ins[6];
18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!fp)
18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return NULL;
18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (struct reg_window *) (fp + STACK_BIAS);
18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid die_if_kernel(char *str, struct pt_regs *regs)
18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	static int die_counter;
18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	extern void __show_regs(struct pt_regs * regs);
18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	extern void smp_report_regs(void);
18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int count = 0;
18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Amuse the user. */
18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(
18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"              \\|/ ____ \\|/\n"
18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"              \"@'/ .. \\`@\"\n"
18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"              /_| \\__/ |_\\\n"
18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds"                 \\__U_/\n");
18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter);
19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV);
19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__asm__ __volatile__("flushw");
19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__show_regs(regs);
19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (regs->tstate & TSTATE_PRIV) {
19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct reg_window *rw = (struct reg_window *)
19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(regs->u_regs[UREG_FP] + STACK_BIAS);
19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Stop the back trace when we hit userland or we
19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * find some badly aligned kernel stack.
19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while (rw &&
19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       count++ < 30&&
19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       is_kernel_stack(current, rw)) {
19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("Caller[%016lx]", rw->ins[7]);
19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			print_symbol(": %s", rw->ins[7]);
19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("\n");
19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rw = kernel_stack_up(rw);
19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		instruction_dump ((unsigned int *) regs->tpc);
19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (test_thread_flag(TIF_32BIT)) {
19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			regs->tpc &= 0xffffffff;
19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			regs->tnpc &= 0xffffffff;
19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		user_instruction_dump ((unsigned int __user *) regs->tpc);
19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP
19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smp_report_regs();
19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (regs->tstate & TSTATE_PRIV)
19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do_exit(SIGKILL);
19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do_exit(SIGSEGV);
19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern int handle_popc(u32 insn, struct pt_regs *regs);
19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern int handle_ldf_stq(u32 insn, struct pt_regs *regs);
19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_illegal_instruction(struct pt_regs *regs)
19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long pc = regs->tpc;
19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long tstate = regs->tstate;
19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 insn;
19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	siginfo_t info;
19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (notify_die(DIE_TRAP, "illegal instruction", regs,
19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       0, 0x10, SIGILL) == NOTIFY_STOP)
19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (tstate & TSTATE_PRIV)
19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		die_if_kernel("Kernel illegal instruction", regs);
19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_thread_flag(TIF_32BIT))
19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pc = (u32)pc;
19541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (get_user(insn, (u32 __user *) pc) != -EFAULT) {
19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((insn & 0xc1ffc000) == 0x81700000) /* POPC */ {
19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (handle_popc(insn, regs))
19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return;
19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if ((insn & 0xc1580000) == 0xc1100000) /* LDQ/STQ */ {
19591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (handle_ldf_stq(insn, regs))
19601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return;
19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_signo = SIGILL;
19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_errno = 0;
19651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_code = ILL_ILLOPC;
19661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_addr = (void __user *)pc;
19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_trapno = 0;
19681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	force_sig_info(SIGILL, &info, current);
19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr)
19721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
19731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	siginfo_t info;
19741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (notify_die(DIE_TRAP, "memory address unaligned", regs,
19761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       0, 0x34, SIGSEGV) == NOTIFY_STOP)
19771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (regs->tstate & TSTATE_PRIV) {
19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		extern void kernel_unaligned_trap(struct pt_regs *regs,
19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  unsigned int insn,
19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  unsigned long sfar,
19831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  unsigned long sfsr);
19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc),
19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				      sfar, sfsr);
19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
19881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_signo = SIGBUS;
19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_errno = 0;
19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_code = BUS_ADRALN;
19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_addr = (void __user *)sfar;
19931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_trapno = 0;
19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	force_sig_info(SIGBUS, &info, current);
19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_privop(struct pt_regs *regs)
19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	siginfo_t info;
20001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (notify_die(DIE_TRAP, "privileged operation", regs,
20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       0, 0x11, SIGILL) == NOTIFY_STOP)
20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_thread_flag(TIF_32BIT)) {
20061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->tpc &= 0xffffffff;
20071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->tnpc &= 0xffffffff;
20081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
20091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_signo = SIGILL;
20101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_errno = 0;
20111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_code = ILL_PRVOPC;
20121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_addr = (void __user *)regs->tpc;
20131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_trapno = 0;
20141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	force_sig_info(SIGILL, &info, current);
20151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_privact(struct pt_regs *regs)
20181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do_privop(regs);
20201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Trap level 1 stuff or other traps we should never see... */
20231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_cee(struct pt_regs *regs)
20241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL0: Cache Error Exception", regs);
20261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_cee_tl1(struct pt_regs *regs)
20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
20311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL1: Cache Error Exception", regs);
20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_dae_tl1(struct pt_regs *regs)
20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
20371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL1: Data Access Exception", regs);
20381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_iae_tl1(struct pt_regs *regs)
20411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
20431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL1: Instruction Access Exception", regs);
20441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_div0_tl1(struct pt_regs *regs)
20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL1: DIV0 Exception", regs);
20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_fpdis_tl1(struct pt_regs *regs)
20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL1: FPU Disabled", regs);
20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_fpieee_tl1(struct pt_regs *regs)
20591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
20611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL1: FPU IEEE Exception", regs);
20621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_fpother_tl1(struct pt_regs *regs)
20651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
20671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL1: FPU Other Exception", regs);
20681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_ill_tl1(struct pt_regs *regs)
20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
20731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL1: Illegal Instruction Exception", regs);
20741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_irq_tl1(struct pt_regs *regs)
20771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL1: IRQ Exception", regs);
20801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_lddfmna_tl1(struct pt_regs *regs)
20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
20851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL1: LDDF Exception", regs);
20861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_stdfmna_tl1(struct pt_regs *regs)
20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL1: STDF Exception", regs);
20921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_paw(struct pt_regs *regs)
20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
20961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL0: Phys Watchpoint Exception", regs);
20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
20981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_paw_tl1(struct pt_regs *regs)
21001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
21021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL1: Phys Watchpoint Exception", regs);
21031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_vaw(struct pt_regs *regs)
21061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL0: Virt Watchpoint Exception", regs);
21081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_vaw_tl1(struct pt_regs *regs)
21111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
21131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL1: Virt Watchpoint Exception", regs);
21141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_tof_tl1(struct pt_regs *regs)
21171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
21191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	die_if_kernel("TL1: Tag Overflow Exception", regs);
21201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid do_getpsr(struct pt_regs *regs)
21231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->u_regs[UREG_I0] = tstate_to_psr(regs->tstate);
21251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->tpc   = regs->tnpc;
21261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->tnpc += 4;
21271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_thread_flag(TIF_32BIT)) {
21281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->tpc &= 0xffffffff;
21291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->tnpc &= 0xffffffff;
21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
213356fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Millerstruct trap_per_cpu trap_block[NR_CPUS];
213456fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Miller
213556fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Miller/* This can get invoked before sched_init() so play it super safe
213656fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Miller * and use hard_smp_processor_id().
213756fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Miller */
213856fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Millervoid init_cur_cpu_trap(void)
213956fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Miller{
214056fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Miller	int cpu = hard_smp_processor_id();
214156fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Miller	struct trap_per_cpu *p = &trap_block[cpu];
214256fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Miller
214356fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Miller	p->thread = current_thread_info();
214456fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Miller	p->pgd_paddr = 0;
214556fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Miller}
214656fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Miller
21471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void thread_info_offsets_are_bolixed_dave(void);
214856fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Millerextern void trap_per_cpu_offsets_are_bolixed_dave(void);
21491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Only invoked on boot processor. */
21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init trap_init(void)
21521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
21531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Compile time sanity check. */
21541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (TI_TASK != offsetof(struct thread_info, task) ||
21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_FLAGS != offsetof(struct thread_info, flags) ||
21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_CPU != offsetof(struct thread_info, cpu) ||
21571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_FPSAVED != offsetof(struct thread_info, fpsaved) ||
21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_KSP != offsetof(struct thread_info, ksp) ||
21591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_FAULT_ADDR != offsetof(struct thread_info, fault_address) ||
21601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_KREGS != offsetof(struct thread_info, kregs) ||
21611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_UTRAPS != offsetof(struct thread_info, utraps) ||
21621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_EXEC_DOMAIN != offsetof(struct thread_info, exec_domain) ||
21631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_REG_WINDOW != offsetof(struct thread_info, reg_window) ||
21641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_RWIN_SPTRS != offsetof(struct thread_info, rwbuf_stkptrs) ||
21651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_GSR != offsetof(struct thread_info, gsr) ||
21661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_XFSR != offsetof(struct thread_info, xfsr) ||
21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_USER_CNTD0 != offsetof(struct thread_info, user_cntd0) ||
21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_USER_CNTD1 != offsetof(struct thread_info, user_cntd1) ||
21691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_KERN_CNTD0 != offsetof(struct thread_info, kernel_cntd0) ||
21701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_KERN_CNTD1 != offsetof(struct thread_info, kernel_cntd1) ||
21711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_PCR != offsetof(struct thread_info, pcr_reg) ||
21721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_CEE_STUFF != offsetof(struct thread_info, cee_stuff) ||
21731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_PRE_COUNT != offsetof(struct thread_info, preempt_count) ||
2174db7d9a4eb700be766cc9f29241483dbb1e748832David S. Miller	    TI_NEW_CHILD != offsetof(struct thread_info, new_child) ||
2175db7d9a4eb700be766cc9f29241483dbb1e748832David S. Miller	    TI_SYS_NOERROR != offsetof(struct thread_info, syscall_noerror) ||
2176a3f9985843b674cbcb58f39fab8416675e7ab842David S. Miller	    TI_RESTART_BLOCK != offsetof(struct thread_info, restart_block) ||
2177a3f9985843b674cbcb58f39fab8416675e7ab842David S. Miller	    TI_KUNA_REGS != offsetof(struct thread_info, kern_una_regs) ||
2178a3f9985843b674cbcb58f39fab8416675e7ab842David S. Miller	    TI_KUNA_INSN != offsetof(struct thread_info, kern_una_insn) ||
21791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    TI_FPREGS != offsetof(struct thread_info, fpregs) ||
21801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (TI_FPREGS & (64 - 1)))
21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		thread_info_offsets_are_bolixed_dave();
21821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
218356fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Miller	if (TRAP_PER_CPU_THREAD != offsetof(struct trap_per_cpu, thread) ||
218456fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Miller	    TRAP_PER_CPU_PGD_PADDR != offsetof(struct trap_per_cpu, pgd_paddr))
218556fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Miller		trap_per_cpu_offsets_are_bolixed_dave();
218656fb4df6da76c35dca22036174e2d1edef83ff1fDavid S. Miller
21871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Attach to the address space of init_task.  On SMP we
21881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * do this in smp.c:smp_callin for other cpus.
21891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
21901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	atomic_inc(&init_mm.mm_count);
21911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	current->active_mm = &init_mm;
21921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2193