patch-2.4.10 linux/arch/alpha/kernel/traps.c
Next file: linux/arch/alpha/mm/fault.c
Previous file: linux/arch/alpha/kernel/sys_jensen.c
Back to the patch index
Back to the overall index
- Lines: 131
- Date:
Mon Sep 17 13:16:30 2001
- Orig file:
v2.4.9/linux/arch/alpha/kernel/traps.c
- Orig date:
Mon Aug 27 12:41:38 2001
diff -u --recursive --new-file v2.4.9/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
@@ -19,9 +19,37 @@
#include <asm/uaccess.h>
#include <asm/unaligned.h>
#include <asm/sysinfo.h>
+#include <asm/hwrpb.h>
#include "proto.h"
+/* data/code implementing a work-around for some SRMs which
+ mishandle opDEC faults
+*/
+static int opDEC_testing = 0;
+static int opDEC_fix = 0;
+static unsigned long opDEC_test_pc = 0;
+
+static void
+opDEC_check(void)
+{
+ unsigned long test_pc;
+
+ lock_kernel();
+ opDEC_testing = 1;
+
+ __asm__ __volatile__(
+ " br %0,1f\n"
+ "1: addq %0,8,%0\n"
+ " stq %0,%1\n"
+ " cvttq/svm $f31,$f31\n"
+ : "=&r"(test_pc), "=m"(opDEC_test_pc)
+ : );
+
+ opDEC_testing = 0;
+ unlock_kernel();
+}
+
void
dik_show_regs(struct pt_regs *regs, unsigned long *r9_15)
{
@@ -56,10 +84,12 @@
#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)
@@ -98,6 +128,18 @@
printk("\n");
}
+void show_trace_task(struct task_struct * tsk)
+{
+ struct thread_struct * thread = &tsk->thread;
+ unsigned long fp, sp = thread->ksp, base = (unsigned long) thread;
+
+ if (sp > base && sp+6*8 < base + 16*1024) {
+ fp = ((unsigned long*)sp)[6];
+ if (fp > sp && fp < base + 16*1024)
+ dik_show_trace((unsigned long *)fp);
+ }
+}
+
int kstack_depth_to_print = 24;
void show_stack(unsigned long *sp)
@@ -188,8 +230,10 @@
unsigned long a2, unsigned long a3, unsigned long a4,
unsigned long a5, struct pt_regs regs)
{
- die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"),
+ if (!opDEC_testing || type != 4) {
+ die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"),
®s, type, 0);
+ }
switch (type) {
case 0: /* breakpoint */
@@ -242,6 +286,21 @@
case 4: /* opDEC */
if (implver() == IMPLVER_EV4) {
+ /* The some versions of SRM do not handle
+ the opDEC properly - they return the PC of the
+ opDEC fault, not the instruction after as the
+ Alpha architecture requires. Here we fix it up.
+ We do this by intentionally causing an opDEC
+ fault during the boot sequence and testing if
+ we get the correct PC. If not, we set a flag
+ to correct it every time through.
+ */
+ if (opDEC_testing && regs.pc == opDEC_test_pc) {
+ opDEC_fix = 4;
+ printk("opDEC fixup enabled.\n");
+ }
+ regs.pc += opDEC_fix;
+
/* EV4 does not implement anything except normal
rounding. Everything else will come here as
an illegal instruction. Emulate them. */
@@ -252,12 +311,13 @@
case 3: /* FEN fault */
case 5: /* illoc */
default: /* unexpected instruction-fault type */
+ ;
}
send_sig(SIGILL, current, 1);
}
/* There is an ifdef in the PALcode in MILO that enables a
- "kernel debugging entry point" as an unprivilaged call_pal.
+ "kernel debugging entry point" as an unpriviledged call_pal.
We don't want to have anything to do with it, but unfortunately
several versions of MILO included in distributions have it enabled,
@@ -933,4 +993,11 @@
wrent(entUna, 4);
wrent(entSys, 5);
wrent(entDbg, 6);
+
+ /* Hack for Multia (UDB) and JENSEN: some of their SRMs have
+ * a bug in the handling of the opDEC fault. Fix it up if so.
+ */
+ if (implver() == IMPLVER_EV4) {
+ opDEC_check();
+ }
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)