memerr.c revision 1.11.8.2 1 1.11.8.2 nathanw /* $NetBSD: memerr.c,v 1.11.8.2 2002/10/18 02:40:20 nathanw Exp $ */
2 1.11.8.2 nathanw
3 1.11.8.2 nathanw /*
4 1.11.8.2 nathanw * Copyright (c) 1992, 1993
5 1.11.8.2 nathanw * The Regents of the University of California. All rights reserved.
6 1.11.8.2 nathanw *
7 1.11.8.2 nathanw * This software was developed by the Computer Systems Engineering group
8 1.11.8.2 nathanw * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 1.11.8.2 nathanw * contributed to Berkeley.
10 1.11.8.2 nathanw *
11 1.11.8.2 nathanw * All advertising materials mentioning features or use of this software
12 1.11.8.2 nathanw * must display the following acknowledgement:
13 1.11.8.2 nathanw * This product includes software developed by the University of
14 1.11.8.2 nathanw * California, Lawrence Berkeley Laboratory.
15 1.11.8.2 nathanw *
16 1.11.8.2 nathanw * Redistribution and use in source and binary forms, with or without
17 1.11.8.2 nathanw * modification, are permitted provided that the following conditions
18 1.11.8.2 nathanw * are met:
19 1.11.8.2 nathanw * 1. Redistributions of source code must retain the above copyright
20 1.11.8.2 nathanw * notice, this list of conditions and the following disclaimer.
21 1.11.8.2 nathanw * 2. Redistributions in binary form must reproduce the above copyright
22 1.11.8.2 nathanw * notice, this list of conditions and the following disclaimer in the
23 1.11.8.2 nathanw * documentation and/or other materials provided with the distribution.
24 1.11.8.2 nathanw * 3. All advertising materials mentioning features or use of this software
25 1.11.8.2 nathanw * must display the following acknowledgement:
26 1.11.8.2 nathanw * This product includes software developed by the University of
27 1.11.8.2 nathanw * California, Berkeley and its contributors.
28 1.11.8.2 nathanw * 4. Neither the name of the University nor the names of its contributors
29 1.11.8.2 nathanw * may be used to endorse or promote products derived from this software
30 1.11.8.2 nathanw * without specific prior written permission.
31 1.11.8.2 nathanw *
32 1.11.8.2 nathanw * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33 1.11.8.2 nathanw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 1.11.8.2 nathanw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 1.11.8.2 nathanw * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36 1.11.8.2 nathanw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 1.11.8.2 nathanw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 1.11.8.2 nathanw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 1.11.8.2 nathanw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40 1.11.8.2 nathanw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41 1.11.8.2 nathanw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 1.11.8.2 nathanw * SUCH DAMAGE.
43 1.11.8.2 nathanw *
44 1.11.8.2 nathanw * @(#)memreg.c 8.1 (Berkeley) 6/11/93
45 1.11.8.2 nathanw */
46 1.11.8.2 nathanw
47 1.11.8.2 nathanw #include <sys/param.h>
48 1.11.8.2 nathanw #include <sys/systm.h>
49 1.11.8.2 nathanw #include <sys/device.h>
50 1.11.8.2 nathanw
51 1.11.8.2 nathanw #include <machine/autoconf.h>
52 1.11.8.2 nathanw #include <machine/cpu.h>
53 1.11.8.2 nathanw #include <machine/idprom.h>
54 1.11.8.2 nathanw #include <machine/pte.h>
55 1.11.8.2 nathanw
56 1.11.8.2 nathanw #include <sun3/sun3/machdep.h>
57 1.11.8.2 nathanw #include <sun3/dev/memerr.h>
58 1.11.8.2 nathanw /* #include <sun3/dev/eccreg.h> - not yet */
59 1.11.8.2 nathanw
60 1.11.8.2 nathanw #define ME_PRI 7 /* Interrupt level (NMI) */
61 1.11.8.2 nathanw
62 1.11.8.2 nathanw extern unsigned char cpu_machine_id;
63 1.11.8.2 nathanw
64 1.11.8.2 nathanw enum memerr_type { ME_PAR = 0, ME_ECC = 1 };
65 1.11.8.2 nathanw
66 1.11.8.2 nathanw struct memerr_softc {
67 1.11.8.2 nathanw struct device sc_dev;
68 1.11.8.2 nathanw struct memerr *sc_reg;
69 1.11.8.2 nathanw enum memerr_type sc_type;
70 1.11.8.2 nathanw char *sc_typename; /* "Parity" or "ECC" */
71 1.11.8.2 nathanw char *sc_csrbits; /* how to print csr bits */
72 1.11.8.2 nathanw /* XXX: counters? */
73 1.11.8.2 nathanw };
74 1.11.8.2 nathanw
75 1.11.8.2 nathanw static int memerr_match __P((struct device *, struct cfdata *, void *));
76 1.11.8.2 nathanw static void memerr_attach __P((struct device *, struct device *, void *));
77 1.11.8.2 nathanw static int memerr_interrupt __P((void *));
78 1.11.8.2 nathanw static void memerr_correctable __P((struct memerr_softc *));
79 1.11.8.2 nathanw
80 1.11.8.2 nathanw CFATTACH_DECL(memerr, sizeof(struct memerr_softc),
81 1.11.8.2 nathanw memerr_match, memerr_attach, NULL, NULL);
82 1.11.8.2 nathanw
83 1.11.8.2 nathanw int memerr_attached;
84 1.11.8.2 nathanw
85 1.11.8.2 nathanw static int
86 1.11.8.2 nathanw memerr_match(parent, cf, args)
87 1.11.8.2 nathanw struct device *parent;
88 1.11.8.2 nathanw struct cfdata *cf;
89 1.11.8.2 nathanw void *args;
90 1.11.8.2 nathanw {
91 1.11.8.2 nathanw struct confargs *ca = args;
92 1.11.8.2 nathanw
93 1.11.8.2 nathanw /* This driver only supports one instance. */
94 1.11.8.2 nathanw if (memerr_attached)
95 1.11.8.2 nathanw return (0);
96 1.11.8.2 nathanw
97 1.11.8.2 nathanw /* Make sure there is something there... */
98 1.11.8.2 nathanw if (bus_peek(ca->ca_bustype, ca->ca_paddr, 1) == -1)
99 1.11.8.2 nathanw return (0);
100 1.11.8.2 nathanw
101 1.11.8.2 nathanw /* Default interrupt priority. */
102 1.11.8.2 nathanw if (ca->ca_intpri == -1)
103 1.11.8.2 nathanw ca->ca_intpri = ME_PRI;
104 1.11.8.2 nathanw
105 1.11.8.2 nathanw return (1);
106 1.11.8.2 nathanw }
107 1.11.8.2 nathanw
108 1.11.8.2 nathanw static void
109 1.11.8.2 nathanw memerr_attach(parent, self, args)
110 1.11.8.2 nathanw struct device *parent;
111 1.11.8.2 nathanw struct device *self;
112 1.11.8.2 nathanw void *args;
113 1.11.8.2 nathanw {
114 1.11.8.2 nathanw struct memerr_softc *sc = (void *)self;
115 1.11.8.2 nathanw struct confargs *ca = args;
116 1.11.8.2 nathanw struct memerr *mer;
117 1.11.8.2 nathanw
118 1.11.8.2 nathanw /*
119 1.11.8.2 nathanw * Which type of memory subsystem do we have?
120 1.11.8.2 nathanw */
121 1.11.8.2 nathanw switch (cpu_machine_id) {
122 1.11.8.2 nathanw case SUN3_MACH_160: /* XXX: correct? */
123 1.11.8.2 nathanw case SUN3_MACH_260:
124 1.11.8.2 nathanw case SUN3X_MACH_470:
125 1.11.8.2 nathanw sc->sc_type = ME_ECC;
126 1.11.8.2 nathanw sc->sc_typename = "ECC";
127 1.11.8.2 nathanw sc->sc_csrbits = ME_ECC_STR;
128 1.11.8.2 nathanw break;
129 1.11.8.2 nathanw
130 1.11.8.2 nathanw default:
131 1.11.8.2 nathanw sc->sc_type = ME_PAR;
132 1.11.8.2 nathanw sc->sc_typename = "Parity";
133 1.11.8.2 nathanw sc->sc_csrbits = ME_PAR_STR;
134 1.11.8.2 nathanw break;
135 1.11.8.2 nathanw }
136 1.11.8.2 nathanw printf(": (%s memory)\n", sc->sc_typename);
137 1.11.8.2 nathanw
138 1.11.8.2 nathanw mer = bus_mapin(ca->ca_bustype, ca->ca_paddr, sizeof(*mer));
139 1.11.8.2 nathanw if (mer == NULL)
140 1.11.8.2 nathanw panic("memerr: can not map register");
141 1.11.8.2 nathanw sc->sc_reg = mer;
142 1.11.8.2 nathanw
143 1.11.8.2 nathanw /* Install interrupt handler. */
144 1.11.8.2 nathanw isr_add_autovect(memerr_interrupt, sc, ca->ca_intpri);
145 1.11.8.2 nathanw
146 1.11.8.2 nathanw /* Enable error interrupt (and checking). */
147 1.11.8.2 nathanw if (sc->sc_type == ME_PAR)
148 1.11.8.2 nathanw mer->me_csr = ME_CSR_IENA | ME_PAR_CHECK;
149 1.11.8.2 nathanw else {
150 1.11.8.2 nathanw /*
151 1.11.8.2 nathanw * XXX: Some day, figure out how to decode
152 1.11.8.2 nathanw * correctable errors and set ME_ECC_CE_ENA
153 1.11.8.2 nathanw * here so we can log them...
154 1.11.8.2 nathanw */
155 1.11.8.2 nathanw mer->me_csr = ME_CSR_IENA; /* | ME_ECC_CE_ENA */
156 1.11.8.2 nathanw }
157 1.11.8.2 nathanw memerr_attached = 1;
158 1.11.8.2 nathanw }
159 1.11.8.2 nathanw
160 1.11.8.2 nathanw /*****************************************************************
161 1.11.8.2 nathanw * Functions for ECC memory
162 1.11.8.2 nathanw *****************************************************************/
163 1.11.8.2 nathanw
164 1.11.8.2 nathanw static int
165 1.11.8.2 nathanw memerr_interrupt(arg)
166 1.11.8.2 nathanw void *arg;
167 1.11.8.2 nathanw {
168 1.11.8.2 nathanw struct memerr_softc *sc = arg;
169 1.11.8.2 nathanw volatile struct memerr *me = sc->sc_reg;
170 1.11.8.2 nathanw u_char csr, ctx;
171 1.11.8.2 nathanw u_int pa, va;
172 1.11.8.2 nathanw int pte;
173 1.11.8.2 nathanw char bits[64];
174 1.11.8.2 nathanw
175 1.11.8.2 nathanw csr = me->me_csr;
176 1.11.8.2 nathanw if ((csr & ME_CSR_IPEND) == 0)
177 1.11.8.2 nathanw return (0);
178 1.11.8.2 nathanw
179 1.11.8.2 nathanw va = me->me_vaddr;
180 1.11.8.2 nathanw ctx = (va >> 28) & 0xF;
181 1.11.8.2 nathanw va &= 0x0FFFffff;
182 1.11.8.2 nathanw pte = get_pte(va);
183 1.11.8.2 nathanw pa = PG_PA(pte);
184 1.11.8.2 nathanw
185 1.11.8.2 nathanw printf("\nMemory error on %s cycle!\n",
186 1.11.8.2 nathanw (ctx & 8) ? "DVMA" : "CPU");
187 1.11.8.2 nathanw printf(" ctx=%d, vaddr=0x%x, paddr=0x%x\n",
188 1.11.8.2 nathanw (ctx & 7), va, pa);
189 1.11.8.2 nathanw printf(" csr=%s\n", bitmask_snprintf(csr, sc->sc_csrbits,
190 1.11.8.2 nathanw bits, sizeof(bits)));
191 1.11.8.2 nathanw
192 1.11.8.2 nathanw /*
193 1.11.8.2 nathanw * If we have parity-checked memory, there is
194 1.11.8.2 nathanw * not much to be done. Any error is fatal.
195 1.11.8.2 nathanw */
196 1.11.8.2 nathanw if (sc->sc_type == ME_PAR) {
197 1.11.8.2 nathanw if (csr & ME_PAR_EMASK) {
198 1.11.8.2 nathanw /* Parity errors are fatal. */
199 1.11.8.2 nathanw goto die;
200 1.11.8.2 nathanw }
201 1.11.8.2 nathanw /* The IPEND bit was set, but no error bits. */
202 1.11.8.2 nathanw goto noerror;
203 1.11.8.2 nathanw }
204 1.11.8.2 nathanw
205 1.11.8.2 nathanw /*
206 1.11.8.2 nathanw * We have ECC memory. More complicated...
207 1.11.8.2 nathanw */
208 1.11.8.2 nathanw if (csr & (ME_ECC_WBTMO | ME_ECC_WBERR)) {
209 1.11.8.2 nathanw printf(" write-back failed, pte=0x%x\n", pte);
210 1.11.8.2 nathanw goto die;
211 1.11.8.2 nathanw }
212 1.11.8.2 nathanw if (csr & ME_ECC_UE) {
213 1.11.8.2 nathanw printf(" uncorrectable ECC error\n");
214 1.11.8.2 nathanw goto die;
215 1.11.8.2 nathanw }
216 1.11.8.2 nathanw if (csr & ME_ECC_CE) {
217 1.11.8.2 nathanw /* Just log this and continue. */
218 1.11.8.2 nathanw memerr_correctable(sc);
219 1.11.8.2 nathanw goto recover;
220 1.11.8.2 nathanw }
221 1.11.8.2 nathanw /* The IPEND bit was set, but no error bits. */
222 1.11.8.2 nathanw goto noerror;
223 1.11.8.2 nathanw
224 1.11.8.2 nathanw die:
225 1.11.8.2 nathanw panic("all bets are off...");
226 1.11.8.2 nathanw
227 1.11.8.2 nathanw noerror:
228 1.11.8.2 nathanw printf("memerr: no error bits set?\n");
229 1.11.8.2 nathanw
230 1.11.8.2 nathanw recover:
231 1.11.8.2 nathanw /* Clear the error by writing the address register. */
232 1.11.8.2 nathanw me->me_vaddr = 0;
233 1.11.8.2 nathanw return (1);
234 1.11.8.2 nathanw }
235 1.11.8.2 nathanw
236 1.11.8.2 nathanw /*
237 1.11.8.2 nathanw * Announce (and log) a correctable ECC error.
238 1.11.8.2 nathanw * Need to look at the ECC syndrome register on
239 1.11.8.2 nathanw * the memory board that caused the error...
240 1.11.8.2 nathanw */
241 1.11.8.2 nathanw void
242 1.11.8.2 nathanw memerr_correctable(sc)
243 1.11.8.2 nathanw struct memerr_softc *sc;
244 1.11.8.2 nathanw {
245 1.11.8.2 nathanw /* XXX: Not yet... */
246 1.11.8.2 nathanw }
247