diff options
-rw-r--r-- | sys/arch/m88k/m88k/m88110_mmu.S | 63 | ||||
-rw-r--r-- | sys/arch/m88k/m88k/trap.c | 31 | ||||
-rw-r--r-- | sys/arch/mvme88k/dev/busswreg.h | 6 | ||||
-rw-r--r-- | sys/arch/mvme88k/include/m88110.h | 13 | ||||
-rw-r--r-- | sys/arch/mvme88k/mvme88k/m88110.c | 29 |
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 |