11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  linux/arch/parisc/traps.c
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 1991, 1992  Linus Torvalds
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 1999, 2000  Philipp Rumpf <prumpf@tux.org>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 'Traps.c' handles hardware traps and faults after we have saved some
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * state in 'asm.s'.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ptrace.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h>
1922fced881122f7fc6f5f259dca03ac6d5c601404Helge Deller#include <linux/delay.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/smp.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/console.h>
276891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller#include <linux/bug.h>
28fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller#include <linux/ratelimit.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/assembly.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/traps.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/unaligned.h>
3660063497a95e716c9a689af3be2687d261f115b4Arun Sharma#include <linux/atomic.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/smp.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pdc.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pdc_chassis.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/unwind.h>
41d6ce8626dbc7d277d29b62e31c24ce777c60546bRandolph Chung#include <asm/tlbflush.h>
42d6ce8626dbc7d277d29b62e31c24ce777c60546bRandolph Chung#include <asm/cacheflush.h>
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "../math-emu/math-emu.h"	/* for handle_fpe() */
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsDEFINE_SPINLOCK(pa_dbit_lock);
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
507a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Dellerstatic void parisc_show_stack(struct task_struct *task, unsigned long *sp,
51dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartin	struct pt_regs *regs);
52dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartin
536891f8a1135b964f8ef30521d1473d5d137af0faHelge Dellerstatic int printbinary(char *buf, unsigned long x, int nbits)
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long mask = 1UL << (nbits - 1);
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (mask != 0) {
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*buf++ = (mask & x ? '1' : '0');
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mask >>= 1;
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*buf = '\0';
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return nbits;
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
65a8f44e3889b686813926b288bd4e51a0cf17d2c7Helge Deller#ifdef CONFIG_64BIT
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RFMT "%016lx"
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RFMT "%08lx"
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
701c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin#define FFMT "%016llx"	/* fpregs are 64-bit always */
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
721c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin#define PRINTREGS(lvl,r,f,fmt,x)	\
731c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin	printk("%s%s%02d-%02d  " fmt " " fmt " " fmt " " fmt "\n",	\
741c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin		lvl, f, (x), (x+3), (r)[(x)+0], (r)[(x)+1],		\
751c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin		(r)[(x)+2], (r)[(x)+3])
761c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin
771c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartinstatic void print_gr(char *level, struct pt_regs *regs)
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
801c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin	char buf[64];
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
821c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin	printk("%s\n", level);
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s     YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n", level);
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printbinary(buf, regs->gr[0], 32);
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%sPSW: %s %s\n", level, buf, print_tainted());
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin	for (i = 0; i < 32; i += 4)
881c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin		PRINTREGS(level, regs->gr, "r", RFMT, i);
891c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin}
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
911c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartinstatic void print_fr(char *level, struct pt_regs *regs)
921c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin{
931c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin	int i;
941c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin	char buf[64];
951c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin	struct { u32 sw[2]; } s;
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
97eba917273eb8579dd8ae36f6645518ca5579a2abThibaut Varene	/* FR are 64bit everywhere. Need to use asm to get the content
98eba917273eb8579dd8ae36f6645518ca5579a2abThibaut Varene	 * of fpsr/fper1, and we assume that we won't have a FP Identify
99eba917273eb8579dd8ae36f6645518ca5579a2abThibaut Varene	 * in our way, otherwise we're screwed.
100eba917273eb8579dd8ae36f6645518ca5579a2abThibaut Varene	 * The fldd is used to restore the T-bit if there was one, as the
101eba917273eb8579dd8ae36f6645518ca5579a2abThibaut Varene	 * store clears it anyway.
1021c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin	 * PA2.0 book says "thou shall not use fstw on FPSR/FPERs" - T-Bone */
1031c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin	asm volatile ("fstd %%fr0,0(%1)	\n\t"
1041c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin		      "fldd 0(%1),%%fr0	\n\t"
1051c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin		      : "=m" (s) : "r" (&s) : "r0");
106eba917273eb8579dd8ae36f6645518ca5579a2abThibaut Varene
107eba917273eb8579dd8ae36f6645518ca5579a2abThibaut Varene	printk("%s\n", level);
108eba917273eb8579dd8ae36f6645518ca5579a2abThibaut Varene	printk("%s      VZOUICununcqcqcqcqcqcrmunTDVZOUI\n", level);
109eba917273eb8579dd8ae36f6645518ca5579a2abThibaut Varene	printbinary(buf, s.sw[0], 32);
110eba917273eb8579dd8ae36f6645518ca5579a2abThibaut Varene	printk("%sFPSR: %s\n", level, buf);
111eba917273eb8579dd8ae36f6645518ca5579a2abThibaut Varene	printk("%sFPER1: %08x\n", level, s.sw[1]);
112eba917273eb8579dd8ae36f6645518ca5579a2abThibaut Varene
113eba917273eb8579dd8ae36f6645518ca5579a2abThibaut Varene	/* here we'll print fr0 again, tho it'll be meaningless */
1141c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin	for (i = 0; i < 32; i += 4)
1151c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin		PRINTREGS(level, regs->fr, "fr", FFMT, i);
1161c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin}
1171c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin
1181c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartinvoid show_regs(struct pt_regs *regs)
1191c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin{
1207a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller	int i, user;
1211c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin	char *level;
1221c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin	unsigned long cr30, cr31;
1231c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin
1247a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller	user = user_mode(regs);
1257a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller	level = user ? KERN_DEBUG : KERN_CRIT;
1261c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin
127a43cb95d547a061ed5bf1acb28e0f5fd575e26c1Tejun Heo	show_regs_print_info(level);
128a43cb95d547a061ed5bf1acb28e0f5fd575e26c1Tejun Heo
1291c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin	print_gr(level, regs);
1301c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin
1311c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin	for (i = 0; i < 8; i += 4)
1321c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin		PRINTREGS(level, regs->sr, "sr", RFMT, i);
1331c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin
1347a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller	if (user)
1351c63b4b8474700f3fb5e3442a78897766f153437Kyle McMartin		print_fr(level, regs);
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cr30 = mfctl(30);
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cr31 = mfctl(31);
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s\n", level);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%sIASQ: " RFMT " " RFMT " IAOQ: " RFMT " " RFMT "\n",
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       level, regs->iasq[0], regs->iasq[1], regs->iaoq[0], regs->iaoq[1]);
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s IIR: %08lx    ISR: " RFMT "  IOR: " RFMT "\n",
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       level, regs->iir, regs->isr, regs->ior);
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s CPU: %8d   CR30: " RFMT " CR31: " RFMT "\n",
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       level, current_thread_info()->cpu, cr30, cr31);
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("%s ORIG_R28: " RFMT "\n", level, regs->orig_r28);
1477a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller
1487a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller	if (user) {
1497a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller		printk("%s IAOQ[0]: " RFMT "\n", level, regs->iaoq[0]);
1507a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller		printk("%s IAOQ[1]: " RFMT "\n", level, regs->iaoq[1]);
1517a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller		printk("%s RP(r2): " RFMT "\n", level, regs->gr[2]);
1527a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller	} else {
1537a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller		printk("%s IAOQ[0]: %pS\n", level, (void *) regs->iaoq[0]);
1547a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller		printk("%s IAOQ[1]: %pS\n", level, (void *) regs->iaoq[1]);
1557a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller		printk("%s RP(r2): %pS\n", level, (void *) regs->gr[2]);
1567a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller
1577a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller		parisc_show_stack(current, NULL, regs);
1587a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller	}
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
161fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Dellerstatic DEFINE_RATELIMIT_STATE(_hppa_rs,
162fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller	DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST);
163fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller
164fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller#define parisc_printk_ratelimited(critical, regs, fmt, ...)	{	      \
165fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller	if ((critical || show_unhandled_signals) && __ratelimit(&_hppa_rs)) { \
166fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller		printk(fmt, ##__VA_ARGS__);				      \
167fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller		show_regs(regs);					      \
168fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller	}								      \
169fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller}
170fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller
171fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void do_show_stack(struct unwind_frame_info *info)
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 1;
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
176bd83bcffb2a582ddac0b463153a4c1fda4335273Helge Deller	printk(KERN_CRIT "Backtrace:\n");
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (i <= 16) {
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (unwind_once(info) < 0 || info->ip == 0)
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (__kernel_text_address(info->ip)) {
1827a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller			printk(KERN_CRIT " [<" RFMT ">] %pS\n",
1837a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller				info->ip, (void *) info->ip);
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			i++;
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1877a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Deller	printk(KERN_CRIT "\n");
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1907a3f5134a8f5bd7fa38b5645eef05e8a4eb62951Helge Dellerstatic void parisc_show_stack(struct task_struct *task, unsigned long *sp,
191dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartin	struct pt_regs *regs)
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct unwind_frame_info info;
194dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartin	struct task_struct *t;
195dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartin
196dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartin	t = task ? task : current;
197dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartin	if (regs) {
198dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartin		unwind_frame_init(&info, t, regs);
199dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartin		goto show_stack;
200dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartin	}
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
202dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartin	if (t == current) {
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long sp;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsHERE:
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		asm volatile ("copy %%r30, %0" : "=r"(sp));
2079f15c82686251cd2b97ac6859de62959d3c4afe1Matthew Wilcox		{
2089f15c82686251cd2b97ac6859de62959d3c4afe1Matthew Wilcox			struct pt_regs r;
2099f15c82686251cd2b97ac6859de62959d3c4afe1Matthew Wilcox
2109f15c82686251cd2b97ac6859de62959d3c4afe1Matthew Wilcox			memset(&r, 0, sizeof(struct pt_regs));
2119f15c82686251cd2b97ac6859de62959d3c4afe1Matthew Wilcox			r.iaoq[0] = (unsigned long)&&HERE;
2129f15c82686251cd2b97ac6859de62959d3c4afe1Matthew Wilcox			r.gr[2] = (unsigned long)__builtin_return_address(0);
2139f15c82686251cd2b97ac6859de62959d3c4afe1Matthew Wilcox			r.gr[30] = sp;
2149f15c82686251cd2b97ac6859de62959d3c4afe1Matthew Wilcox
2159f15c82686251cd2b97ac6859de62959d3c4afe1Matthew Wilcox			unwind_frame_init(&info, current, &r);
2169f15c82686251cd2b97ac6859de62959d3c4afe1Matthew Wilcox		}
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
218dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartin		unwind_frame_init_from_blocked_task(&info, t);
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
221dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartinshow_stack:
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do_show_stack(&info);
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
225dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartinvoid show_stack(struct task_struct *t, unsigned long *sp)
226dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartin{
227dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartin	return parisc_show_stack(t, sp, NULL);
228dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartin}
229dc39455e7948ec9bc5f3f2dced5c2f5ac8a8dfd9Kyle McMartin
2306891f8a1135b964f8ef30521d1473d5d137af0faHelge Dellerint is_valid_bugaddr(unsigned long iaoq)
2316891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller{
2326891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller	return 1;
2336891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller}
2346891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid die_if_kernel(char *str, struct pt_regs *regs, long err)
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (user_mode(regs)) {
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (err == 0)
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return; /* STFU */
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller		parisc_printk_ratelimited(1, regs,
242fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller			KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "\n",
24319c5870c0eefd27c6d09d867465e0571262e05d0Alexey Dobriyan			current->comm, task_pid_nr(current), str, err, regs->iaoq[0]);
244fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	oops_in_progress = 1;
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
250c48faf86b0d59cc43ff4eede59c4af7afbd7c0ffHelge Deller	oops_enter();
251c48faf86b0d59cc43ff4eede59c4af7afbd7c0ffHelge Deller
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Amuse the user in a SPARC fashion */
253ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches	if (err) printk(KERN_CRIT
254ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches			"      _______________________________ \n"
255ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches			"     < Your System ate a SPARC! Gah! >\n"
256ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches			"      ------------------------------- \n"
257ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches			"             \\   ^__^\n"
258ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches			"                 (__)\\       )\\/\\\n"
259ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches			"                  U  ||----w |\n"
260ad361c9884e809340f6daca80d56a9e9c871690aJoe Perches			"                     ||     ||\n");
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* unlock the pdc lock if necessary */
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pdc_emergency_unlock();
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* maybe the kernel hasn't booted very far yet and hasn't been able
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * to initialize the serial or STI console. In that case we should
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * re-enable the pdc console, so that the user will be able to
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * identify the problem. */
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!console_drivers)
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pdc_console_restart();
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2726891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller	if (err)
2736891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller		printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n",
27419c5870c0eefd27c6d09d867465e0571262e05d0Alexey Dobriyan			current->comm, task_pid_nr(current), str, err);
275bd83bcffb2a582ddac0b463153a4c1fda4335273Helge Deller
2760bbdac0897a48f415eb788bf3263c92bd5e97ffbHelge Deller	/* Wot's wrong wif bein' racy? */
2770bbdac0897a48f415eb788bf3263c92bd5e97ffbHelge Deller	if (current->thread.flags & PARISC_KERNEL_DEATH) {
27891bae23ce185b74c9b6dda86b92bb204a1c951c3Harvey Harrison		printk(KERN_CRIT "%s() recursion detected.\n", __func__);
2790bbdac0897a48f415eb788bf3263c92bd5e97ffbHelge Deller		local_irq_enable();
2800bbdac0897a48f415eb788bf3263c92bd5e97ffbHelge Deller		while (1);
2810bbdac0897a48f415eb788bf3263c92bd5e97ffbHelge Deller	}
2820bbdac0897a48f415eb788bf3263c92bd5e97ffbHelge Deller	current->thread.flags |= PARISC_KERNEL_DEATH;
2830bbdac0897a48f415eb788bf3263c92bd5e97ffbHelge Deller
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_regs(regs);
2850bbdac0897a48f415eb788bf3263c92bd5e97ffbHelge Deller	dump_stack();
286373d4d099761cb1f637bed488ab3871945882273Rusty Russell	add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28822fced881122f7fc6f5f259dca03ac6d5c601404Helge Deller	if (in_interrupt())
28922fced881122f7fc6f5f259dca03ac6d5c601404Helge Deller		panic("Fatal exception in interrupt");
29022fced881122f7fc6f5f259dca03ac6d5c601404Helge Deller
29122fced881122f7fc6f5f259dca03ac6d5c601404Helge Deller	if (panic_on_oops) {
29222fced881122f7fc6f5f259dca03ac6d5c601404Helge Deller		printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
29322fced881122f7fc6f5f259dca03ac6d5c601404Helge Deller		ssleep(5);
29422fced881122f7fc6f5f259dca03ac6d5c601404Helge Deller		panic("Fatal exception");
29522fced881122f7fc6f5f259dca03ac6d5c601404Helge Deller	}
29622fced881122f7fc6f5f259dca03ac6d5c601404Helge Deller
297c48faf86b0d59cc43ff4eede59c4af7afbd7c0ffHelge Deller	oops_exit();
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do_exit(SIGSEGV);
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* gdb uses break 4,8 */
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GDB_BREAK_INSN 0x10004
3036891f8a1135b964f8ef30521d1473d5d137af0faHelge Dellerstatic void handle_gdb_break(struct pt_regs *regs, int wot)
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct siginfo si;
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	si.si_signo = SIGTRAP;
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	si.si_errno = 0;
3096891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller	si.si_code = wot;
3106891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller	si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	force_sig_info(SIGTRAP, &si, current);
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3146891f8a1135b964f8ef30521d1473d5d137af0faHelge Dellerstatic void handle_break(struct pt_regs *regs)
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3166891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller	unsigned iir = regs->iir;
3176891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller
3186891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller	if (unlikely(iir == PARISC_BUG_BREAK_INSN && !user_mode(regs))) {
3196891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller		/* check if a BUG() or WARN() trapped here.  */
3206891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller		enum bug_trap_type tt;
321608e2619682e951f525b08e7a48669a3c0263b41Heiko Carstens		tt = report_bug(regs->iaoq[0] & ~3, regs);
3226891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller		if (tt == BUG_TRAP_TYPE_WARN) {
3236891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller			regs->iaoq[0] += 4;
3246891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller			regs->iaoq[1] += 4;
3256891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller			return; /* return to next instruction when WARN_ON().  */
3266891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller		}
3276891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller		die_if_kernel("Unknown kernel breakpoint", regs,
3286891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller			(tt == BUG_TRAP_TYPE_NONE) ? 9 : 0);
3296891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller	}
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller	if (unlikely(iir != GDB_BREAK_INSN))
332fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller		parisc_printk_ratelimited(0, regs,
333fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller			KERN_DEBUG "break %d,%d: pid=%d command='%s'\n",
334df47b4386a473eba87095e6dea8046762434817dHelge Deller			iir & 31, (iir>>13) & ((1<<13)-1),
33519c5870c0eefd27c6d09d867465e0571262e05d0Alexey Dobriyan			task_pid_nr(current), current->comm);
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3376891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller	/* send standard GDB signal */
3386891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller	handle_gdb_break(regs, TRAP_BRKPT);
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void default_trap(int code, struct pt_regs *regs)
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_ERR "Trap %d on CPU %d\n", code, smp_processor_id());
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_regs(regs);
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3476891f8a1135b964f8ef30521d1473d5d137af0faHelge Dellervoid (*cpu_lpmc) (int code, struct pt_regs *regs) __read_mostly = default_trap;
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid transfer_pim_to_trap_frame(struct pt_regs *regs)
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    register int i;
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    extern unsigned int hpmc_pim_data[];
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    struct pdc_hpmc_pim_11 *pim_narrow;
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    struct pdc_hpmc_pim_20 *pim_wide;
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (boot_cpu_data.cpu_type >= pcxu) {
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pim_wide = (struct pdc_hpmc_pim_20 *)hpmc_pim_data;
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Note: The following code will probably generate a
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * bunch of truncation error warnings from the compiler.
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Could be handled with an ifdef, but perhaps there
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * is a better way.
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->gr[0] = pim_wide->cr[22];
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 1; i < 32; i++)
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    regs->gr[i] = pim_wide->gr[i];
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 32; i++)
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    regs->fr[i] = pim_wide->fr[i];
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 8; i++)
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    regs->sr[i] = pim_wide->sr[i];
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->iasq[0] = pim_wide->cr[17];
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->iasq[1] = pim_wide->iasq_back;
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->iaoq[0] = pim_wide->cr[18];
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->iaoq[1] = pim_wide->iaoq_back;
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->sar  = pim_wide->cr[11];
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->iir  = pim_wide->cr[19];
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->isr  = pim_wide->cr[20];
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->ior  = pim_wide->cr[21];
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    else {
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pim_narrow = (struct pdc_hpmc_pim_11 *)hpmc_pim_data;
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->gr[0] = pim_narrow->cr[22];
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 1; i < 32; i++)
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    regs->gr[i] = pim_narrow->gr[i];
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 32; i++)
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    regs->fr[i] = pim_narrow->fr[i];
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 8; i++)
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    regs->sr[i] = pim_narrow->sr[i];
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->iasq[0] = pim_narrow->cr[17];
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->iasq[1] = pim_narrow->iasq_back;
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->iaoq[0] = pim_narrow->cr[18];
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->iaoq[1] = pim_narrow->iaoq_back;
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->sar  = pim_narrow->cr[11];
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->iir  = pim_narrow->cr[19];
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->isr  = pim_narrow->cr[20];
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->ior  = pim_narrow->cr[21];
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /*
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * The following fields only have meaning if we came through
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * another path. So just zero them here.
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     */
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    regs->ksp = 0;
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    regs->kpc = 0;
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    regs->orig_r28 = 0;
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine is called as a last resort when everything else
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * has gone clearly wrong. We get called for faults in kernel space,
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and HPMC's.
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset)
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	static DEFINE_SPINLOCK(terminate_lock);
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	oops_in_progress = 1;
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	set_eiem(0);
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	local_irq_disable();
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&terminate_lock);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* unlock the pdc lock if necessary */
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pdc_emergency_unlock();
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* restart pdc console if necessary */
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!console_drivers)
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pdc_console_restart();
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Not all paths will gutter the processor... */
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(code){
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1:
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		transfer_pim_to_trap_frame(regs);
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Fall through */
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* show_stack(NULL, (unsigned long *)regs->gr[30]); */
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct unwind_frame_info info;
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unwind_frame_init(&info, current, regs);
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do_show_stack(&info);
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("\n");
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_CRIT "%s: Code=%d regs=%p (Addr=" RFMT ")\n",
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			msg, code, regs, offset);
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_regs(regs);
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&terminate_lock);
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* put soft power button back under hardware control;
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * if the user had pressed it once at any time, the
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * system will shut down immediately right here. */
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pdc_soft_power_button(0);
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Call kernel panic() so reboot timeouts work properly
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * FIXME: This function should be on the list of
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * panic notifiers, and we should call panic
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * directly from the location that we wish.
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * e.g. We should not call panic from
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * parisc_terminate, but rather the oter way around.
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * This hack works, prints the panic message twice,
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * and it enables reboot timers!
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	panic(msg);
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
491d75f054a2cf0614ff63d534ff21ca8eaab41e713Helge Dellervoid notrace handle_interruption(int code, struct pt_regs *regs)
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long fault_address = 0;
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long fault_space = 0;
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct siginfo si;
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (code == 1)
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    pdc_console_restart();  /* switch back to pdc if HPMC */
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    local_irq_enable();
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Security check:
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If the priority level is still user, and the
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * faulting space is not equal to the active space
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * then the user is attempting something in a space
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * that does not belong to them. Kill the process.
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * This is normally the situation when the user
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * attempts to jump into the kernel space at the
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * wrong offset, be it at the gateway page or a
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * random location.
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We cannot normally signal the process because it
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * could *be* on the gateway page, and processes
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * executing on the gateway page can't have signals
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * delivered.
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We merely readjust the address into the users
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * space, at a destination address of zero, and
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * allow processing to continue.
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (((unsigned long)regs->iaoq[0] & 3) &&
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    ((unsigned long)regs->iasq[0] != (unsigned long)regs->sr[7])) {
524a39e6beaa1455407af7b0bb6f501e9135987334bRolf Eike Beer		/* Kill the user process later */
525a39e6beaa1455407af7b0bb6f501e9135987334bRolf Eike Beer		regs->iaoq[0] = 0 | 3;
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->iaoq[1] = regs->iaoq[0] + 4;
527a39e6beaa1455407af7b0bb6f501e9135987334bRolf Eike Beer		regs->iasq[0] = regs->iasq[1] = regs->sr[7];
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->gr[0] &= ~PSW_B;
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_CRIT "Interruption # %d\n", code);
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(code) {
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case  1:
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* High-priority machine check (HPMC) */
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* set up a new led state on systems shipped with a LED State panel */
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pdc_chassis_send_status(PDC_CHASSIS_DIRECT_HPMC);
543a39e6beaa1455407af7b0bb6f501e9135987334bRolf Eike Beer
544a39e6beaa1455407af7b0bb6f501e9135987334bRolf Eike Beer		parisc_terminate("High Priority Machine Check (HPMC)",
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				regs, code, 0);
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* NOT REACHED */
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case  2:
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Power failure interrupt */
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_CRIT "Power failure interrupt !\n");
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case  3:
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Recovery counter trap */
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->gr[0] &= ~PSW_R;
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (user_space(regs))
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			handle_gdb_break(regs, TRAP_TRACE);
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* else this must be the start of a syscall - just let it run */
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case  5:
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Low-priority machine check */
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pdc_chassis_send_status(PDC_CHASSIS_DIRECT_LPMC);
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
565d6ce8626dbc7d277d29b62e31c24ce777c60546bRandolph Chung		flush_cache_all();
566d6ce8626dbc7d277d29b62e31c24ce777c60546bRandolph Chung		flush_tlb_all();
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpu_lpmc(5, regs);
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case  6:
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Instruction TLB miss fault/Instruction page fault */
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fault_address = regs->iaoq[0];
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fault_space   = regs->iasq[0];
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case  8:
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Illegal instruction trap */
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		die_if_kernel("Illegal instruction", regs, code);
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		si.si_code = ILL_ILLOPC;
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto give_sigill;
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case  9:
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Break instruction trap */
5846891f8a1135b964f8ef30521d1473d5d137af0faHelge Deller		handle_break(regs);
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
586a39e6beaa1455407af7b0bb6f501e9135987334bRolf Eike Beer
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 10:
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Privileged operation trap */
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		die_if_kernel("Privileged operation", regs, code);
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		si.si_code = ILL_PRVOPC;
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto give_sigill;
592a39e6beaa1455407af7b0bb6f501e9135987334bRolf Eike Beer
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 11:
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Privileged register trap */
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((regs->iir & 0xffdfffe0) == 0x034008a0) {
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* This is a MFCTL cr26/cr27 to gr instruction.
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * PCXS traps on this, so we need to emulate it.
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (regs->iir & 0x00200000)
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				regs->gr[regs->iir & 0x1f] = mfctl(27);
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				regs->gr[regs->iir & 0x1f] = mfctl(26);
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			regs->iaoq[0] = regs->iaoq[1];
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			regs->iaoq[1] += 4;
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			regs->iasq[0] = regs->iasq[1];
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		die_if_kernel("Privileged register usage", regs, code);
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		si.si_code = ILL_PRVREG;
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	give_sigill:
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		si.si_signo = SIGILL;
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		si.si_errno = 0;
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		si.si_addr = (void __user *) regs->iaoq[0];
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		force_sig_info(SIGILL, &si, current);
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 12:
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Overflow Trap, let the userland signal handler do the cleanup */
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		si.si_signo = SIGFPE;
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		si.si_code = FPE_INTOVF;
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		si.si_addr = (void __user *) regs->iaoq[0];
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		force_sig_info(SIGFPE, &si, current);
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 13:
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Conditional Trap
6317022672e4046fac4699aa5f8ff2a5213b7ec4ff9Simon Arlott		   The condition succeeds in an instruction which traps
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   on condition  */
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(user_mode(regs)){
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			si.si_signo = SIGFPE;
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Set to zero, and let the userspace app figure it out from
636a39e6beaa1455407af7b0bb6f501e9135987334bRolf Eike Beer			   the insn pointed to by si_addr */
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			si.si_code = 0;
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			si.si_addr = (void __user *) regs->iaoq[0];
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			force_sig_info(SIGFPE, &si, current);
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* The kernel doesn't want to handle condition codes */
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 14:
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Assist Exception Trap, i.e. floating point exception. */
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		die_if_kernel("Floating point exception", regs, 0); /* quiet */
648d0c3be806a3fe7f4abdb0f7e7287addb55e73f35Helge Deller		__inc_irq_stat(irq_fpassist_count);
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		handle_fpe(regs);
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
651a39e6beaa1455407af7b0bb6f501e9135987334bRolf Eike Beer
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 15:
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Data TLB miss fault/Data page fault */
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Fall through */
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 16:
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Non-access instruction TLB miss fault */
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* The instruction TLB entry needed for the target address of the FIC
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   is absent, and hardware can't find it, so we get to cleanup */
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Fall through */
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 17:
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Non-access data TLB miss fault/Non-access data page fault */
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* FIXME:
663a39e6beaa1455407af7b0bb6f501e9135987334bRolf Eike Beer			 Still need to add slow path emulation code here!
664a39e6beaa1455407af7b0bb6f501e9135987334bRolf Eike Beer			 If the insn used a non-shadow register, then the tlb
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 handlers could not have their side-effect (e.g. probe
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 writing to a target register) emulated since rfir would
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 erase the changes to said register. Instead we have to
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 setup everything, call this function we are in, and emulate
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 by hand. Technically we need to emulate:
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 fdc,fdce,pdc,"fic,4f",prober,probeir,probew, probeiw
671a39e6beaa1455407af7b0bb6f501e9135987334bRolf Eike Beer		*/
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fault_address = regs->ior;
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fault_space = regs->isr;
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 18:
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* PCXS only -- later cpu's split this into types 26,27 & 28 */
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Check for unaligned access */
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (check_unaligned(regs)) {
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			handle_unaligned(regs);
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Fall Through */
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 26:
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* PCXL: Data memory access rights trap */
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fault_address = regs->ior;
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fault_space   = regs->isr;
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 19:
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Data memory break trap */
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->gr[0] |= PSW_X; /* So we can single-step over the trap */
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* fall thru */
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 21:
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Page reference trap */
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		handle_gdb_break(regs, TRAP_HWBKPT);
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 25:
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Taken branch trap */
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->gr[0] &= ~PSW_T;
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (user_space(regs))
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			handle_gdb_break(regs, TRAP_BRANCH);
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* else this must be the start of a syscall - just let it
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * run.
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case  7:
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Instruction access rights */
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* PCXL: Instruction memory protection trap */
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * This could be caused by either: 1) a process attempting
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * to execute within a vma that does not have execute
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * permission, or 2) an access rights violation caused by a
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * flush only translation set up by ptep_get_and_clear().
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * So we check the vma permissions to differentiate the two.
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * If the vma indicates we have execute permission, then
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * the cause is the latter one. In this case, we need to
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * call do_page_fault() to fix the problem.
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (user_mode(regs)) {
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct vm_area_struct *vma;
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			down_read(&current->mm->mmap_sem);
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			vma = find_vma(current->mm,regs->iaoq[0]);
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (vma && (regs->iaoq[0] >= vma->vm_start)
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				&& (vma->vm_flags & VM_EXEC)) {
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				fault_address = regs->iaoq[0];
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				fault_space = regs->iasq[0];
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				up_read(&current->mm->mmap_sem);
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break; /* call do_page_fault() */
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			up_read(&current->mm->mmap_sem);
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Fall Through */
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 27:
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Data memory protection ID trap */
743c61c25eb02757ecf697015ef4ae3675c5e114e2eKyle McMartin		if (code == 27 && !user_mode(regs) &&
744c61c25eb02757ecf697015ef4ae3675c5e114e2eKyle McMartin			fixup_exception(regs))
745c61c25eb02757ecf697015ef4ae3675c5e114e2eKyle McMartin			return;
746c61c25eb02757ecf697015ef4ae3675c5e114e2eKyle McMartin
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		die_if_kernel("Protection id trap", regs, code);
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		si.si_code = SEGV_MAPERR;
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		si.si_signo = SIGSEGV;
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		si.si_errno = 0;
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (code == 7)
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    si.si_addr = (void __user *) regs->iaoq[0];
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    si.si_addr = (void __user *) regs->ior;
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		force_sig_info(SIGSEGV, &si, current);
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 28:
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Unaligned data reference trap */
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		handle_unaligned(regs);
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (user_mode(regs)) {
765fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller			parisc_printk_ratelimited(0, regs, KERN_DEBUG
766fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller				"handle_interruption() pid=%d command='%s'\n",
767fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller				task_pid_nr(current), current->comm);
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* SIGBUS, for lack of a better one. */
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			si.si_signo = SIGBUS;
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			si.si_code = BUS_OBJERR;
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			si.si_errno = 0;
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			si.si_addr = (void __user *) regs->ior;
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			force_sig_info(SIGBUS, &si, current);
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		parisc_terminate("Unexpected interruption", regs, code, 0);
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* NOT REACHED */
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (user_mode(regs)) {
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    if ((fault_space >> SPACEID_SHIFT) != (regs->sr[7] >> SPACEID_SHIFT)) {
784fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller		parisc_printk_ratelimited(0, regs, KERN_DEBUG
785fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller				"User fault %d on space 0x%08lx, pid=%d command='%s'\n",
786fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller				code, fault_space,
787fef47e2a2e1e75fe50a10f634a80f16808348cc6Helge Deller				task_pid_nr(current), current->comm);
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		si.si_signo = SIGSEGV;
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		si.si_errno = 0;
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		si.si_code = SEGV_MAPERR;
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		si.si_addr = (void __user *) regs->ior;
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		force_sig_info(SIGSEGV, &si, current);
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    }
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    /*
79959b33f148cc08fb33cbe823fca1e34f7f023765eHelge Deller	     * The kernel should never fault on its own address space,
80059b33f148cc08fb33cbe823fca1e34f7f023765eHelge Deller	     * unless pagefault_disable() was called before.
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     */
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
80359b33f148cc08fb33cbe823fca1e34f7f023765eHelge Deller	    if (fault_space == 0 && !in_atomic())
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    {
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		parisc_terminate("Kernel Fault", regs, code, fault_address);
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    }
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do_page_fault(regs, code, fault_address);
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init check_ivt(void *iva)
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
816ae16489eb1175066c8f3008fc3c0396c525e1906Kyle McMartin	extern u32 os_hpmc_size;
817c3d4ed4e3e5aa8d9e6b4b795f004a7028ce780e9Kyle McMartin	extern const u32 os_hpmc[];
818c3d4ed4e3e5aa8d9e6b4b795f004a7028ce780e9Kyle McMartin
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 check = 0;
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 *ivap;
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 *hpmcp;
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 length;
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (strcmp((char *)iva, "cows can fly"))
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ivap = (u32 *)iva;
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 8; i++)
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    *ivap++ = 0;
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Compute Checksum for HPMC handler */
834ae16489eb1175066c8f3008fc3c0396c525e1906Kyle McMartin	length = os_hpmc_size;
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ivap[7] = length;
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hpmcp = (u32 *)os_hpmc;
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i=0; i<length/4; i++)
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    check += *hpmcp++;
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i=0; i<8; i++)
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    check += ivap[i];
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ivap[5] = -check;
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
850a8f44e3889b686813926b288bd4e51a0cf17d2c7Helge Deller#ifndef CONFIG_64BIT
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern const void fault_vector_11;
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern const void fault_vector_20;
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init trap_init(void)
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *iva;
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (boot_cpu_data.cpu_type >= pcxu)
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iva = (void *) &fault_vector_20;
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
862a8f44e3889b686813926b288bd4e51a0cf17d2c7Helge Deller#ifdef CONFIG_64BIT
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		panic("Can't boot 64-bit OS on PA1.1 processor!");
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iva = (void *) &fault_vector_11;
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (check_ivt(iva))
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		panic("IVT invalid");
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
871