patch-2.3.99-pre9 linux/arch/mips/kernel/traps.c

Next file: linux/arch/mips/kernel/unaligned.c
Previous file: linux/arch/mips/kernel/sysmips.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c
@@ -1,12 +1,13 @@
-/* $Id: traps.c,v 1.27 2000/01/16 01:29:05 ralf Exp $
+/* $Id: traps.c,v 1.28 2000/03/13 10:33:02 raiko Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright 1994, 1995, 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 1994 - 1999 by Ralf Baechle
  * Modified for R3000 by Paul M. Antoine, 1995, 1996
  * Complete output from die() by Ulf Carlsson, 1998
+ * Copyright (C) 1999 Silicon Graphics, Inc.
  */
 #include <linux/config.h>
 #include <linux/init.h>
@@ -226,8 +227,50 @@
 		__die(str, regs, where, line);
 }
 
+extern const struct exception_table_entry __start___dbe_table[];
+extern const struct exception_table_entry __stop___dbe_table[];
+
+static void __declare_dbe_table(void)
+{
+	__asm__ __volatile__(
+	".section\t__dbe_table,\"a\"\n\t"
+	".previous"
+	);
+}
+
+static inline unsigned long
+search_one_table(const struct exception_table_entry *first,
+		 const struct exception_table_entry *last,
+		 unsigned long value)
+{
+	const struct exception_table_entry *mid;
+	long diff;
+
+	while (first < last) {
+		mid = (last - first) / 2 + first;
+		diff = mid->insn - value;
+		if (diff < 0)
+			first = mid + 1;
+		else
+			last = mid;
+	}
+	return (first == last && first->insn == value) ? first->nextinsn : 0;
+}
+
+#define search_dbe_table(addr)	\
+	search_one_table(__start___dbe_table, __stop___dbe_table - 1, (addr))
+
 static void default_be_board_handler(struct pt_regs *regs)
 {
+	unsigned long new_epc;
+	unsigned long fixup = search_dbe_table(regs->cp0_epc);
+
+	if (fixup) {
+		new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc);
+		regs->cp0_epc = new_epc;
+		return;
+	}
+
 	/*
 	 * Assume it would be too dangerous to continue ...
 	 */
@@ -281,7 +324,7 @@
 {
 	unsigned long pc;
 	unsigned int insn;
-	extern void simfp(void*);
+	extern void simfp(unsigned int);
 
 #ifdef CONFIG_MIPS_FPE_MODULE
 	if (fpe_handler != NULL) {
@@ -688,8 +731,7 @@
 		else
 			memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
 
-		/* Cache error vector  */
-		memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80);
+		/* Cache error vector already set above.  */
 
 		if (vce_available) {
 			memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000,
@@ -698,7 +740,6 @@
 			memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
 			       0x80);
 		}
-
 		break;
 
 	case CPU_R6000:
@@ -718,14 +759,14 @@
 	case CPU_R2000:
 	case CPU_R3000:
 	case CPU_R3000A:
-		memcpy((void *)KSEG0, &except_vec0_r2300, 0x80);
-		memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80);
-		break;
 	case CPU_R3041:
 	case CPU_R3051:
 	case CPU_R3052:
 	case CPU_R3081:
 	case CPU_R3081E:
+		memcpy((void *)KSEG0, &except_vec0_r2300, 0x80);
+		memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80);
+		break;
 	case CPU_R8000:
 		printk("Detected unsupported CPU type %s.\n",
 			cpu_names[mips_cputype]);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)