diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2012-05-25 18:17:21 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2012-05-25 18:17:21 +0000 |
commit | 0045739c12e0e9c44b16949d3aac53c9fa45d89b (patch) | |
tree | f2accb115a01fb22005f3cf2987e359e1ce80d29 /sys | |
parent | 4f151eb9f34ba34504f7e738215af75be350274d (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.c | 40 | ||||
-rw-r--r-- | sys/arch/sgi/localbus/imcreg.h | 9 |
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 */ |