summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2004-08-02 22:16:44 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2004-08-02 22:16:44 +0000
commit68541f1fd2757160a5aaa3523688b417f79ae346 (patch)
tree29a51b1ae541c9ab6bcb2a419cd3263350c13277
parent16864ab061f41f531e180c37b7fda194da118cbf (diff)
On MVME188 systems with 4:1 or 8:1 CMMU pairings, make sure the exception
handling code checks the error status of the correct CMMUs and really reports an error code. This gets us closer to getting these modules to work, at the expense of sanity and some code readability.
-rw-r--r--sys/arch/mvme88k/mvme88k/eh.S228
1 files changed, 176 insertions, 52 deletions
diff --git a/sys/arch/mvme88k/mvme88k/eh.S b/sys/arch/mvme88k/mvme88k/eh.S
index 21219937ead..7a85abbf6a4 100644
--- a/sys/arch/mvme88k/mvme88k/eh.S
+++ b/sys/arch/mvme88k/mvme88k/eh.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: eh.S,v 1.58 2004/08/02 08:35:00 miod Exp $ */
+/* $OpenBSD: eh.S,v 1.59 2004/08/02 22:16:43 miod Exp $ */
/*
* Mach Operating System
* Copyright (c) 1993-1991 Carnegie Mellon University
@@ -32,7 +32,10 @@
* Save Pbus fault status register from data and inst CMMU.
*/
-/* Single-processor SBC version (MVME187, MVME8120) */
+/*
+ * Single-processor SBC version (MVME187, MVME8120)
+ */
+
#ifdef MVME187
#include <machine/mvme187.h>
#define PFSR_SAVE_187 \
@@ -46,68 +49,25 @@
#define PFSR_SAVE_187
#endif
-/* MVME188 version */
+/*
+ * MVME188 version (see pfsr188 below)
+ */
#ifdef MVME188
-#include <machine/mvme188.h>
#define PFSR_SAVE_188 \
- extu TMP, FLAGS, FLAG_CPU_FIELD_WIDTH<0>; /* TMP = cpu# */ \
- cmp TMP2, TMP, 0x0; /* CPU0 ? */ \
- bb1 eq, TMP2, 1f; \
- cmp TMP2, TMP, 0x1; /* CPU1 ? */ \
- bb1 eq, TMP2, 2f; \
- cmp TMP2, TMP, 0x2; /* CPU2 ? */ \
- bb1 eq, TMP2, 3f; \
- br 4f; \
- /* XXX WHAT ABOUT MODULES WITH SPLIT U/S CMMUS ??? */ \
-1: \
- /* must be CPU0 */ \
- or.u TMP, r0, hi16(VME_CMMU_I0); \
- ld TMP2, TMP, lo16(VME_CMMU_I0) + 0x108; \
- st TMP2, r31, REG_OFF(EF_IPFSR); \
- or.u TMP, r0, hi16(VME_CMMU_D0); \
- ld TMP2, TMP, lo16(VME_CMMU_D0) + 0x108; \
- br.n _ASM_LABEL(pfsr_done); \
- st TMP2, r31, REG_OFF(EF_DPFSR); \
-2: \
- /* must be CPU1 */ \
- or.u TMP, r0, hi16(VME_CMMU_I1); \
- ld TMP2, TMP, lo16(VME_CMMU_I1) + 0x108; \
- st TMP2, r31, REG_OFF(EF_IPFSR); \
- or.u TMP, r0, hi16(VME_CMMU_D1); \
- ld TMP2, TMP, lo16(VME_CMMU_D1) + 0x108; \
- br.n _ASM_LABEL(pfsr_done); \
- st TMP2, r31, REG_OFF(EF_DPFSR); \
-3: \
- /* must be CPU2 */ \
- or.u TMP, r0, hi16(VME_CMMU_I2); \
- ld TMP2, TMP, lo16(VME_CMMU_I2) + 0x108; \
- st TMP2, r31, REG_OFF(EF_IPFSR); \
- or.u TMP, r0, hi16(VME_CMMU_D2); \
- ld TMP2, TMP, lo16(VME_CMMU_D2) + 0x108; \
- br.n _ASM_LABEL(pfsr_done); \
- st TMP2, r31, REG_OFF(EF_DPFSR); \
-4: \
- /* must be CPU3 */ \
- or.u TMP, r0, hi16(VME_CMMU_I3); \
- ld TMP2, TMP, lo16(VME_CMMU_I3) + 0x108; \
- st TMP2, r31, REG_OFF(EF_IPFSR); \
- or.u TMP, r0, hi16(VME_CMMU_D3); \
- ld TMP2, TMP, lo16(VME_CMMU_D3) + 0x108; \
- br.n _ASM_LABEL(pfsr_done); \
- st TMP2, r31, REG_OFF(EF_DPFSR);
+ br _ASM_LABEL(pfsr188);
#else
#define PFSR_SAVE_188
#endif
+
#if defined(MVME187) && defined(MVME188)
#define PFSR_SAVE \
/* check if it's a mvme188 */ \
or.u TMP, r0, hi16(_C_LABEL(brdtyp)); \
ld TMP2, TMP, lo16(_C_LABEL(brdtyp)); \
cmp TMP, TMP2, BRD_188; \
- bb1 ne, TMP, 9f; \
- PFSR_SAVE_188 \
-9: PFSR_SAVE_187
+ bb1 eq, TMP, _ASM_LABEL(pfsr188); \
+ PFSR_SAVE_187
#else
#define PFSR_SAVE \
PFSR_SAVE_188 \
@@ -115,3 +75,167 @@
#endif
#include <m88k/m88k/eh_common.S>
+
+#ifdef MVME188
+#include <machine/mvme188.h>
+/*
+ * Handling faults can be very tricky, as it is necessary to check all
+ * the CMMUs of the faulting processor.
+ *
+ * This implementation tries to favor, speedwise:
+ * - simple (2 CMMUs per CPU) configurations over any other configuration;
+ * - faults on CPU0 over the other CPUs.
+ */
+ text
+
+ASLOCAL(pfsr188)
+ or.u TMP, r0, hi16(_C_LABEL(cmmu_shift))
+ ld TMP, TMP, lo16(_C_LABEL(cmmu_shift))
+ cmp TMP2, TMP, 2
+ bb1.n lt, TMP2, _ASM_LABEL(pfsr188_straight)
+ extu TMP, FLAGS, FLAG_CPU_FIELD_WIDTH<0> /* TMP = cpu# */
+ bb1 eq, TMP2, _ASM_LABEL(pfsr188_double)
+
+ASLOCAL(pfsr188_quad)
+ /*
+ * We're in configuration 2 (1 CPU, 8 CMMU).
+ *
+ * Reading the MVME188 error register could tell us which
+ * CMMU faulted, but it's easier to check every one until
+ * we find the first fault.
+ *
+ * If two or more CMMU faulted simultaneously, restarting from
+ * the trap will fault again, and we'll handle the remaining
+ * exceptions here.
+ *
+ * XXX It will probably be worth changing this so that we can
+ * handle a bunch of CMMU faults at once in trap.c.
+ */
+ or.u TMP, r0, hi16(VME_CMMU_I0)
+ ld TMP2, TMP, lo16(VME_CMMU_I0) + 0x108
+ extu TMP, TMP2, 3<16>
+ bcnd ne0, TMP, 1f
+ or.u TMP, r0, hi16(VME_CMMU_I1)
+ ld TMP2, TMP, lo16(VME_CMMU_I1) + 0x108
+ extu TMP, TMP2, 3<16>
+ bcnd ne0, TMP, 1f
+ or.u TMP, r0, hi16(VME_CMMU_I2)
+ ld TMP2, TMP, lo16(VME_CMMU_I2) + 0x108
+ extu TMP, TMP2, 3<16>
+ bcnd ne0, TMP, 1f
+ or.u TMP, r0, hi16(VME_CMMU_I3)
+ ld TMP2, TMP, lo16(VME_CMMU_I3) + 0x108
+1:
+ st TMP2, r31, REG_OFF(EF_IPFSR)
+
+ or.u TMP, r0, hi16(VME_CMMU_D0)
+ ld TMP2, TMP, lo16(VME_CMMU_D0) + 0x108
+ extu TMP, TMP2, 3<16>
+ bcnd ne0, TMP, 2f
+ or.u TMP, r0, hi16(VME_CMMU_D1)
+ ld TMP2, TMP, lo16(VME_CMMU_D1) + 0x108
+ extu TMP, TMP2, 3<16>
+ bcnd ne0, TMP, 2f
+ or.u TMP, r0, hi16(VME_CMMU_D2)
+ ld TMP2, TMP, lo16(VME_CMMU_D2) + 0x108
+ extu TMP, TMP2, 3<16>
+ bcnd ne0, TMP, 2f
+ or.u TMP, r0, hi16(VME_CMMU_D3)
+ ld TMP2, TMP, lo16(VME_CMMU_D3) + 0x108
+2:
+ br.n _ASM_LABEL(pfsr_done)
+ st TMP2, r31, REG_OFF(EF_DPFSR)
+
+ASLOCAL(pfsr188_double)
+ /*
+ * 4 CMMUs per CPU. Almost as simple as the 2 CMMUs per CPU
+ * situation...
+ */
+ bcnd ne0, TMP, 5f
+
+ /* CPU 0 -> CMMU 0 and 1 */
+ or.u TMP, r0, hi16(VME_CMMU_I0)
+ ld TMP2, TMP, lo16(VME_CMMU_I0) + 0x108
+ extu TMP, TMP2, 3<16>
+ bcnd ne0, TMP, 1f
+ or.u TMP, r0, hi16(VME_CMMU_I1)
+ ld TMP2, TMP, lo16(VME_CMMU_I1) + 0x108
+1:
+ st TMP2, r31, REG_OFF(EF_IPFSR)
+
+ or.u TMP, r0, hi16(VME_CMMU_D0)
+ ld TMP2, TMP, lo16(VME_CMMU_D0) + 0x108
+ extu TMP, TMP2, 3<16>
+ bcnd ne0, TMP, 2f
+ or.u TMP, r0, hi16(VME_CMMU_D1)
+ ld TMP2, TMP, lo16(VME_CMMU_D1) + 0x108
+2:
+ br.n _ASM_LABEL(pfsr_done)
+ st TMP2, r31, REG_OFF(EF_DPFSR)
+
+5:
+ /* CPU 1 -> CMMU 2 and 3 */
+ or.u TMP, r0, hi16(VME_CMMU_I2)
+ ld TMP2, TMP, lo16(VME_CMMU_I2) + 0x108
+ extu TMP, TMP2, 3<16>
+ bcnd ne0, TMP, 1f
+ or.u TMP, r0, hi16(VME_CMMU_I3)
+ ld TMP2, TMP, lo16(VME_CMMU_I3) + 0x108
+1:
+ st TMP2, r31, REG_OFF(EF_IPFSR)
+
+ or.u TMP, r0, hi16(VME_CMMU_D2)
+ ld TMP2, TMP, lo16(VME_CMMU_D2) + 0x108
+ extu TMP, TMP2, 3<16>
+ bcnd ne0, TMP, 2f
+ or.u TMP, r0, hi16(VME_CMMU_D3)
+ ld TMP2, TMP, lo16(VME_CMMU_D3) + 0x108
+2:
+ br.n _ASM_LABEL(pfsr_done)
+ st TMP2, r31, REG_OFF(EF_DPFSR)
+
+ASLOCAL(pfsr188_straight)
+ /*
+ * We have the simple 2 CMMUs per CPU mapping. Pick our couple.
+ */
+ bcnd eq0, TMP, 1f /* CPU0 */
+ cmp TMP2, TMP, 0x2
+ bb1 lt, TMP2, 2f /* CPU1 */
+ bb1 eq, TMP2, 3f /* CPU2 */
+
+ /* must be CPU3 */
+ or.u TMP, r0, hi16(VME_CMMU_I3)
+ ld TMP2, TMP, lo16(VME_CMMU_I3) + 0x108
+ st TMP2, r31, REG_OFF(EF_IPFSR)
+ or.u TMP, r0, hi16(VME_CMMU_D3)
+ ld TMP2, TMP, lo16(VME_CMMU_D3) + 0x108
+ br.n _ASM_LABEL(pfsr_done)
+ st TMP2, r31, REG_OFF(EF_DPFSR)
+1:
+ /* must be CPU0 */
+ or.u TMP, r0, hi16(VME_CMMU_I0)
+ ld TMP2, TMP, lo16(VME_CMMU_I0) + 0x108
+ st TMP2, r31, REG_OFF(EF_IPFSR)
+ or.u TMP, r0, hi16(VME_CMMU_D0)
+ ld TMP2, TMP, lo16(VME_CMMU_D0) + 0x108
+ br.n _ASM_LABEL(pfsr_done)
+ st TMP2, r31, REG_OFF(EF_DPFSR)
+2:
+ /* must be CPU1 */
+ or.u TMP, r0, hi16(VME_CMMU_I1)
+ ld TMP2, TMP, lo16(VME_CMMU_I1) + 0x108
+ st TMP2, r31, REG_OFF(EF_IPFSR)
+ or.u TMP, r0, hi16(VME_CMMU_D1)
+ ld TMP2, TMP, lo16(VME_CMMU_D1) + 0x108
+ br.n _ASM_LABEL(pfsr_done)
+ st TMP2, r31, REG_OFF(EF_DPFSR)
+3:
+ /* must be CPU2 */
+ or.u TMP, r0, hi16(VME_CMMU_I2)
+ ld TMP2, TMP, lo16(VME_CMMU_I2) + 0x108
+ st TMP2, r31, REG_OFF(EF_IPFSR)
+ or.u TMP, r0, hi16(VME_CMMU_D2)
+ ld TMP2, TMP, lo16(VME_CMMU_D2) + 0x108
+ br.n _ASM_LABEL(pfsr_done)
+ st TMP2, r31, REG_OFF(EF_DPFSR)
+#endif