summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2014-07-02 17:44:36 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2014-07-02 17:44:36 +0000
commitcb9f61dc41a4aa984a6c90a52941869d9d0413c8 (patch)
tree737f67dee4a960666bfa5ef8391fe241b0f4e60f /sys/arch
parentcd7f6e93caacde55ec8dcf508173e254ed17a7a0 (diff)
On IP28, ignore (as in, do not report) GIO bus errors where the address isn't
actually part of the GIO address range; these obviously come from speculative R10000 execution and are completely harmless (except for the need to acknowledge them, which we have to do anyway).
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/sgi/gio/gioreg.h4
-rw-r--r--sys/arch/sgi/localbus/imc.c62
-rw-r--r--sys/arch/sgi/localbus/imcreg.h15
-rw-r--r--sys/arch/sgi/sgi/ip22_machdep.c4
4 files changed, 55 insertions, 30 deletions
diff --git a/sys/arch/sgi/gio/gioreg.h b/sys/arch/sgi/gio/gioreg.h
index 7822ce4f0b6..9abc4ff4283 100644
--- a/sys/arch/sgi/gio/gioreg.h
+++ b/sys/arch/sgi/gio/gioreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: gioreg.h,v 1.3 2012/05/10 21:30:39 miod Exp $ */
+/* $OpenBSD: gioreg.h,v 1.4 2014/07/02 17:44:35 miod Exp $ */
/* $NetBSD: gioreg.h,v 1.4 2006/08/31 00:01:10 rumble Exp $ */
/*
@@ -71,3 +71,5 @@
#define GIO_ADDR_EXP0 0x1f400000 /* 2MB */
#define GIO_ADDR_EXP1 0x1f600000 /* 4MB */
#define GIO_ADDR_END 0x1fa00000
+
+#define IS_GIO_ADDRESS(pa) ((pa) >= GIO_ADDR_GFX && (pa) < GIO_ADDR_END)
diff --git a/sys/arch/sgi/localbus/imc.c b/sys/arch/sgi/localbus/imc.c
index 58e78bbd938..04b60273ee7 100644
--- a/sys/arch/sgi/localbus/imc.c
+++ b/sys/arch/sgi/localbus/imc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: imc.c,v 1.16 2014/05/19 21:18:42 miod Exp $ */
+/* $OpenBSD: imc.c,v 1.17 2014/07/02 17:44:35 miod Exp $ */
/* $NetBSD: imc.c,v 1.32 2011/07/01 18:53:46 dyoung Exp $ */
/*
@@ -61,8 +61,10 @@
#include <sgi/sgi/ip22.h>
#include <sgi/localbus/imcreg.h>
#include <sgi/localbus/imcvar.h>
+#include <sgi/localbus/intreg.h>
#include <sgi/hpc/hpcreg.h>
+#include <sgi/gio/gioreg.h>
#include <sgi/gio/giovar.h>
#include "eisa.h"
@@ -716,10 +718,13 @@ uint32_t
imc_bus_error(uint32_t hwpend, struct trap_frame *tf)
{
uint32_t cpustat, giostat;
- int quiet = 0;
+ paddr_t cpuaddr, gioaddr;
+ int cpuquiet = 0, gioquiet = 0;
cpustat = imc_read(IMC_CPU_ERRSTAT);
+ cpuaddr = imc_read(IMC_CPU_ERRADDR);
giostat = imc_read(IMC_GIO_ERRSTAT);
+ gioaddr = imc_read(IMC_GIO_ERRADDR);
switch (sys_config.system_type) {
case SGI_IP28:
@@ -728,34 +733,41 @@ imc_bus_error(uint32_t hwpend, struct trap_frame *tf)
* non-existing memory when in the kernel. We do not
* want to flood the console about those.
*/
- if ((cpustat & IMC_CPU_ERRSTAT_ADDR) &&
- IS_XKPHYS((vaddr_t)tf->pc))
- quiet = 1;
- /* This happens. No idea why. */
- if (cpustat == 0 && giostat == 0)
- quiet = 1;
+ if (cpustat & IMC_CPU_ERRSTAT_ADDR) {
+ if (IS_XKPHYS((vaddr_t)tf->pc))
+ cpuquiet = 1;
+ }
+ if (giostat != 0) {
+ /*
+ * Ignore speculative writes to interrupt controller
+ * registers.
+ */
+ if ((giostat & IMC_ECC_ERRSTAT_FUW) &&
+ (gioaddr & ~0x3f) == INT2_IP22)
+ gioquiet = 1;
+ /* XXX is it wise to hide these? */
+ if ((giostat & IMC_GIO_ERRSTAT_TMO) &&
+ !IS_GIO_ADDRESS(gioaddr))
+ gioquiet = 1;
+ }
break;
}
- if (quiet == 0) {
- printf("bus error:");
- if (cpustat != 0) {
- vaddr_t pc = tf->pc;
- uint32_t insn = 0xffffffff;
+ if (cpustat != 0 && cpuquiet == 0) {
+ vaddr_t pc = tf->pc;
+ uint32_t insn = 0xffffffff;
- if (tf->pc < 0)
- guarded_read_4(pc, &insn);
- else
- copyin((void *)pc, &insn, sizeof insn);
+ if (tf->pc < 0)
+ guarded_read_4(pc, &insn);
+ else
+ copyin((void *)pc, &insn, sizeof insn);
- printf(" cpu_stat %08x addr %08x pc %p insn %08x",
- cpustat, imc_read(IMC_CPU_ERRADDR), (void *)pc,
- insn);
- }
- if (giostat != 0)
- printf(" gio_stat %08x addr %08x",
- giostat, imc_read(IMC_GIO_ERRADDR));
- printf("\n");
+ printf("bus error: cpu_stat %08x addr %08lx pc %p insn %08x\n",
+ cpustat, cpuaddr, (void *)pc, insn);
+ }
+ if (giostat != 0 && gioquiet == 0) {
+ printf("bus error: gio_stat %08x addr %08lx\n",
+ giostat, gioaddr);
}
if (cpustat != 0)
diff --git a/sys/arch/sgi/localbus/imcreg.h b/sys/arch/sgi/localbus/imcreg.h
index 70b80203396..0f7cfa7abb8 100644
--- a/sys/arch/sgi/localbus/imcreg.h
+++ b/sys/arch/sgi/localbus/imcreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: imcreg.h,v 1.4 2014/03/27 21:24:22 miod Exp $ */
+/* $OpenBSD: imcreg.h,v 1.5 2014/07/02 17:44:35 miod Exp $ */
/* $NetBSD: imcreg.h,v 1.4 2005/12/11 12:18:52 christos Exp $ */
/*
@@ -142,7 +142,18 @@
#define IMC_GIO_ERRADDR 0xf4 /* GIO error address */
#define IMC_GIO_ERRSTAT 0xfc /* GIO error status */
-
+#define IMC_GIO_ERRSTAT_RD 0x00000100 /* read parity error */
+#define IMC_GIO_ERRSTAT_WR 0x00000200 /* write parity error */
+#define IMC_GIO_ERRSTAT_TMO 0x00000400 /* bus timeout */
+#define IMC_GIO_ERRSTAT_PROM 0x00000800 /* PROM write while disabled */
+#define IMC_GIO_ERRSTAT_ADDR 0x00001000 /* parity error during */
+ /* address cycle */
+#define IMC_GIO_ERRSTAT_BC 0x00002000 /* parity error during */
+ /* byte count cycle */
+#define IMC_GIO_ERRSTAT_PIO_RD 0x00004000 /* data parity error during */
+ /* PIO read */
+#define IMC_GIO_ERRSTAT_PIO_WR 0x00008000 /* data parity error during */
+ /* PIO write */
/* {CPU,GIO}_ERRSTAT bits in ECC mode */
#define IMC_ECC_ERRSTAT_FUW 0x00000001 /* fast mode uncached write */
#define IMC_ECC_ERRSTAT_MULTI 0x00000002 /* multi bit error */
diff --git a/sys/arch/sgi/sgi/ip22_machdep.c b/sys/arch/sgi/sgi/ip22_machdep.c
index 39fd2f8d842..2326c50a9a4 100644
--- a/sys/arch/sgi/sgi/ip22_machdep.c
+++ b/sys/arch/sgi/sgi/ip22_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip22_machdep.c,v 1.18 2014/05/19 21:18:42 miod Exp $ */
+/* $OpenBSD: ip22_machdep.c,v 1.19 2014/07/02 17:44:35 miod Exp $ */
/*
* Copyright (c) 2012 Miodrag Vallat.
@@ -352,7 +352,7 @@ ip22_video_setup()
else
return;
- if (fbphys < GIO_ADDR_GFX || fbphys >= GIO_ADDR_END)
+ if (!IS_GIO_ADDRESS(fbphys))
return;
/*