summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2007-05-25 20:58:40 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2007-05-25 20:58:40 +0000
commitea6c22ed3e8787ca90bd0c939d3f389e7e2ec427 (patch)
tree807153580a6a6c9b5032011fbe1659dfe149d138 /sys
parentf317bc290c14036a44fa5bd89e108b886c5cca9c (diff)
Edge cases can trigger a TLB miss exception instead of an invalid TLB
exception on early R5000 revisions. Despite this bug being supposedly fixed in R5000 revision 2 onwards, it nevertheless occurs quite frequently on matthieu's revision 2.1 R5000. Servicing the TLB miss exception would cause a duplicate TLB to be inserted, which causes the processor operation to become unpredictable (but lethal to the kernel, ten times out of nine). More details about the problem can be found in: http://www.linux-mips.org/archives/linux-mips/2000-02/msg00040.html We work around the issue by checking for an existing TLB entry, and handling this as an invalid TLB exception (as it was intended to be), in this case. Unfortunately this causes a measurable 1% slowdown on ``safe'' processors, so we'll work on providing different tlb handler flavours in the near future to recover from this.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/mips64/mips64/tlbhandler.S37
1 files changed, 36 insertions, 1 deletions
diff --git a/sys/arch/mips64/mips64/tlbhandler.S b/sys/arch/mips64/mips64/tlbhandler.S
index 10d8cd37803..4bbd2603c64 100644
--- a/sys/arch/mips64/mips64/tlbhandler.S
+++ b/sys/arch/mips64/mips64/tlbhandler.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: tlbhandler.S,v 1.15 2007/05/25 20:47:19 miod Exp $ */
+/* $OpenBSD: tlbhandler.S,v 1.16 2007/05/25 20:58:39 miod Exp $ */
/*
* Copyright (c) 1995-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -38,6 +38,8 @@
#include <machine/regnum.h>
#include <machine/cpustate.h>
+#define HAIRY_R5000_ERRATA
+
#include "assym.h"
.set mips3
@@ -57,6 +59,29 @@
.set noat
.ent tlb_miss, 0
tlb_miss:
+#ifdef HAIRY_R5000_ERRATA
+ /*
+ * R5000 errata: edge cases can trigger a TLB miss exception
+ * instead of an invalid TLB exception. Servicing the TLB miss
+ * exception would cause a duplicate TLB to be inserted, which
+ * causes the processor operation to become unpredictable (but
+ * very bad for the kernel's health, ten times out of nine).
+ *
+ * More details about the problem can be found in:
+ * http://www.linux-mips.org/archives/linux-mips/2000-02/msg00040.html
+ *
+ * We work around the issue by checking for an existing TLB entry,
+ * and handling this as an invalid TLB exception (as it was intended
+ * to be), in this case.
+ */
+ tlbp
+ mfc0 k1, COP_0_TLB_INDEX
+ bltz k1, 1f # missing!
+ nop
+ j k_tlb_inv
+ nop
+1:
+#endif
PTR_L k1, curprocpaddr
dmfc0 k0, COP_0_BAD_VADDR
bltz k0, _k_miss # kernel address space
@@ -101,6 +126,16 @@ e_tlb_miss:
.set noat
.ent xtlb_miss, 0
xtlb_miss:
+#ifdef HAIRY_R5000_ERRATA
+ /* See errata comments in tlb_miss above */
+ tlbp
+ mfc0 k1, COP_0_TLB_INDEX
+ bltz k1, 1f # missing!
+ nop
+ j k_tlb_inv
+ nop
+1:
+#endif
dmfc0 k0, COP_0_BAD_VADDR
bltz k0, _k_miss # kernel address space
PTR_SRL k0, k0, SEGSHIFT