xref: /openbmc/linux/arch/mips/mm/cerr-sb1.c (revision 8730046c)
1 /*
2  * Copyright (C) 2001,2002,2003 Broadcom Corporation
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18 #include <linux/sched.h>
19 #include <asm/mipsregs.h>
20 #include <asm/sibyte/sb1250.h>
21 #include <asm/sibyte/sb1250_regs.h>
22 
23 #if !defined(CONFIG_SIBYTE_BUS_WATCHER) || defined(CONFIG_SIBYTE_BW_TRACE)
24 #include <asm/io.h>
25 #include <asm/sibyte/sb1250_scd.h>
26 #endif
27 
28 /*
29  * We'd like to dump the L2_ECC_TAG register on errors, but errata make
30  * that unsafe... So for now we don't.	(BCM1250/BCM112x erratum SOC-48.)
31  */
32 #undef DUMP_L2_ECC_TAG_ON_ERROR
33 
34 /* SB1 definitions */
35 
36 /* XXX should come from config1 XXX */
37 #define SB1_CACHE_INDEX_MASK   0x1fe0
38 
39 #define CP0_ERRCTL_RECOVERABLE (1 << 31)
40 #define CP0_ERRCTL_DCACHE      (1 << 30)
41 #define CP0_ERRCTL_ICACHE      (1 << 29)
42 #define CP0_ERRCTL_MULTIBUS    (1 << 23)
43 #define CP0_ERRCTL_MC_TLB      (1 << 15)
44 #define CP0_ERRCTL_MC_TIMEOUT  (1 << 14)
45 
46 #define CP0_CERRI_TAG_PARITY   (1 << 29)
47 #define CP0_CERRI_DATA_PARITY  (1 << 28)
48 #define CP0_CERRI_EXTERNAL     (1 << 26)
49 
50 #define CP0_CERRI_IDX_VALID(c) (!((c) & CP0_CERRI_EXTERNAL))
51 #define CP0_CERRI_DATA	       (CP0_CERRI_DATA_PARITY)
52 
53 #define CP0_CERRD_MULTIPLE     (1 << 31)
54 #define CP0_CERRD_TAG_STATE    (1 << 30)
55 #define CP0_CERRD_TAG_ADDRESS  (1 << 29)
56 #define CP0_CERRD_DATA_SBE     (1 << 28)
57 #define CP0_CERRD_DATA_DBE     (1 << 27)
58 #define CP0_CERRD_EXTERNAL     (1 << 26)
59 #define CP0_CERRD_LOAD	       (1 << 25)
60 #define CP0_CERRD_STORE	       (1 << 24)
61 #define CP0_CERRD_FILLWB       (1 << 23)
62 #define CP0_CERRD_COHERENCY    (1 << 22)
63 #define CP0_CERRD_DUPTAG       (1 << 21)
64 
65 #define CP0_CERRD_DPA_VALID(c) (!((c) & CP0_CERRD_EXTERNAL))
66 #define CP0_CERRD_IDX_VALID(c) \
67    (((c) & (CP0_CERRD_LOAD | CP0_CERRD_STORE)) ? (!((c) & CP0_CERRD_EXTERNAL)) : 0)
68 #define CP0_CERRD_CAUSES \
69    (CP0_CERRD_LOAD | CP0_CERRD_STORE | CP0_CERRD_FILLWB | CP0_CERRD_COHERENCY | CP0_CERRD_DUPTAG)
70 #define CP0_CERRD_TYPES \
71    (CP0_CERRD_TAG_STATE | CP0_CERRD_TAG_ADDRESS | CP0_CERRD_DATA_SBE | CP0_CERRD_DATA_DBE | CP0_CERRD_EXTERNAL)
72 #define CP0_CERRD_DATA	       (CP0_CERRD_DATA_SBE | CP0_CERRD_DATA_DBE)
73 
74 static uint32_t extract_ic(unsigned short addr, int data);
75 static uint32_t extract_dc(unsigned short addr, int data);
76 
77 static inline void breakout_errctl(unsigned int val)
78 {
79 	if (val & CP0_ERRCTL_RECOVERABLE)
80 		printk(" recoverable");
81 	if (val & CP0_ERRCTL_DCACHE)
82 		printk(" dcache");
83 	if (val & CP0_ERRCTL_ICACHE)
84 		printk(" icache");
85 	if (val & CP0_ERRCTL_MULTIBUS)
86 		printk(" multiple-buserr");
87 	printk("\n");
88 }
89 
90 static inline void breakout_cerri(unsigned int val)
91 {
92 	if (val & CP0_CERRI_TAG_PARITY)
93 		printk(" tag-parity");
94 	if (val & CP0_CERRI_DATA_PARITY)
95 		printk(" data-parity");
96 	if (val & CP0_CERRI_EXTERNAL)
97 		printk(" external");
98 	printk("\n");
99 }
100 
101 static inline void breakout_cerrd(unsigned int val)
102 {
103 	switch (val & CP0_CERRD_CAUSES) {
104 	case CP0_CERRD_LOAD:
105 		printk(" load,");
106 		break;
107 	case CP0_CERRD_STORE:
108 		printk(" store,");
109 		break;
110 	case CP0_CERRD_FILLWB:
111 		printk(" fill/wb,");
112 		break;
113 	case CP0_CERRD_COHERENCY:
114 		printk(" coherency,");
115 		break;
116 	case CP0_CERRD_DUPTAG:
117 		printk(" duptags,");
118 		break;
119 	default:
120 		printk(" NO CAUSE,");
121 		break;
122 	}
123 	if (!(val & CP0_CERRD_TYPES))
124 		printk(" NO TYPE");
125 	else {
126 		if (val & CP0_CERRD_MULTIPLE)
127 			printk(" multi-err");
128 		if (val & CP0_CERRD_TAG_STATE)
129 			printk(" tag-state");
130 		if (val & CP0_CERRD_TAG_ADDRESS)
131 			printk(" tag-address");
132 		if (val & CP0_CERRD_DATA_SBE)
133 			printk(" data-SBE");
134 		if (val & CP0_CERRD_DATA_DBE)
135 			printk(" data-DBE");
136 		if (val & CP0_CERRD_EXTERNAL)
137 			printk(" external");
138 	}
139 	printk("\n");
140 }
141 
142 #ifndef CONFIG_SIBYTE_BUS_WATCHER
143 
144 static void check_bus_watcher(void)
145 {
146 	uint32_t status, l2_err, memio_err;
147 #ifdef DUMP_L2_ECC_TAG_ON_ERROR
148 	uint64_t l2_tag;
149 #endif
150 
151 	/* Destructive read, clears register and interrupt */
152 	status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS));
153 	/* Bit 31 is always on, but there's no #define for that */
154 	if (status & ~(1UL << 31)) {
155 		l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS));
156 #ifdef DUMP_L2_ECC_TAG_ON_ERROR
157 		l2_tag = in64(IOADDR(A_L2_ECC_TAG));
158 #endif
159 		memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS));
160 		printk("Bus watcher error counters: %08x %08x\n", l2_err, memio_err);
161 		printk("\nLast recorded signature:\n");
162 		printk("Request %02x from %d, answered by %d with Dcode %d\n",
163 		       (unsigned int)(G_SCD_BERR_TID(status) & 0x3f),
164 		       (int)(G_SCD_BERR_TID(status) >> 6),
165 		       (int)G_SCD_BERR_RID(status),
166 		       (int)G_SCD_BERR_DCODE(status));
167 #ifdef DUMP_L2_ECC_TAG_ON_ERROR
168 		printk("Last L2 tag w/ bad ECC: %016llx\n", l2_tag);
169 #endif
170 	} else {
171 		printk("Bus watcher indicates no error\n");
172 	}
173 }
174 #else
175 extern void check_bus_watcher(void);
176 #endif
177 
178 asmlinkage void sb1_cache_error(void)
179 {
180 	uint32_t errctl, cerr_i, cerr_d, dpalo, dpahi, eepc, res;
181 	unsigned long long cerr_dpa;
182 
183 #ifdef CONFIG_SIBYTE_BW_TRACE
184 	/* Freeze the trace buffer now */
185 	csr_out32(M_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG));
186 	printk("Trace buffer frozen\n");
187 #endif
188 
189 	printk("Cache error exception on CPU %x:\n",
190 	       (read_c0_prid() >> 25) & 0x7);
191 
192 	__asm__ __volatile__ (
193 	"	.set	push\n\t"
194 	"	.set	mips64\n\t"
195 	"	.set	noat\n\t"
196 	"	mfc0	%0, $26\n\t"
197 	"	mfc0	%1, $27\n\t"
198 	"	mfc0	%2, $27, 1\n\t"
199 	"	dmfc0	$1, $27, 3\n\t"
200 	"	dsrl32	%3, $1, 0 \n\t"
201 	"	sll	%4, $1, 0 \n\t"
202 	"	mfc0	%5, $30\n\t"
203 	"	.set	pop"
204 	: "=r" (errctl), "=r" (cerr_i), "=r" (cerr_d),
205 	  "=r" (dpahi), "=r" (dpalo), "=r" (eepc));
206 
207 	cerr_dpa = (((uint64_t)dpahi) << 32) | dpalo;
208 	printk(" c0_errorepc ==	  %08x\n", eepc);
209 	printk(" c0_errctl   ==	  %08x", errctl);
210 	breakout_errctl(errctl);
211 	if (errctl & CP0_ERRCTL_ICACHE) {
212 		printk(" c0_cerr_i   ==	  %08x", cerr_i);
213 		breakout_cerri(cerr_i);
214 		if (CP0_CERRI_IDX_VALID(cerr_i)) {
215 			/* Check index of EPC, allowing for delay slot */
216 			if (((eepc & SB1_CACHE_INDEX_MASK) != (cerr_i & SB1_CACHE_INDEX_MASK)) &&
217 			    ((eepc & SB1_CACHE_INDEX_MASK) != ((cerr_i & SB1_CACHE_INDEX_MASK) - 4)))
218 				printk(" cerr_i idx doesn't match eepc\n");
219 			else {
220 				res = extract_ic(cerr_i & SB1_CACHE_INDEX_MASK,
221 						 (cerr_i & CP0_CERRI_DATA) != 0);
222 				if (!(res & cerr_i))
223 					printk("...didn't see indicated icache problem\n");
224 			}
225 		}
226 	}
227 	if (errctl & CP0_ERRCTL_DCACHE) {
228 		printk(" c0_cerr_d   ==	  %08x", cerr_d);
229 		breakout_cerrd(cerr_d);
230 		if (CP0_CERRD_DPA_VALID(cerr_d)) {
231 			printk(" c0_cerr_dpa == %010llx\n", cerr_dpa);
232 			if (!CP0_CERRD_IDX_VALID(cerr_d)) {
233 				res = extract_dc(cerr_dpa & SB1_CACHE_INDEX_MASK,
234 						 (cerr_d & CP0_CERRD_DATA) != 0);
235 				if (!(res & cerr_d))
236 					printk("...didn't see indicated dcache problem\n");
237 			} else {
238 				if ((cerr_dpa & SB1_CACHE_INDEX_MASK) != (cerr_d & SB1_CACHE_INDEX_MASK))
239 					printk(" cerr_d idx doesn't match cerr_dpa\n");
240 				else {
241 					res = extract_dc(cerr_d & SB1_CACHE_INDEX_MASK,
242 							 (cerr_d & CP0_CERRD_DATA) != 0);
243 					if (!(res & cerr_d))
244 						printk("...didn't see indicated problem\n");
245 				}
246 			}
247 		}
248 	}
249 
250 	check_bus_watcher();
251 
252 	/*
253 	 * Calling panic() when a fatal cache error occurs scrambles the
254 	 * state of the system (and the cache), making it difficult to
255 	 * investigate after the fact.	However, if you just stall the CPU,
256 	 * the other CPU may keep on running, which is typically very
257 	 * undesirable.
258 	 */
259 #ifdef CONFIG_SB1_CERR_STALL
260 	while (1)
261 		;
262 #else
263 	panic("unhandled cache error");
264 #endif
265 }
266 
267 
268 /* Parity lookup table. */
269 static const uint8_t parity[256] = {
270 	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
271 	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
272 	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
273 	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
274 	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
275 	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
276 	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
277 	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
278 	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
279 	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
280 	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
281 	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
282 	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
283 	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
284 	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
285 	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0
286 };
287 
288 /* Masks to select bits for Hamming parity, mask_72_64[i] for bit[i] */
289 static const uint64_t mask_72_64[8] = {
290 	0x0738C808099264FFULL,
291 	0x38C808099264FF07ULL,
292 	0xC808099264FF0738ULL,
293 	0x08099264FF0738C8ULL,
294 	0x099264FF0738C808ULL,
295 	0x9264FF0738C80809ULL,
296 	0x64FF0738C8080992ULL,
297 	0xFF0738C808099264ULL
298 };
299 
300 /* Calculate the parity on a range of bits */
301 static char range_parity(uint64_t dword, int max, int min)
302 {
303 	char parity = 0;
304 	int i;
305 	dword >>= min;
306 	for (i=max-min; i>=0; i--) {
307 		if (dword & 0x1)
308 			parity = !parity;
309 		dword >>= 1;
310 	}
311 	return parity;
312 }
313 
314 /* Calculate the 4-bit even byte-parity for an instruction */
315 static unsigned char inst_parity(uint32_t word)
316 {
317 	int i, j;
318 	char parity = 0;
319 	for (j=0; j<4; j++) {
320 		char byte_parity = 0;
321 		for (i=0; i<8; i++) {
322 			if (word & 0x80000000)
323 				byte_parity = !byte_parity;
324 			word <<= 1;
325 		}
326 		parity <<= 1;
327 		parity |= byte_parity;
328 	}
329 	return parity;
330 }
331 
332 static uint32_t extract_ic(unsigned short addr, int data)
333 {
334 	unsigned short way;
335 	int valid;
336 	uint32_t taghi, taglolo, taglohi;
337 	unsigned long long taglo, va;
338 	uint64_t tlo_tmp;
339 	uint8_t lru;
340 	int res = 0;
341 
342 	printk("Icache index 0x%04x  ", addr);
343 	for (way = 0; way < 4; way++) {
344 		/* Index-load-tag-I */
345 		__asm__ __volatile__ (
346 		"	.set	push		\n\t"
347 		"	.set	noreorder	\n\t"
348 		"	.set	mips64		\n\t"
349 		"	.set	noat		\n\t"
350 		"	cache	4, 0(%3)	\n\t"
351 		"	mfc0	%0, $29		\n\t"
352 		"	dmfc0	$1, $28		\n\t"
353 		"	dsrl32	%1, $1, 0	\n\t"
354 		"	sll	%2, $1, 0	\n\t"
355 		"	.set	pop"
356 		: "=r" (taghi), "=r" (taglohi), "=r" (taglolo)
357 		: "r" ((way << 13) | addr));
358 
359 		taglo = ((unsigned long long)taglohi << 32) | taglolo;
360 		if (way == 0) {
361 			lru = (taghi >> 14) & 0xff;
362 			printk("[Bank %d Set 0x%02x]  LRU > %d %d %d %d > MRU\n",
363 				    ((addr >> 5) & 0x3), /* bank */
364 				    ((addr >> 7) & 0x3f), /* index */
365 				    (lru & 0x3),
366 				    ((lru >> 2) & 0x3),
367 				    ((lru >> 4) & 0x3),
368 				    ((lru >> 6) & 0x3));
369 		}
370 		va = (taglo & 0xC0000FFFFFFFE000ULL) | addr;
371 		if ((taglo & (1 << 31)) && (((taglo >> 62) & 0x3) == 3))
372 			va |= 0x3FFFF00000000000ULL;
373 		valid = ((taghi >> 29) & 1);
374 		if (valid) {
375 			tlo_tmp = taglo & 0xfff3ff;
376 			if (((taglo >> 10) & 1) ^ range_parity(tlo_tmp, 23, 0)) {
377 				printk("   ** bad parity in VTag0/G/ASID\n");
378 				res |= CP0_CERRI_TAG_PARITY;
379 			}
380 			if (((taglo >> 11) & 1) ^ range_parity(taglo, 63, 24)) {
381 				printk("   ** bad parity in R/VTag1\n");
382 				res |= CP0_CERRI_TAG_PARITY;
383 			}
384 		}
385 		if (valid ^ ((taghi >> 27) & 1)) {
386 			printk("   ** bad parity for valid bit\n");
387 			res |= CP0_CERRI_TAG_PARITY;
388 		}
389 		printk(" %d  [VA %016llx]  [Vld? %d]  raw tags: %08X-%016llX\n",
390 			    way, va, valid, taghi, taglo);
391 
392 		if (data) {
393 			uint32_t datahi, insta, instb;
394 			uint8_t predecode;
395 			int offset;
396 
397 			/* (hit all banks and ways) */
398 			for (offset = 0; offset < 4; offset++) {
399 				/* Index-load-data-I */
400 				__asm__ __volatile__ (
401 				"	.set	push\n\t"
402 				"	.set	noreorder\n\t"
403 				"	.set	mips64\n\t"
404 				"	.set	noat\n\t"
405 				"	cache	6, 0(%3)  \n\t"
406 				"	mfc0	%0, $29, 1\n\t"
407 				"	dmfc0  $1, $28, 1\n\t"
408 				"	dsrl32 %1, $1, 0 \n\t"
409 				"	sll    %2, $1, 0 \n\t"
410 				"	.set	pop	    \n"
411 				: "=r" (datahi), "=r" (insta), "=r" (instb)
412 				: "r" ((way << 13) | addr | (offset << 3)));
413 				predecode = (datahi >> 8) & 0xff;
414 				if (((datahi >> 16) & 1) != (uint32_t)range_parity(predecode, 7, 0)) {
415 					printk("   ** bad parity in predecode\n");
416 					res |= CP0_CERRI_DATA_PARITY;
417 				}
418 				/* XXXKW should/could check predecode bits themselves */
419 				if (((datahi >> 4) & 0xf) ^ inst_parity(insta)) {
420 					printk("   ** bad parity in instruction a\n");
421 					res |= CP0_CERRI_DATA_PARITY;
422 				}
423 				if ((datahi & 0xf) ^ inst_parity(instb)) {
424 					printk("   ** bad parity in instruction b\n");
425 					res |= CP0_CERRI_DATA_PARITY;
426 				}
427 				printk("  %05X-%08X%08X", datahi, insta, instb);
428 			}
429 			printk("\n");
430 		}
431 	}
432 	return res;
433 }
434 
435 /* Compute the ECC for a data doubleword */
436 static uint8_t dc_ecc(uint64_t dword)
437 {
438 	uint64_t t;
439 	uint32_t w;
440 	uint8_t	 p;
441 	int	 i;
442 
443 	p = 0;
444 	for (i = 7; i >= 0; i--)
445 	{
446 		p <<= 1;
447 		t = dword & mask_72_64[i];
448 		w = (uint32_t)(t >> 32);
449 		p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF]
450 		      ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]);
451 		w = (uint32_t)(t & 0xFFFFFFFF);
452 		p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF]
453 		      ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]);
454 	}
455 	return p;
456 }
457 
458 struct dc_state {
459 	unsigned char val;
460 	char *name;
461 };
462 
463 static struct dc_state dc_states[] = {
464 	{ 0x00, "INVALID" },
465 	{ 0x0f, "COH-SHD" },
466 	{ 0x13, "NCO-E-C" },
467 	{ 0x19, "NCO-E-D" },
468 	{ 0x16, "COH-E-C" },
469 	{ 0x1c, "COH-E-D" },
470 	{ 0xff, "*ERROR*" }
471 };
472 
473 #define DC_TAG_VALID(state) \
474     (((state) == 0x0) || ((state) == 0xf) || ((state) == 0x13) || \
475      ((state) == 0x19) || ((state) == 0x16) || ((state) == 0x1c))
476 
477 static char *dc_state_str(unsigned char state)
478 {
479 	struct dc_state *dsc = dc_states;
480 	while (dsc->val != 0xff) {
481 		if (dsc->val == state)
482 			break;
483 		dsc++;
484 	}
485 	return dsc->name;
486 }
487 
488 static uint32_t extract_dc(unsigned short addr, int data)
489 {
490 	int valid, way;
491 	unsigned char state;
492 	uint32_t taghi, taglolo, taglohi;
493 	unsigned long long taglo, pa;
494 	uint8_t ecc, lru;
495 	int res = 0;
496 
497 	printk("Dcache index 0x%04x  ", addr);
498 	for (way = 0; way < 4; way++) {
499 		__asm__ __volatile__ (
500 		"	.set	push\n\t"
501 		"	.set	noreorder\n\t"
502 		"	.set	mips64\n\t"
503 		"	.set	noat\n\t"
504 		"	cache	5, 0(%3)\n\t"	/* Index-load-tag-D */
505 		"	mfc0	%0, $29, 2\n\t"
506 		"	dmfc0	$1, $28, 2\n\t"
507 		"	dsrl32	%1, $1, 0\n\t"
508 		"	sll	%2, $1, 0\n\t"
509 		"	.set	pop"
510 		: "=r" (taghi), "=r" (taglohi), "=r" (taglolo)
511 		: "r" ((way << 13) | addr));
512 
513 		taglo = ((unsigned long long)taglohi << 32) | taglolo;
514 		pa = (taglo & 0xFFFFFFE000ULL) | addr;
515 		if (way == 0) {
516 			lru = (taghi >> 14) & 0xff;
517 			printk("[Bank %d Set 0x%02x]  LRU > %d %d %d %d > MRU\n",
518 				    ((addr >> 11) & 0x2) | ((addr >> 5) & 1), /* bank */
519 				    ((addr >> 6) & 0x3f), /* index */
520 				    (lru & 0x3),
521 				    ((lru >> 2) & 0x3),
522 				    ((lru >> 4) & 0x3),
523 				    ((lru >> 6) & 0x3));
524 		}
525 		state = (taghi >> 25) & 0x1f;
526 		valid = DC_TAG_VALID(state);
527 		printk(" %d  [PA %010llx]  [state %s (%02x)]  raw tags: %08X-%016llX\n",
528 			    way, pa, dc_state_str(state), state, taghi, taglo);
529 		if (valid) {
530 			if (((taglo >> 11) & 1) ^ range_parity(taglo, 39, 26)) {
531 				printk("   ** bad parity in PTag1\n");
532 				res |= CP0_CERRD_TAG_ADDRESS;
533 			}
534 			if (((taglo >> 10) & 1) ^ range_parity(taglo, 25, 13)) {
535 				printk("   ** bad parity in PTag0\n");
536 				res |= CP0_CERRD_TAG_ADDRESS;
537 			}
538 		} else {
539 			res |= CP0_CERRD_TAG_STATE;
540 		}
541 
542 		if (data) {
543 			uint32_t datalohi, datalolo, datahi;
544 			unsigned long long datalo;
545 			int offset;
546 			char bad_ecc = 0;
547 
548 			for (offset = 0; offset < 4; offset++) {
549 				/* Index-load-data-D */
550 				__asm__ __volatile__ (
551 				"	.set	push\n\t"
552 				"	.set	noreorder\n\t"
553 				"	.set	mips64\n\t"
554 				"	.set	noat\n\t"
555 				"	cache	7, 0(%3)\n\t" /* Index-load-data-D */
556 				"	mfc0	%0, $29, 3\n\t"
557 				"	dmfc0	$1, $28, 3\n\t"
558 				"	dsrl32	%1, $1, 0 \n\t"
559 				"	sll	%2, $1, 0 \n\t"
560 				"	.set	pop"
561 				: "=r" (datahi), "=r" (datalohi), "=r" (datalolo)
562 				: "r" ((way << 13) | addr | (offset << 3)));
563 				datalo = ((unsigned long long)datalohi << 32) | datalolo;
564 				ecc = dc_ecc(datalo);
565 				if (ecc != datahi) {
566 					int bits;
567 					bad_ecc |= 1 << (3-offset);
568 					ecc ^= datahi;
569 					bits = hweight8(ecc);
570 					res |= (bits == 1) ? CP0_CERRD_DATA_SBE : CP0_CERRD_DATA_DBE;
571 				}
572 				printk("  %02X-%016llX", datahi, datalo);
573 			}
574 			printk("\n");
575 			if (bad_ecc)
576 				printk("  dwords w/ bad ECC: %d %d %d %d\n",
577 				       !!(bad_ecc & 8), !!(bad_ecc & 4),
578 				       !!(bad_ecc & 2), !!(bad_ecc & 1));
579 		}
580 	}
581 	return res;
582 }
583