xref: /netbsd/sys/arch/sparc/sparc/memreg.c (revision c4a72b64)
1 /*	$NetBSD: memreg.c,v 1.35 2002/10/02 16:02:11 thorpej Exp $ */
2 
3 /*
4  * Copyright (c) 1992, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This software was developed by the Computer Systems Engineering group
8  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9  * contributed to Berkeley.
10  *
11  * All advertising materials mentioning features or use of this software
12  * must display the following acknowledgement:
13  *	This product includes software developed by the University of
14  *	California, Lawrence Berkeley Laboratory.
15  *	This product includes software developed by Harvard University.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  * 1. Redistributions of source code must retain the above copyright
21  *    notice, this list of conditions and the following disclaimer.
22  * 2. Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the
24  *    documentation and/or other materials provided with the distribution.
25  * 3. All advertising materials mentioning features or use of this software
26  *    must display the following acknowledgement:
27  *	This product includes software developed by the University of
28  *	California, Berkeley and its contributors.
29  *	This product includes software developed by Harvard University.
30  * 4. Neither the name of the University nor the names of its contributors
31  *    may be used to endorse or promote products derived from this software
32  *    without specific prior written permission.
33  *
34  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
35  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44  * SUCH DAMAGE.
45  *
46  *	@(#)memreg.c	8.1 (Berkeley) 6/11/93
47  */
48 #include "opt_sparc_arch.h"
49 
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/proc.h>
53 #include <sys/device.h>
54 
55 #include <machine/autoconf.h>
56 #include <machine/ctlreg.h>
57 
58 #include <sparc/sparc/memreg.h>
59 #include <sparc/sparc/vaddrs.h>
60 #include <sparc/sparc/asm.h>
61 #include <sparc/sparc/cpuvar.h>
62 
63 #include <machine/reg.h>	/* for trapframe */
64 #include <machine/trap.h>	/* for trap types */
65 
66 static int	memregmatch_mainbus
67 			__P((struct device *, struct cfdata *, void *));
68 static int	memregmatch_obio
69 			__P((struct device *, struct cfdata *, void *));
70 static void	memregattach_mainbus
71 			__P((struct device *, struct device *, void *));
72 static void	memregattach_obio
73 			__P((struct device *, struct device *, void *));
74 
75 CFATTACH_DECL(memreg_mainbus, sizeof(struct device),
76     memregmatch_mainbus, memregattach_mainbus, NULL, NULL);
77 
78 CFATTACH_DECL(memreg_obio, sizeof(struct device),
79     memregmatch_obio, memregattach_obio, NULL, NULL);
80 
81 #if defined(SUN4M)
82 static void hardmemerr4m __P((unsigned, u_int, u_int, u_int, u_int));
83 #endif
84 
85 /*
86  * The OPENPROM calls this "memory-error".
87  */
88 static int
89 memregmatch_mainbus(parent, cf, aux)
90 	struct device *parent;
91 	struct cfdata *cf;
92 	void *aux;
93 {
94 	struct mainbus_attach_args *ma = aux;
95 
96 	return (strcmp("memory-error", ma->ma_name) == 0);
97 }
98 
99 static int
100 memregmatch_obio(parent, cf, aux)
101 	struct device *parent;
102 	struct cfdata *cf;
103 	void *aux;
104 {
105 	union obio_attach_args *uoba = aux;
106 
107 	if (uoba->uoba_isobio4 == 0)
108 		return (strcmp("memory-error", uoba->uoba_sbus.sa_name) == 0);
109 
110 	if (!CPU_ISSUN4) {
111 		printf("memregmatch_obio: attach args mixed up\n");
112 		return (0);
113 	}
114 
115 	return (1);
116 }
117 
118 /* ARGSUSED */
119 static void
120 memregattach_mainbus(parent, self, aux)
121 	struct device *parent, *self;
122 	void *aux;
123 {
124 	struct mainbus_attach_args *ma = aux;
125 	bus_space_handle_t bh;
126 
127 	printf("\n");
128 	if (ma->ma_promvaddr != 0) {
129 		par_err_reg = (volatile int *)ma->ma_promvaddr;
130 		return;
131 	}
132 
133 	if (bus_space_map(ma->ma_bustag,
134 			   ma->ma_paddr,
135 			   sizeof(par_err_reg),
136 			   BUS_SPACE_MAP_LINEAR,
137 			   &bh) != 0) {
138 		printf("memregattach_mainbus: can't map register\n");
139 		return;
140 	}
141 	par_err_reg = (volatile int *)bh;
142 }
143 
144 /* ARGSUSED */
145 static void
146 memregattach_obio(parent, self, aux)
147 	struct device *parent, *self;
148 	void *aux;
149 {
150 	union obio_attach_args *uoba = aux;
151 	bus_space_handle_t bh;
152 
153 	if (uoba->uoba_isobio4 == 0) {
154 		struct sbus_attach_args *sa = &uoba->uoba_sbus;
155 		if (sa->sa_promvaddr != 0) {
156 			par_err_reg = (volatile int *)sa->sa_promvaddr;
157 			return;
158 		}
159 
160 		if (sbus_bus_map(sa->sa_bustag,
161 				 sa->sa_slot, sa->sa_offset,
162 				 sizeof(par_err_reg),
163 				 BUS_SPACE_MAP_LINEAR, &bh) != 0) {
164 			printf("memregattach_obio: can't map register\n");
165 			return;
166 		}
167 		par_err_reg = (volatile int *)bh;
168 	}
169 
170 	/* On sun4, `par_err_reg' has already been mapped in autoconf.c */
171 	if (par_err_reg == NULL)
172 		panic("memregattach");
173 
174 	printf("\n");
175 }
176 
177 /*
178  * Synchronous and asynchronous memory error handler.
179  * (This is the level 15 interrupt, which is not vectored.)
180  * Should kill the process that got its bits clobbered,
181  * and take the page out of the page pool, but for now...
182  */
183 
184 void
185 memerr4_4c(issync, ser, sva, aer, ava, tf)
186 	unsigned int issync;
187 	u_int ser, sva, aer, ava;
188 	struct trapframe *tf;	/* XXX - unused/invalid */
189 {
190 	char bits[64];
191 
192 	printf("%ssync mem arr: ser=%s sva=0x%x ",
193 		issync ? "" : "a",
194 		bitmask_snprintf(ser, SER_BITS, bits, sizeof(bits)),
195 		sva);
196 	printf("aer=%s ava=0x%x\n", bitmask_snprintf(aer & 0xff,
197 		AER_BITS, bits, sizeof(bits)), ava);
198 	if (par_err_reg)
199 		printf("parity error register = %s\n",
200 			bitmask_snprintf(*par_err_reg, PER_BITS,
201 					 bits, sizeof(bits)));
202 	panic("memory error");		/* XXX */
203 }
204 
205 
206 #if defined(SUN4M)
207 /*
208  * hardmemerr4m: called upon fatal memory error. Print a message and panic.
209  */
210 static void
211 hardmemerr4m(type, sfsr, sfva, afsr, afva)
212 	unsigned type;
213 	u_int sfsr;
214 	u_int sfva;
215 	u_int afsr;
216 	u_int afva;
217 {
218 	char *s, bits[64];
219 
220 	printf("memory fault: type %d", type);
221 	s = bitmask_snprintf(sfsr, SFSR_BITS, bits, sizeof(bits));
222 	printf("sfsr=%s sfva=0x%x\n", s, sfva);
223 
224 	if (afsr != 0) {
225 		s = bitmask_snprintf(afsr, AFSR_BITS, bits, sizeof(bits));
226 		printf("; afsr=%s afva=0x%x%x\n", s,
227 			(afsr & AFSR_AFA) >> AFSR_AFA_RSHIFT, afva);
228 	}
229 
230 	if ((sfsr & SFSR_FT) == SFSR_FT_NONE  && (afsr & AFSR_AFO) == 0)
231 		return;
232 
233 	panic("hard memory error");
234 }
235 
236 /*
237  * Memerr4m: handle a non-trivial memory fault. These include HyperSPARC
238  * asynchronous faults, SuperSPARC store-buffer copyback failures, and
239  * data faults without a valid faulting VA. We try to retry the operation
240  * once, and then fail if we get called again.
241  */
242 
243 /* XXXSMP */
244 static int addrold = (int) 0xdeadbeef; /* We pick an unlikely address */
245 static int addroldtop = (int) 0xdeadbeef;
246 static int oldtype = -1;
247 /* XXXSMP */
248 
249 void
250 hypersparc_memerr(type, sfsr, sfva, tf)
251 	unsigned type;
252 	u_int sfsr;
253 	u_int sfva;
254 	struct trapframe *tf;
255 {
256 	u_int afsr;
257 	u_int afva;
258 
259 	if ((tf->tf_psr & PSR_PS) == 0)
260 		KERNEL_PROC_LOCK(curproc);
261 	else
262 		KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE);
263 
264 	(*cpuinfo.get_asyncflt)(&afsr, &afva);
265 	if ((afsr & AFSR_AFO) != 0) {	/* HS async fault! */
266 
267 		printf("HyperSPARC async cache memory failure at phys 0x%x%x\n",
268 		       (afsr & AFSR_AFA) >> AFSR_AFA_RSHIFT, afva);
269 
270 		if (afva == addrold && (afsr & AFSR_AFA) == addroldtop)
271 			goto hard;
272 
273 		oldtype = -1;
274 		addrold = afva;
275 		addroldtop = afsr & AFSR_AFA;
276 	}
277 out:
278 	if ((tf->tf_psr & PSR_PS) == 0)
279 		KERNEL_PROC_UNLOCK(curproc);
280 	else
281 		KERNEL_UNLOCK();
282 	return;
283 
284 hard:
285 	hardmemerr4m(type, sfsr, sfva, afsr, afva);
286 	goto out;
287 }
288 
289 void
290 viking_memerr(type, sfsr, sfva, tf)
291 	unsigned type;
292 	u_int sfsr;
293 	u_int sfva;
294 	struct trapframe *tf;
295 {
296 	u_int afsr=0;	/* No Async fault registers on the viking */
297 	u_int afva=0;
298 
299 	if ((tf->tf_psr & PSR_PS) == 0)
300 		KERNEL_PROC_LOCK(curproc);
301 	else
302 		KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE);
303 
304 	if (type == T_STOREBUFFAULT) {
305 
306 		/*
307 		 * On Supersparc, we try to re-enable the store buffers
308 		 * to force a retry.
309 		 */
310 		printf("store buffer copy-back failure at 0x%x. Retrying...\n",
311 		       sfva);
312 
313 		if (oldtype == T_STOREBUFFAULT || addrold == sfva)
314 			goto hard;
315 
316 		oldtype = T_STOREBUFFAULT;
317 		addrold = sfva;
318 
319 		/* re-enable store buffer */
320 		sta(SRMMU_PCR, ASI_SRMMU,
321 		    lda(SRMMU_PCR, ASI_SRMMU) | VIKING_PCR_SB);
322 
323 	} else if (type == T_DATAFAULT && (sfsr & SFSR_FAV) == 0) {
324 		/*
325 		 * bizarre.
326 		 * XXX: Should handle better. See SuperSPARC manual pg. 9-35
327 		 */
328 		printf("warning: got data fault with no faulting address."
329 		       " Ignoring.\n");
330 
331 		if (oldtype == T_DATAFAULT)
332 			goto hard;
333 		oldtype = T_DATAFAULT;
334 	}
335 
336 out:
337 	if ((tf->tf_psr & PSR_PS) == 0)
338 		KERNEL_PROC_UNLOCK(curproc);
339 	else
340 		KERNEL_UNLOCK();
341 	return;
342 
343 hard:
344 	hardmemerr4m(type, sfsr, sfva, afsr, afva);
345 	goto out;
346 }
347 
348 void
349 memerr4m(type, sfsr, sfva, tf)
350 	unsigned type;
351 	u_int sfsr;
352 	u_int sfva;
353 	struct trapframe *tf;
354 {
355 	u_int afsr;
356 	u_int afva;
357 
358 	if ((tf->tf_psr & PSR_PS) == 0)
359 		KERNEL_PROC_LOCK(curproc);
360 	else
361 		KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE);
362 
363 	/*
364 	 * No known special cases.
365 	 * Just get async registers, if any, and report the unhandled case.
366 	 */
367 	if ((*cpuinfo.get_asyncflt)(&afsr, &afva) != 0)
368 		afsr = afva = 0;
369 
370 	hardmemerr4m(type, sfsr, sfva, afsr, afva);
371 	if ((tf->tf_psr & PSR_PS) == 0)
372 		KERNEL_PROC_UNLOCK(curproc);
373 	else
374 		KERNEL_UNLOCK();
375 }
376 #endif /* SUN4M */
377