/*
* linux/arch/parisc/traps.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1999, 2000 Philipp Rumpf <prumpf@tux.org>
*/
/*
* 'Traps.c' handles hardware traps and faults after we have saved some
* state in 'asm.s'.
*/
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/console.h>
#include <linux/kallsyms.h>
#include <asm/assembly.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/traps.h>
#include <asm/unaligned.h>
#include <asm/atomic.h>
#include <asm/smp.h>
#include <asm/pdc.h>
#include <asm/pdc_chassis.h>
#include <asm/unwind.h>
#include "../math-emu/math-emu.h" /* for handle_fpe() */
#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */
/* dumped to the console via printk) */
#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
DEFINE_SPINLOCK(pa_dbit_lock);
#endif
int printbinary(char *buf, unsigned long x, int nbits)
{
unsigned long mask = 1UL << (nbits - 1);
while (mask != 0) {
*buf++ = (mask & x ? '1' : '0');
mask >>= 1;
}
*buf = '\0';
return nbits;
}
#ifdef __LP64__
#define RFMT "%016lx"
#else
#define RFMT "%08lx"
#endif
void show_regs(struct pt_regs *regs)
{
int i;
char buf[128], *p;
char *level;
unsigned long cr30;
unsigned long cr31;
/* carlos says that gcc understands better memory in a struct,
* and it makes our life easier with fpregs -- T-Bone */
struct { u32 sw[2]; } s;
level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT;
printk("%s\n", level); /* don't want to have that pretty register dump messed up */
printk("%s YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n", level);
printbinary(buf, regs->gr[0], 32);
printk("%sPSW: %s %s\n", level, buf, print_tainted());
for (i = 0; i < 32; i += 4) {
int j;
p = buf;
p += sprintf(p, "%sr%02d-%02d ", level, i, i + 3);
for (j = 0; j < 4; j++) {
p += sprintf(p, " " RFMT, (i+j) == 0 ? 0 : regs->gr[i + j]);
}
printk("%s\n", buf);
}
for (i = 0; i < 8; i += 4) {
int j;
p = buf;
p += sprintf(p, "%ssr%d-%d ", level, i, i + 3);
for (j = 0; j < 4; j++) {
p += sprintf(p, " " RFMT, regs->sr[i + j]);
}
printk("%s\n", buf);
}
/* FR are 64bit everywhere. Need to use asm to get the content
* of fpsr/fper1, and we assume that we won't have a FP Identify
* in our way, otherwise we're screwed.
* The fldd is used to restore the T-bit if there was one, as the
* store clears it anyway.
* BTW, PA2.0 book says "thou shall not use fstw on FPSR/FPERs". */
__asm__ (
"fstd %%fr0,0(%1) \n\t"
"fldd 0(%1),%%fr0 \n\t"
: "=m" (s) : "r" (&s) : "%r0"
);
printk("%s\n", level);
printk("%s VZOUICununcqcqcqcqcqcrmunTDVZOUI\n", level);
printbinary(buf, s.sw[0], 32);
printk("%sFPSR: %s\n", level, buf);
printk("%sFPER1: %08x\n", level, s.sw[1]);
/* here we'll print fr0 again, tho it'll be meaningless */
for (i = 0; i < 32; i += 4) {
int j;
p = buf;
p += sprintf(p, "%sfr%02d-%02d ", level, i, i + 3);
for (j = 0; j < 4; j++)
p += sprintf(p, " %016llx", (i+j) == 0 ? 0 : regs->fr[i+j]);
printk("%s\n", buf);
}
cr30 = mfctl(30);
cr31 = mfctl(31);
printk("%s\n", level);
printk("%sIASQ: " RFMT " " RFMT " IAOQ: " RFMT " " RFMT "\n",
level, regs->iasq[0], regs->iasq[1], regs->iaoq[0], regs->iaoq[1]);
printk("%s IIR: %08lx ISR: " RFMT " IOR: " RFMT "\n",
level, regs->iir, regs->isr, regs->ior);
printk("%s CPU: %8d CR30: " RFMT " CR31: " RFMT "\n",
level, current_thread_info()->cpu, cr30, cr31);<