summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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