/* * arch/alpha/kernel/traps.c * * (C) Copyright 1994 Linus Torvalds */ /* * This file initializes the trap entry points */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "proto.h" /* Work-around for some SRMs which mishandle opDEC faults. */ static int opDEC_fix; static void __cpuinit opDEC_check(void) { __asm__ __volatile__ ( /* Load the address of... */ " br $16, 1f\n" /* A stub instruction fault handler. Just add 4 to the pc and continue. */ " ldq $16, 8($sp)\n" " addq $16, 4, $16\n" " stq $16, 8($sp)\n" " call_pal %[rti]\n" /* Install the instruction fault handler. */ "1: lda $17, 3\n" " call_pal %[wrent]\n" /* With that in place, the fault from the round-to-minf fp insn will arrive either at the "lda 4" insn (bad) or one past that (good). This places the correct fixup in %0. */ " lda %[fix], 0\n" " cvttq/svm $f31,$f31\n" " lda %[fix], 4" : [fix] "=r" (opDEC_fix) : [rti] "n" (PAL_rti), [wrent] "n" (PAL_wrent) : "$0", "$1", "$16", "$17", "$22", "$23", "$24", "$25"); if (opDEC_fix) printk("opDEC fixup enabled.\n"); } void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15) { printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx %s\n", regs->pc, regs->r26, regs->ps, print_tainted()); print_symbol("pc is at %s\n", regs->pc); print_symbol("ra is at %s\n", regs->r26 ); printk("v0 = %016lx t0 = %016lx t1 = %016lx\n", regs->r0, regs->r1, regs->r2); printk("t2 = %016lx t3 = %016lx t4 = %016lx\n", regs->r3, regs->r4, regs->r5); printk("t5 = %016lx t6 = %016lx t7 = %016lx\n", regs->r6, regs->r7, regs->r8); if (r9_15) { printk("s0 = %016lx s1 = %016lx s2 = %016lx\n", r9_15[9], r9_15[10], r9_15[11]); printk("s3 = %016lx s4 = %016lx s5 = %016lx\n", r9_15[12], r9_15[13], r9_15[14]); printk("s6 = %016lx\n", r9_15[15]); } printk("a0 = %016lx a1 = %016lx a2 = %016lx\n", regs->r16, regs->r17, regs->r18); printk("a3 = %016lx a4 = %016lx a5 = %016lx\n", regs->r19, regs->r20, regs->r21); printk("t8 = %016lx t9 = %016lx t10= %016lx\n", regs->r22, regs->r23, regs->r24); printk("t11= %016lx pv = %016lx at = %016lx\n", regs->r25, regs->r27, regs->r28); printk("gp = %016lx sp = %p\n", regs->gp, regs+1); #if 0 __halt(); #endif } #if 0 static char * ireg_name[] = {"v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9", "t10", "t11", "ra", "pv", "at", "gp", "sp", "zero"}; #endif static void dik_show_code(unsigned int *pc) { long i; printk("Code:"); for (i = -6; i < 2; i++) { unsigned int insn; if (__get_user(insn, (unsigned int __user *)pc + i)) break; printk("%c%08x%c", i ? ' ' : '<', insn, i ? ' ' : '>'); } printk("\n"); } static void dik_show_trace(unsigned long *sp) { long i = 0; printk("Trace:\n"); while (0x1ff8 & (unsigned long) sp) { extern char _stext[], _etext[]; unsigned long tmp = *sp; sp++; if (tmp < (unsigned long) &_stext) continue;