summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2012-05-25 18:17:21 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2012-05-25 18:17:21 +0000
commit0045739c12e0e9c44b16949d3aac53c9fa45d89b (patch)
treef2accb115a01fb22005f3cf2987e359e1ce80d29 /sys
parent4f151eb9f34ba34504f7e738215af75be350274d (diff)
On IP28, silently acknowledge bus errors which can be attributed to
speculative execution, while in kernel mode, attempting to access bogus physical address through CKSEG[01] or XKPHYS. Surprisingly enough, an IP28 system can boot multiuser without triggering any such error; they will only show up if there is a lot of I/O (and thus, context switching).
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/sgi/localbus/imc.c40
-rw-r--r--sys/arch/sgi/localbus/imcreg.h9
2 files changed, 39 insertions, 10 deletions
diff --git a/sys/arch/sgi/localbus/imc.c b/sys/arch/sgi/localbus/imc.c
index 2526284582a..c8d1a8c85d6 100644
--- a/sys/arch/sgi/localbus/imc.c
+++ b/sys/arch/sgi/localbus/imc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: imc.c,v 1.7 2012/05/25 11:31:04 miod Exp $ */
+/* $OpenBSD: imc.c,v 1.8 2012/05/25 18:17:20 miod Exp $ */
/* $NetBSD: imc.c,v 1.32 2011/07/01 18:53:46 dyoung Exp $ */
/*
@@ -713,12 +713,38 @@ imc_bus_reset()
uint32_t
imc_bus_error(uint32_t hwpend, struct trap_frame *tf)
{
- printf("bus error: cpu_stat %08x addr %08x, gio_stat %08x addr %08x\n",
- imc_read(IMC_CPU_ERRSTAT),
- imc_read(IMC_CPU_ERRADDR),
- imc_read(IMC_GIO_ERRSTAT),
- imc_read(IMC_GIO_ERRADDR));
- imc_bus_reset();
+ uint32_t cpustat, giostat;
+ int quiet = 0;
+
+ cpustat = imc_read(IMC_CPU_ERRSTAT);
+ giostat = imc_read(IMC_GIO_ERRSTAT);
+
+ switch (sys_config.system_type) {
+ case SGI_IP28:
+ /*
+ * R10000 speculative execution may attempt to access
+ * non-existing memory when in the kernel. We do not
+ * want to flood the console about those.
+ */
+ if (cpustat & IMC_CPU_ERRSTAT_ADDR)
+ quiet = 1;
+ /* This happens. No idea why. */
+ if (cpustat == 0 && giostat == 0)
+ quiet = 1;
+ break;
+ }
+
+ if (quiet == 0) {
+ printf("bus error: "
+ "cpu_stat %08x addr %08x, gio_stat %08x addr %08x\n",
+ cpustat, imc_read(IMC_CPU_ERRADDR),
+ giostat, imc_read(IMC_GIO_ERRADDR));
+ }
+
+ if (cpustat != 0)
+ imc_write(IMC_CPU_ERRSTAT, 0);
+ if (giostat != 0)
+ imc_write(IMC_GIO_ERRSTAT, 0);
return hwpend;
}
diff --git a/sys/arch/sgi/localbus/imcreg.h b/sys/arch/sgi/localbus/imcreg.h
index fd27ff4c9be..14a437fe4f3 100644
--- a/sys/arch/sgi/localbus/imcreg.h
+++ b/sys/arch/sgi/localbus/imcreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: imcreg.h,v 1.1 2012/03/28 20:44:23 miod Exp $ */
+/* $OpenBSD: imcreg.h,v 1.2 2012/05/25 18:17:20 miod Exp $ */
/* $NetBSD: imcreg.h,v 1.4 2005/12/11 12:18:52 christos Exp $ */
/*
@@ -133,11 +133,14 @@
#define IMC_GIO_MEMACC 0xdc /* GIO mem access config */
#define IMC_CPU_ERRADDR 0xe4 /* CPU error address */
-
#define IMC_CPU_ERRSTAT 0xec /* CPU error status */
+#define IMC_CPU_ERRSTAT_RD 0x00000100 /* memory parity error */
+#define IMC_CPU_ERRSTAT_PAR 0x00000200 /* CPU parity error */
+#define IMC_CPU_ERRSTAT_ADDR 0x00000400 /* memory bus error */
+#define IMC_CPU_ERRSTAT_SYSAD 0x00000800 /* SysAD parity error */
+#define IMC_CPU_ERRSTAT_SYSCMD 0x00001000 /* syscmd parity error */
#define IMC_GIO_ERRADDR 0xf4 /* GIO error address */
-
#define IMC_GIO_ERRSTAT 0xfc /* GIO error status */
#define IMC_RPSS 0x1004 /* RPSS counter */