summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/m88k/m88k/m88110_mmu.S63
-rw-r--r--sys/arch/m88k/m88k/trap.c31
-rw-r--r--sys/arch/mvme88k/dev/busswreg.h6
-rw-r--r--sys/arch/mvme88k/include/m88110.h13
-rw-r--r--sys/arch/mvme88k/mvme88k/m88110.c29
5 files changed, 132 insertions, 10 deletions
diff --git a/sys/arch/m88k/m88k/m88110_mmu.S b/sys/arch/m88k/m88k/m88110_mmu.S
index 27c94454682..342edef96f2 100644
--- a/sys/arch/m88k/m88k/m88110_mmu.S
+++ b/sys/arch/m88k/m88k/m88110_mmu.S
@@ -1,4 +1,4 @@
-# $OpenBSD: m88110_mmu.S,v 1.2 2004/06/22 04:54:54 miod Exp $
+# $OpenBSD: m88110_mmu.S,v 1.3 2007/11/22 05:53:56 miod Exp $
/*
* Copyright (c) 2000 Steve Murphree, Jr.
* All rights reserved.
@@ -32,15 +32,34 @@
#include <machine/asm.h>
-/* set routines */
+/*
+ * 88110 errata #20 (4.2) or #4 (5.1.1):
+ * ``If a ldcr, stcr, fldcr, or fstcr instruction is located in the last
+ * word of an instruction page, and the fetch of the next page results
+ * in an mmu exception (invalid descriptor, tablewalk bus error,
+ * software atc miss), the exip and enip value may be incorrectly
+ * incremented to the second word of the page.
+ * Suggested fix: do not allow thses instructions to occupy the last
+ * word of a page if this can occur.''
+ *
+ * This is why the following function are not inlines in asm.h, and are
+ * aligned to 32 byte boundaries.
+ *
+ * Note that fldcr/fstcr are used in several places in userland (libc,
+ * libpthread, afs lwp) which will need alignment hints as well to
+ * avoid this. Sigh -- miod
+ */
+
text
- align 4096 /* sigh */
+/* set routines */
+ align 32
ENTRY(set_icmd)
FLUSH_PIPELINE
jmp.n r1
stcr r2, ICMD
+ align 32
ENTRY(set_ictl)
FLUSH_PIPELINE
stcr r2, ICTL
@@ -48,47 +67,57 @@ ENTRY(set_ictl)
FLUSH_PIPELINE
jmp r1
+ align 32
ENTRY(set_isar)
jmp.n r1
stcr r2, ISAR
+ align 32
ENTRY(set_isap)
FLUSH_PIPELINE
NOP
stcr r2, ISAP
jmp r1
+ align 32
ENTRY(set_iuap)
FLUSH_PIPELINE
NOP
stcr r2, IUAP
jmp r1
+ align 32
ENTRY(set_iir)
jmp.n r1
stcr r2, IIR
+ align 32
ENTRY(set_ibp)
jmp.n r1
stcr r2, IBP
+ align 32
ENTRY(set_ippu)
jmp.n r1
stcr r2, IPPU
+ align 32
ENTRY(set_ippl)
jmp.n r1
stcr r2, IPPL
+ align 32
ENTRY(set_isr)
jmp.n r1
stcr r2, ISR
+ align 32
ENTRY(set_dcmd)
FLUSH_PIPELINE
jmp.n r1
stcr r2, DCMD
+ align 32
ENTRY(set_dctl)
FLUSH_PIPELINE
stcr r2, DCTL
@@ -96,11 +125,13 @@ ENTRY(set_dctl)
FLUSH_PIPELINE
jmp r1
+ align 32
ENTRY(set_dsar)
stcr r2, DSAR
NOP
jmp r1
+ align 32
ENTRY(set_dsap)
FLUSH_PIPELINE
NOP
@@ -109,6 +140,7 @@ ENTRY(set_dsap)
NOP
jmp r1
+ align 32
ENTRY(set_duap)
FLUSH_PIPELINE
NOP
@@ -117,103 +149,128 @@ ENTRY(set_duap)
NOP
jmp r1
+ align 32
ENTRY(set_dir)
jmp.n r1
stcr r2, DIR
+ align 32
ENTRY(set_dbp)
jmp.n r1
stcr r2, DBP
+ align 32
ENTRY(set_dppu)
jmp.n r1
stcr r2, DPPU
+ align 32
ENTRY(set_dppl)
jmp.n r1
stcr r2, DPPL
+ align 32
ENTRY(set_dsr)
jmp.n r1
stcr r2, DSR
/* get routines */
+ align 32
ENTRY(get_icmd)
jmp.n r1
ldcr r2, ICMD
+ align 32
ENTRY(get_ictl)
jmp.n r1
ldcr r2, ICTL
+ align 32
ENTRY(get_isar)
jmp.n r1
ldcr r2, ISAR
+ align 32
ENTRY(get_isap)
jmp.n r1
ldcr r2, ISAP
+ align 32
ENTRY(get_iuap)
jmp.n r1
ldcr r2, IUAP
+ align 32
ENTRY(get_iir)
jmp.n r1
ldcr r2, IIR
+ align 32
ENTRY(get_ibp)
jmp.n r1
ldcr r2, IBP
+ align 32
ENTRY(get_ippu)
jmp.n r1
ldcr r2, IPPU
+ align 32
ENTRY(get_ippl)
jmp.n r1
ldcr r2, IPPL
+ align 32
ENTRY(get_isr)
jmp.n r1
ldcr r2, ISR
+ align 32
ENTRY(get_dcmd)
jmp.n r1
ldcr r2, DCMD
+ align 32
ENTRY(get_dctl)
jmp.n r1
ldcr r2, DCTL
+ align 32
ENTRY(get_dsar)
jmp.n r1
ldcr r2, DSAR
+ align 32
ENTRY(get_dsap)
jmp.n r1
ldcr r2, DSAP
+ align 32
ENTRY(get_duap)
jmp.n r1
ldcr r2, DUAP
+ align 32
ENTRY(get_dir)
jmp.n r1
ldcr r2, DIR
+ align 32
ENTRY(get_dbp)
jmp.n r1
ldcr r2, DBP
+ align 32
ENTRY(get_dppu)
jmp.n r1
ldcr r2, DPPU
+ align 32
ENTRY(get_dppl)
jmp.n r1
ldcr r2, DPPL
+ align 32
ENTRY(get_dsr)
jmp.n r1
ldcr r2, DSR
diff --git a/sys/arch/m88k/m88k/trap.c b/sys/arch/m88k/m88k/trap.c
index 05d8b642e8c..ee0f5d36eff 100644
--- a/sys/arch/m88k/m88k/trap.c
+++ b/sys/arch/m88k/m88k/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.48 2007/11/21 19:40:34 miod Exp $ */
+/* $OpenBSD: trap.c,v 1.49 2007/11/22 05:53:56 miod Exp $ */
/*
* Copyright (c) 2004, Miodrag Vallat.
* Copyright (c) 1998 Steve Murphree, Jr.
@@ -621,6 +621,35 @@ m88110_trap(u_int type, struct trapframe *frame)
fault_code = 0;
fault_addr = frame->tf_exip & XIP_ADDR;
+#if 0
+ /*
+ * 88110 errata #16 (4.2) or #3 (5.1.1):
+ * ``bsr, br, bcnd, jsr and jmp instructions with the .n extension
+ * can cause the enip value to be incremented by 4 incorrectly
+ * if the instruction in the delay slot is the first word of a
+ * page which misses in the mmu and results in a hardware
+ * tablewalk which encounters an exception or an invalid
+ * descriptor. The exip value in this case will point to the
+ * first word of the page, and the D bit will be set.
+ *
+ * Note: if the instruction is a jsr.n r1, r1 will be overwritten
+ * with erroneous data. Therefore, no recovery is possible. Do
+ * not allow this instruction to occupy the last word of a page.
+ *
+ * Suggested fix: recover in general by backing up the exip by 4
+ * and clearing the delay bit before an rte when the lower 3 hex
+ * digits of the exip are 001.''
+ *
+ * (the font in the errata document I have does not make it clear
+ * whether the jsr.n problem applies to all registers or only
+ * r1 -- miod)
+ */
+ if ((frame->tf_exip & 0x00000fff) == 0x00000001) {
+ panic("mc88110 errata #16, exip %p enip %p",
+ frame->tf_exip, frame->tf_enip);
+ }
+#endif
+
switch (type) {
default:
panictrap(frame->tf_vector, frame);
diff --git a/sys/arch/mvme88k/dev/busswreg.h b/sys/arch/mvme88k/dev/busswreg.h
index b88f10d5c15..15a31df42ca 100644
--- a/sys/arch/mvme88k/dev/busswreg.h
+++ b/sys/arch/mvme88k/dev/busswreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: busswreg.h,v 1.7 2005/12/11 21:31:36 miod Exp $ */
+/* $OpenBSD: busswreg.h,v 1.8 2007/11/22 05:53:57 miod Exp $ */
/*
* Memory map for BusSwitch chip found in mvme197 boards.
@@ -60,8 +60,8 @@
#define BS_TCTRL2 0x0063
#define BS_LEVEL 0x0064
#define BS_MASK 0x0065
-#define BS_ISEL0 0x0066
-#define BS_ISEL1 0x0067
+#define BS_ISEL0 0x0066 /* do not access on 197LE!!! */
+#define BS_ISEL1 0x0067 /* do not access on 197LE!!! */
#define BS_ABORT 0x0068
#define BS_CPINT 0x0069
#define BS_TINT1 0x006a
diff --git a/sys/arch/mvme88k/include/m88110.h b/sys/arch/mvme88k/include/m88110.h
index a3edd8df00d..d04f3cc24e4 100644
--- a/sys/arch/mvme88k/include/m88110.h
+++ b/sys/arch/mvme88k/include/m88110.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: m88110.h,v 1.18 2007/11/17 05:36:23 miod Exp $ */
+/* $OpenBSD: m88110.h,v 1.19 2007/11/22 05:53:57 miod Exp $ */
#ifndef __MACHINE_M88110_H__
#define __MACHINE_M88110_H__
@@ -173,6 +173,17 @@ u_int get_dsr(void);
#define line_addr(x) (paddr_t)((x) & ~CLINE_MASK)
#define page_addr(x) (paddr_t)((x) & ~PAGE_MASK)
+/*
+ * 88110 general information #22:
+ * ``Issuing a command to flush and invalidate the data cache while the
+ * dcache is disabled (CEN = 0 in dctl) will cause problems. Do not
+ * flush a disabled data cache. In general, there is no reason to
+ * perform this operation with the cache disabled, since it may be
+ * incoherent with the proper state of memory. Before 5.0 the flush
+ * command was treated like a nop when the cache was disabled. This
+ * is no longer the case.''
+ */
+
static __inline__ void mc88110_flush_data_line(paddr_t x)
{
u_int dctl = get_dctl();
diff --git a/sys/arch/mvme88k/mvme88k/m88110.c b/sys/arch/mvme88k/mvme88k/m88110.c
index a3116a62483..d6d64fdf4cd 100644
--- a/sys/arch/mvme88k/mvme88k/m88110.c
+++ b/sys/arch/mvme88k/mvme88k/m88110.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: m88110.c,v 1.42 2007/11/22 05:47:46 miod Exp $ */
+/* $OpenBSD: m88110.c,v 1.43 2007/11/22 05:53:57 miod Exp $ */
/*
* Copyright (c) 1998 Steve Murphree, Jr.
* All rights reserved.
@@ -193,7 +193,13 @@ m88110_initialize_cpu(cpuid_t cpu)
/* clear PATCs */
patc_clear();
- /* Do NOT enable ICTL_PREN (branch prediction) */
+ /*
+ * 88110 errata #1:
+ * ``Under certain conditions involving exceptions, with branch
+ * prediction enabled, the CPU may hang.
+ * Suggested fix: Clear the PREN bit of the ICTL. This will
+ * disable branch prediction.''
+ */
set_ictl(BATC_32M
| CMMU_ICTL_DID /* Double instruction disable */
| CMMU_ICTL_MEN
@@ -201,6 +207,25 @@ m88110_initialize_cpu(cpuid_t cpu)
| CMMU_ICTL_BEN
| CMMU_ICTL_HTEN);
+ /*
+ * 88110 errata #10 (4.2) or #2 (5.1.1):
+ * ``Under some circumstances, the 88110 may incorrectly latch data
+ * as it comes from the bus.
+ * [...]
+ * It is the data matching mechanism that may give corrupt data to
+ * the register files.
+ * Suggested fix: Set the Data Matching Disable bit (bit 2) of the
+ * DCTL. This bit is not documented in the user's manual. This bit
+ * is only present for debug purposes and its functionality should
+ * not be depended upon long term.''
+ *
+ * 88110 errata #5 (5.1.1):
+ * ``Setting the xmem bit in the dctl register to perform st/ld
+ * xmems can cause the cpu to hang if a st instruction follows the
+ * xmem.
+ * Work-Around: do not set the xmem bit in dctl, or separate st
+ * from xmem instructions.''
+ */
set_dctl(BATC_32M
| CMMU_DCTL_RSVD1 /* Data Matching Disable */
| CMMU_DCTL_MEN