diff options
| author | 2014-11-22 22:48:38 +0000 | |
|---|---|---|
| committer | 2014-11-22 22:48:38 +0000 | |
| commit | febcf9eec4b1065eefb2597eb953e37d30caf79e (patch) | |
| tree | 618c64a034f9cafe95400fcbda4b69d5cc0f3986 /sys/arch/sparc | |
| parent | Previous diff changed the location of the ACPI S3/S4 trampoline, which has (diff) | |
| download | wireguard-openbsd-febcf9eec4b1065eefb2597eb953e37d30caf79e.tar.xz wireguard-openbsd-febcf9eec4b1065eefb2597eb953e37d30caf79e.zip | |
Driver for the ECC memory controller found on some sun4m (ss20), so that
recoverable memory errors no longer panic the kernel.
From NetBSD but the manual page.
Diffstat (limited to 'sys/arch/sparc')
| -rw-r--r-- | sys/arch/sparc/conf/GENERIC | 5 | ||||
| -rw-r--r-- | sys/arch/sparc/conf/RAMDISK | 4 | ||||
| -rw-r--r-- | sys/arch/sparc/conf/SUN4M | 5 | ||||
| -rw-r--r-- | sys/arch/sparc/conf/files.sparc | 6 | ||||
| -rw-r--r-- | sys/arch/sparc/sparc/autoconf.c | 3 | ||||
| -rw-r--r-- | sys/arch/sparc/sparc/intr.c | 13 | ||||
| -rw-r--r-- | sys/arch/sparc/sparc/memecc.c | 132 | ||||
| -rw-r--r-- | sys/arch/sparc/sparc/memeccreg.h | 83 |
8 files changed, 240 insertions, 11 deletions
diff --git a/sys/arch/sparc/conf/GENERIC b/sys/arch/sparc/conf/GENERIC index 29a8da7cc0e..43e1d2c39c9 100644 --- a/sys/arch/sparc/conf/GENERIC +++ b/sys/arch/sparc/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.106 2014/10/25 16:51:31 miod Exp $ +# $OpenBSD: GENERIC,v 1.107 2014/11/22 22:48:38 miod Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -73,6 +73,9 @@ memreg0 at mainbus0 # sun4c and sun4e memreg0 at obio0 # sun4m memreg0 at obio0 addr 0xf4000000 # sun4 +# ECC memory control +eccmemctl0 at mainbus0 # sun4m + # Timer chip found on 4/300, sun4c, and sun4m systems. timer0 at mainbus0 # sun4c and sun4e timer0 at obio0 # sun4m diff --git a/sys/arch/sparc/conf/RAMDISK b/sys/arch/sparc/conf/RAMDISK index fbababc9c01..d5a45031783 100644 --- a/sys/arch/sparc/conf/RAMDISK +++ b/sys/arch/sparc/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.76 2014/10/10 05:43:35 deraadt Exp $ +# $OpenBSD: RAMDISK,v 1.77 2014/11/22 22:48:38 miod Exp $ machine sparc maxusers 4 @@ -51,6 +51,8 @@ memreg0 at mainbus0 # sun4c and sun4e memreg0 at obio0 # sun4m memreg0 at obio0 addr 0xf4000000 # sun4 +eccmemctl0 at mainbus0 # sun4m + timer0 at mainbus0 # sun4c and sun4e timer0 at obio0 # sun4m timer0 at obio0 addr 0xef000000 # sun4/300 diff --git a/sys/arch/sparc/conf/SUN4M b/sys/arch/sparc/conf/SUN4M index a6ab372c2e8..8bed40f996d 100644 --- a/sys/arch/sparc/conf/SUN4M +++ b/sys/arch/sparc/conf/SUN4M @@ -1,4 +1,4 @@ -# $OpenBSD: SUN4M,v 1.83 2014/10/25 16:51:31 miod Exp $ +# $OpenBSD: SUN4M,v 1.84 2014/11/22 22:48:38 miod Exp $ # $NetBSD: GENERIC,v 1.28.2.1 1996/07/02 23:55:22 jtc Exp $ # Machine architecture; required by config(8) @@ -52,6 +52,9 @@ clock0 at obio0 # sun4m # Memory error registers. memreg0 at obio0 # sun4m +# ECC memory control +eccmemctl0 at mainbus0 # sun4m + # Timer chip found on 4/300, sun4c, and sun4m systems. timer0 at obio0 # sun4m diff --git a/sys/arch/sparc/conf/files.sparc b/sys/arch/sparc/conf/files.sparc index a676ec48e6b..36470b78ed8 100644 --- a/sys/arch/sparc/conf/files.sparc +++ b/sys/arch/sparc/conf/files.sparc @@ -1,4 +1,4 @@ -# $OpenBSD: files.sparc,v 1.96 2014/10/12 19:21:41 miod Exp $ +# $OpenBSD: files.sparc,v 1.97 2014/11/22 22:48:38 miod Exp $ # $NetBSD: files.sparc,v 1.44 1997/08/31 21:29:16 pk Exp $ # @(#)files.sparc 8.1 (Berkeley) 7/19/93 @@ -61,6 +61,10 @@ device memreg attach memreg at mainbus, obio file arch/sparc/sparc/memreg.c +device eccmemctl +attach eccmemctl at mainbus +file arch/sparc/sparc/memecc.c eccmemctl + device zs {[channel = -1]} attach zs at mainbus, obio file arch/sparc/dev/zs.c zs needs-flag diff --git a/sys/arch/sparc/sparc/autoconf.c b/sys/arch/sparc/sparc/autoconf.c index bb338bf3e7c..766bfcb3eb1 100644 --- a/sys/arch/sparc/sparc/autoconf.c +++ b/sys/arch/sparc/sparc/autoconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.c,v 1.96 2014/11/16 12:30:58 deraadt Exp $ */ +/* $OpenBSD: autoconf.c,v 1.97 2014/11/22 22:48:38 miod Exp $ */ /* $NetBSD: autoconf.c,v 1.73 1997/07/29 09:41:53 fair Exp $ */ /* @@ -1163,7 +1163,6 @@ mainbus_attach(parent, dev, aux) * elsewhere. */ "SUNW,sx", /* XXX: no driver for SX yet */ - "eccmemctl", "virtual-memory", "aliases", "memory", diff --git a/sys/arch/sparc/sparc/intr.c b/sys/arch/sparc/sparc/intr.c index d06cdc9d71b..de042ed21c8 100644 --- a/sys/arch/sparc/sparc/intr.c +++ b/sys/arch/sparc/sparc/intr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.c,v 1.39 2014/07/12 18:44:43 tedu Exp $ */ +/* $OpenBSD: intr.c,v 1.40 2014/11/22 22:48:38 miod Exp $ */ /* $NetBSD: intr.c,v 1.20 1997/07/29 09:42:03 fair Exp $ */ /* @@ -92,15 +92,16 @@ strayintr(fp) #if defined(SUN4M) void nmi_hard(void); + +int (*memerr_handler)(void); + void nmi_hard() { /* * A level 15 hard interrupt. */ -#ifdef noyet int fatal = 0; -#endif u_int32_t si; u_int afsr, afva; @@ -125,12 +126,12 @@ nmi_hard() si = *((u_int32_t *)ICR_SI_PEND); printf("NMI: system interrupts: %b\n", si, SINTR_BITS); -#ifdef notyet if ((si & SINTR_M) != 0) { /* ECC memory error */ if (memerr_handler != NULL) fatal |= (*memerr_handler)(); } +#ifdef notyet if ((si & SINTR_I) != 0) { /* MBus/SBus async error */ if (sbuserr_handler != NULL) @@ -146,9 +147,11 @@ nmi_hard() if (moduleerr_handler != NULL) fatal |= (*moduleerr_handler)(); } +#else + fatal |= si & (SINTR_I | SINTR_V | SINTR_ME); +#endif if (fatal) -#endif panic("nmi"); } #endif diff --git a/sys/arch/sparc/sparc/memecc.c b/sys/arch/sparc/sparc/memecc.c new file mode 100644 index 00000000000..3512dc5e38a --- /dev/null +++ b/sys/arch/sparc/sparc/memecc.c @@ -0,0 +1,132 @@ +/* $OpenBSD: memecc.c,v 1.1 2014/11/22 22:48:38 miod Exp $ */ +/* $NetBSD: memecc.c,v 1.16 2013/10/19 19:40:23 mrg Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * ECC memory control. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> + +#include <machine/autoconf.h> +#include <sparc/sparc/memeccreg.h> + +struct memecc_softc { + struct device sc_dev; + vaddr_t sc_reg; +}; + +struct memecc_softc *memecc_sc; + +/* autoconfiguration driver */ +void memecc_attach(struct device *, struct device *, void *); +int memecc_match(struct device *, void *, void *); +int memecc_error(void); + +extern int (*memerr_handler)(void); + +const struct cfattach eccmemctl_ca = { + sizeof(struct memecc_softc), + memecc_match, + memecc_attach +}; + +struct cfdriver eccmemctl_cd = { + 0, "eccmemctl", DV_DULL +}; + +int +memecc_match(struct device *parent, void *vcf, void *aux) +{ + struct confargs *ca = aux; + + if (memerr_handler != NULL) + return 0; + + return (strcmp("eccmemctl", ca->ca_ra.ra_name) == 0); +} + +/* + * Attach the device. + */ +void +memecc_attach(struct device *parent, struct device *self, void *aux) +{ + struct memecc_softc *sc = (struct memecc_softc *)self; + struct confargs *ca = aux; + struct romaux *ra = &ca->ca_ra; + uint32_t reg; + + /* XXX getprop width, mc-type */ + sc->sc_reg = ra->ra_vaddr != NULL ? (vaddr_t)ra->ra_vaddr : + (vaddr_t)mapiodev(ra->ra_reg, 0, 0x20); + + reg = *(volatile uint32_t *)(sc->sc_reg + ECC_EN_REG); + + printf(": version 0x%x/0x%x\n", + (reg & ECC_EN_VER) >> 24, + (reg & ECC_EN_IMPL) >> 28); + + /* Enable checking & interrupts */ + reg |= ECC_EN_EE | ECC_EN_EI; + *(volatile uint32_t *)(sc->sc_reg + ECC_EN_REG) = reg; + memecc_sc = sc; + + memerr_handler = memecc_error; +} + +/* + * Called if the MEMORY ERROR bit is set after a level 25 interrupt. + */ +int +memecc_error(void) +{ + uint32_t efsr, efar0, efar1; + + efsr = *(volatile uint32_t *)(memecc_sc->sc_reg + ECC_FSR_REG); + efar0 = *(volatile uint32_t *)(memecc_sc->sc_reg + ECC_AFR0_REG); + efar1 = *(volatile uint32_t *)(memecc_sc->sc_reg + ECC_AFR1_REG); + printf("memory error:\n\tEFSR: %08x\n", efsr); + printf("\tMBus transaction: %08x\n", efar0 & ~ECC_AFR_PAH); + printf("\taddress: 0x%x%x\n", efar0 & ECC_AFR_PAH, efar1); +#if 0 + printf("\tmodule location: %s\n", + prom_pa_location(efar1, efar0 & ECC_AFR_PAH)); +#endif + + /* Unlock registers and clear interrupt */ + *(volatile uint32_t *)(memecc_sc->sc_reg + ECC_FSR_REG) = efsr; + + /* Return 0 if this was a correctable error */ + return ((efsr & ECC_FSR_CE) == 0); +} diff --git a/sys/arch/sparc/sparc/memeccreg.h b/sys/arch/sparc/sparc/memeccreg.h new file mode 100644 index 00000000000..d81904c4499 --- /dev/null +++ b/sys/arch/sparc/sparc/memeccreg.h @@ -0,0 +1,83 @@ +/* $OpenBSD: memeccreg.h,v 1.1 2014/11/22 22:48:38 miod Exp $ */ +/* $NetBSD: memeccreg.h,v 1.2 2008/04/28 20:23:36 martin Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * ECC memory control. + */ + +/* Register offsets */ +#define ECC_EN_REG 0 +#define ECC_FSR_REG 8 +#define ECC_AFR0_REG 16 +#define ECC_AFR1_REG 20 +#define ECC_DIAG_REG 24 + +/* ECC Memory Enable register */ +#define ECC_EN_EE 0x00000001 /* Enable ECC checking */ +#define ECC_EN_EI 0x00000002 /* Interrupt on correctable error */ +#define ECC_EN_VER 0x0f000000 /* Version */ +#define ECC_EN_IMPL 0xf0000000 /* Implementation Id */ + +/* ECC Memory Fault Status register */ +#define ECC_FSR_CE 0x00000001 /* Correctable error */ +#define ECC_FSR_TO 0x00000004 /* Timeout on write */ +#define ECC_FSR_UE 0x00000008 /* Uncorrectable error */ +#define ECC_FSR_DW 0x000000f0 /* Index of double word in block */ +#define ECC_FSR_SYND 0x0000ff00 /* Syndrome for correctable error */ +#define ECC_FSR_ME 0x00010000 /* Multiple errors */ + +/* + * ECC Memory Fault Address registers + * There are two of these. The first has bits 32-35 of the faulting + * physical address and assorted MBus bits. The second has bits + * 0-31 of the faulting physical address. + */ +#define ECC_AFR_PAH 0x0000000f /* PA[31-35] */ +#define ECC_AFR_TYPE 0x000000f0 /* Transaction type */ +#define ECC_AFR_SIZE 0x00000700 /* Transaction size */ +#define ECC_AFR_C 0x00000800 /* Mapped cacheable */ +#define ECC_AFR_LOCK 0x00001000 /* Error occurred in atomic cycle */ +#define ECC_AFR_MBL 0x00002000 /* Boot mode */ +#define ECC_AFR_VA 0x003fc000 /* VA[12-19] (superset bits) */ +#define ECC_AFR_S 0x08000000 /* Access was in supervisor mode */ +#define ECC_AFR_MID 0xf0000000 /* Module code */ + +/* ECC Diagnostic register */ +#define ECC_DR_CBX 0x00000001 +#define ECC_DR_CB0 0x00000002 +#define ECC_DR_CB1 0x00000004 +#define ECC_DR_CB2 0x00000008 +#define ECC_DR_CB4 0x00000010 +#define ECC_DR_CB8 0x00000020 +#define ECC_DR_CB16 0x00000040 +#define ECC_DR_CB32 0x00000080 +#define ECC_DR_DMODE 0x00000c00 |
