xref: /openbmc/linux/arch/mips/mm/cerr-sb1.c (revision d0b73b48)
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 #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
186 	csr_out32(M_BCM1480_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG));
187 #else
188 	csr_out32(M_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG));
189 #endif
190 	printk("Trace buffer frozen\n");
191 #endif
192 
193 	printk("Cache error exception on CPU %x:\n",
194 	       (read_c0_prid() >> 25) & 0x7);
195 
196 	__asm__ __volatile__ (
197 	"	.set	push\n\t"
198 	"	.set	mips64\n\t"
199 	"	.set	noat\n\t"
200 	"	mfc0	%0, $26\n\t"
201 	"	mfc0	%1, $27\n\t"
202 	"	mfc0	%2, $27, 1\n\t"
203 	"	dmfc0	$1, $27, 3\n\t"
204 	"	dsrl32	%3, $1, 0 \n\t"
205 	"	sll	%4, $1, 0 \n\t"
206 	"	mfc0	%5, $30\n\t"
207 	"	.set	pop"
208 	: "=r" (errctl), "=r" (cerr_i), "=r" (cerr_d),
209 	  "=r" (dpahi), "=r" (dpalo), "=r" (eepc));
210 
211 	cerr_dpa = (((uint64_t)dpahi) << 32) | dpalo;
212 	printk(" c0_errorepc ==   %08x\n", eepc);
213 	printk(" c0_errctl   ==   %08x", errctl);
214 	breakout_errctl(errctl);
215 	if (errctl & CP0_ERRCTL_ICACHE) {
216 		printk(" c0_cerr_i   ==   %08x", cerr_i);
217 		breakout_cerri(cerr_i);
218 		if (CP0_CERRI_IDX_VALID(cerr_i)) {
219 			/* Check index of EPC, allowing for delay slot */
220 			if (((eepc & SB1_CACHE_INDEX_MASK) != (cerr_i & SB1_CACHE_INDEX_MASK)) &&
221 			    ((eepc & SB1_CACHE_INDEX_MASK) != ((cerr_i & SB1_CACHE_INDEX_MASK) - 4)))
222 				printk(" cerr_i idx doesn't match eepc\n");
223 			else {
224 				res = extract_ic(cerr_i & SB1_CACHE_INDEX_MASK,
225 						 (cerr_i & CP0_CERRI_DATA) != 0);
226 				if (!(res & cerr_i))
227 					printk("...didn't see indicated icache problem\n");
228 			}
229 		}
230 	}
231 	if (errctl & CP0_ERRCTL_DCACHE) {
232 		printk(" c0_cerr_d   ==   %08x", cerr_d);
233 		breakout_cerrd(cerr_d);
234 		if (CP0_CERRD_DPA_VALID(cerr_d)) {
235 			printk(" c0_cerr_dpa == %010llx\n", cerr_dpa);
236 			if (!CP0_CERRD_IDX_VALID(cerr_d)) {
237 				res = extract_dc(cerr_dpa & SB1_CACHE_INDEX_MASK,
238 						 (cerr_d & CP0_CERRD_DATA) != 0);
239 				if (!(res & cerr_d))
240 					printk("...didn't see indicated dcache problem\n");
241 			} else {
242 				if ((cerr_dpa & SB1_CACHE_INDEX_MASK) != (cerr_d & SB1_CACHE_INDEX_MASK))
243 					printk(" cerr_d idx doesn't match cerr_dpa\n");
244 				else {
245 					res = extract_dc(cerr_d & SB1_CACHE_INDEX_MASK,
246 							 (cerr_d & CP0_CERRD_DATA) != 0);
247 					if (!(res & cerr_d))
248 						printk("...didn't see indicated problem\n");
249 				}
250 			}
251 		}
252 	}
253 
254 	check_bus_watcher();
255 
256 	/*
257 	 * Calling panic() when a fatal cache error occurs scrambles the
258 	 * state of the system (and the cache), making it difficult to
259 	 * investigate after the fact.  However, if you just stall the CPU,
260 	 * the other CPU may keep on running, which is typically very
261 	 * undesirable.
262 	 */
263 #ifdef CONFIG_SB1_CERR_STALL
264 	while (1)
265 		;
266 #else
267 	panic("unhandled cache error");
268 #endif
269 }
270 
271 
272 /* Parity lookup table. */
273 static const uint8_t parity[256] = {
274 	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
275 	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
276 	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
277 	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
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 	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
283 	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
284 	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
285 	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
286 	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
287 	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
288 	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
289 	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0
290 };
291 
292 /* Masks to select bits for Hamming parity, mask_72_64[i] for bit[i] */
293 static const uint64_t mask_72_64[8] = {
294 	0x0738C808099264FFULL,
295 	0x38C808099264FF07ULL,
296 	0xC808099264FF0738ULL,
297 	0x08099264FF0738C8ULL,
298 	0x099264FF0738C808ULL,
299 	0x9264FF0738C80809ULL,
300 	0x64FF0738C8080992ULL,
301 	0xFF0738C808099264ULL
302 };
303 
304 /* Calculate the parity on a range of bits */
305 static char range_parity(uint64_t dword, int max, int min)
306 {
307 	char parity = 0;
308 	int i;
309 	dword >>= min;
310 	for (i=max-min; i>=0; i--) {
311 		if (dword & 0x1)
312 			parity = !parity;
313 		dword >>= 1;
314 	}
315 	return parity;
316 }
317 
318 /* Calculate the 4-bit even byte-parity for an instruction */
319 static unsigned char inst_parity(uint32_t word)
320 {
321 	int i, j;
322 	char parity = 0;
323 	for (j=0; j<4; j++) {
324 		char byte_parity = 0;
325 		for (i=0; i<8; i++) {
326 			if (word & 0x80000000)
327 				byte_parity = !byte_parity;
328 			word <<= 1;
329 		}
330 		parity <<= 1;
331 		parity |= byte_parity;
332 	}
333 	return parity;
334 }
335 
336 static uint32_t extract_ic(unsigned short addr, int data)
337 {
338 	unsigned short way;
339 	int valid;
340 	uint32_t taghi, taglolo, taglohi;
341 	unsigned long long taglo, va;
342 	uint64_t tlo_tmp;
343 	uint8_t lru;
344 	int res = 0;
345 
346 	printk("Icache index 0x%04x  ", addr);
347 	for (way = 0; way < 4; way++) {
348 		/* Index-load-tag-I */
349 		__asm__ __volatile__ (
350 		"	.set	push		\n\t"
351 		"	.set	noreorder	\n\t"
352 		"	.set	mips64		\n\t"
353 		"	.set	noat		\n\t"
354 		"	cache	4, 0(%3)	\n\t"
355 		"	mfc0	%0, $29		\n\t"
356 		"	dmfc0	$1, $28		\n\t"
357 		"	dsrl32	%1, $1, 0	\n\t"
358 		"	sll	%2, $1, 0	\n\t"
359 		"	.set	pop"
360 		: "=r" (taghi), "=r" (taglohi), "=r" (taglolo)
361 		: "r" ((way << 13) | addr));
362 
363 		taglo = ((unsigned long long)taglohi << 32) | taglolo;
364 		if (way == 0) {
365 			lru = (taghi >> 14) & 0xff;
366 			printk("[Bank %d Set 0x%02x]  LRU > %d %d %d %d > MRU\n",
367 				    ((addr >> 5) & 0x3), /* bank */
368 				    ((addr >> 7) & 0x3f), /* index */
369 				    (lru & 0x3),
370 				    ((lru >> 2) & 0x3),
371 				    ((lru >> 4) & 0x3),
372 				    ((lru >> 6) & 0x3));
373 		}
374 		va = (taglo & 0xC0000FFFFFFFE000ULL) | addr;
375 		if ((taglo & (1 << 31)) && (((taglo >> 62) & 0x3) == 3))
376 			va |= 0x3FFFF00000000000ULL;
377 		valid = ((taghi >> 29) & 1);
378 		if (valid) {
379 			tlo_tmp = taglo & 0xfff3ff;
380 			if (((taglo >> 10) & 1) ^ range_parity(tlo_tmp, 23, 0)) {
381 				printk("   ** bad parity in VTag0/G/ASID\n");
382 				res |= CP0_CERRI_TAG_PARITY;
383 			}
384 			if (((taglo >> 11) & 1) ^ range_parity(taglo, 63, 24)) {
385 				printk("   ** bad parity in R/VTag1\n");
386 				res |= CP0_CERRI_TAG_PARITY;
387 			}
388 		}
389 		if (valid ^ ((taghi >> 27) & 1)) {
390 			printk("   ** bad parity for valid bit\n");
391 			res |= CP0_CERRI_TAG_PARITY;
392 		}
393 		printk(" %d  [VA %016llx]  [Vld? %d]  raw tags: %08X-%016llX\n",
394 			    way, va, valid, taghi, taglo);
395 
396 		if (data) {
397 			uint32_t datahi, insta, instb;
398 			uint8_t predecode;
399 			int offset;
400 
401 			/* (hit all banks and ways) */
402 			for (offset = 0; offset < 4; offset++) {
403 				/* Index-load-data-I */
404 				__asm__ __volatile__ (
405 				"	.set	push\n\t"
406 				"	.set	noreorder\n\t"
407 				"	.set	mips64\n\t"
408 				"	.set	noat\n\t"
409 				"	cache	6, 0(%3)  \n\t"
410 				"	mfc0	%0, $29, 1\n\t"
411 				"	dmfc0  $1, $28, 1\n\t"
412 				"	dsrl32 %1, $1, 0 \n\t"
413 				"	sll    %2, $1, 0 \n\t"
414 				"	.set	pop         \n"
415 				: "=r" (datahi), "=r" (insta), "=r" (instb)
416 				: "r" ((way << 13) | addr | (offset << 3)));
417 				predecode = (datahi >> 8) & 0xff;
418 				if (((datahi >> 16) & 1) != (uint32_t)range_parity(predecode, 7, 0)) {
419 					printk("   ** bad parity in predecode\n");
420 					res |= CP0_CERRI_DATA_PARITY;
421 				}
422 				/* XXXKW should/could check predecode bits themselves */
423 				if (((datahi >> 4) & 0xf) ^ inst_parity(insta)) {
424 					printk("   ** bad parity in instruction a\n");
425 					res |= CP0_CERRI_DATA_PARITY;
426 				}
427 				if ((datahi & 0xf) ^ inst_parity(instb)) {
428 					printk("   ** bad parity in instruction b\n");
429 					res |= CP0_CERRI_DATA_PARITY;
430 				}
431 				printk("  %05X-%08X%08X", datahi, insta, instb);
432 			}
433 			printk("\n");
434 		}
435 	}
436 	return res;
437 }
438 
439 /* Compute the ECC for a data doubleword */
440 static uint8_t dc_ecc(uint64_t dword)
441 {
442 	uint64_t t;
443 	uint32_t w;
444 	uint8_t  p;
445 	int      i;
446 
447 	p = 0;
448 	for (i = 7; i >= 0; i--)
449 	{
450 		p <<= 1;
451 		t = dword & mask_72_64[i];
452 		w = (uint32_t)(t >> 32);
453 		p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF]
454 		      ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]);
455 		w = (uint32_t)(t & 0xFFFFFFFF);
456 		p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF]
457 		      ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]);
458 	}
459 	return p;
460 }
461 
462 struct dc_state {
463 	unsigned char val;
464 	char *name;
465 };
466 
467 static struct dc_state dc_states[] = {
468 	{ 0x00, "INVALID" },
469 	{ 0x0f, "COH-SHD" },
470 	{ 0x13, "NCO-E-C" },
471 	{ 0x19, "NCO-E-D" },
472 	{ 0x16, "COH-E-C" },
473 	{ 0x1c, "COH-E-D" },
474 	{ 0xff, "*ERROR*" }
475 };
476 
477 #define DC_TAG_VALID(state) \
478     (((state) == 0x0) || ((state) == 0xf) || ((state) == 0x13) || \
479      ((state) == 0x19) || ((state) == 0x16) || ((state) == 0x1c))
480 
481 static char *dc_state_str(unsigned char state)
482 {
483 	struct dc_state *dsc = dc_states;
484 	while (dsc->val != 0xff) {
485 		if (dsc->val == state)
486 			break;
487 		dsc++;
488 	}
489 	return dsc->name;
490 }
491 
492 static uint32_t extract_dc(unsigned short addr, int data)
493 {
494 	int valid, way;
495 	unsigned char state;
496 	uint32_t taghi, taglolo, taglohi;
497 	unsigned long long taglo, pa;
498 	uint8_t ecc, lru;
499 	int res = 0;
500 
501 	printk("Dcache index 0x%04x  ", addr);
502 	for (way = 0; way < 4; way++) {
503 		__asm__ __volatile__ (
504 		"	.set	push\n\t"
505 		"	.set	noreorder\n\t"
506 		"	.set	mips64\n\t"
507 		"	.set	noat\n\t"
508 		"	cache	5, 0(%3)\n\t"	/* Index-load-tag-D */
509 		"	mfc0	%0, $29, 2\n\t"
510 		"	dmfc0	$1, $28, 2\n\t"
511 		"	dsrl32	%1, $1, 0\n\t"
512 		"	sll	%2, $1, 0\n\t"
513 		"	.set	pop"
514 		: "=r" (taghi), "=r" (taglohi), "=r" (taglolo)
515 		: "r" ((way << 13) | addr));
516 
517 		taglo = ((unsigned long long)taglohi << 32) | taglolo;
518 		pa = (taglo & 0xFFFFFFE000ULL) | addr;
519 		if (way == 0) {
520 			lru = (taghi >> 14) & 0xff;
521 			printk("[Bank %d Set 0x%02x]  LRU > %d %d %d %d > MRU\n",
522 				    ((addr >> 11) & 0x2) | ((addr >> 5) & 1), /* bank */
523 				    ((addr >> 6) & 0x3f), /* index */
524 				    (lru & 0x3),
525 				    ((lru >> 2) & 0x3),
526 				    ((lru >> 4) & 0x3),
527 				    ((lru >> 6) & 0x3));
528 		}
529 		state = (taghi >> 25) & 0x1f;
530 		valid = DC_TAG_VALID(state);
531 		printk(" %d  [PA %010llx]  [state %s (%02x)]  raw tags: %08X-%016llX\n",
532 			    way, pa, dc_state_str(state), state, taghi, taglo);
533 		if (valid) {
534 			if (((taglo >> 11) & 1) ^ range_parity(taglo, 39, 26)) {
535 				printk("   ** bad parity in PTag1\n");
536 				res |= CP0_CERRD_TAG_ADDRESS;
537 			}
538 			if (((taglo >> 10) & 1) ^ range_parity(taglo, 25, 13)) {
539 				printk("   ** bad parity in PTag0\n");
540 				res |= CP0_CERRD_TAG_ADDRESS;
541 			}
542 		} else {
543 			res |= CP0_CERRD_TAG_STATE;
544 		}
545 
546 		if (data) {
547 			uint32_t datalohi, datalolo, datahi;
548 			unsigned long long datalo;
549 			int offset;
550 			char bad_ecc = 0;
551 
552 			for (offset = 0; offset < 4; offset++) {
553 				/* Index-load-data-D */
554 				__asm__ __volatile__ (
555 				"	.set	push\n\t"
556 				"	.set	noreorder\n\t"
557 				"	.set	mips64\n\t"
558 				"	.set	noat\n\t"
559 				"	cache	7, 0(%3)\n\t" /* Index-load-data-D */
560 				"	mfc0	%0, $29, 3\n\t"
561 				"	dmfc0	$1, $28, 3\n\t"
562 				"	dsrl32	%1, $1, 0 \n\t"
563 				"	sll	%2, $1, 0 \n\t"
564 				"	.set	pop"
565 				: "=r" (datahi), "=r" (datalohi), "=r" (datalolo)
566 				: "r" ((way << 13) | addr | (offset << 3)));
567 				datalo = ((unsigned long long)datalohi << 32) | datalolo;
568 				ecc = dc_ecc(datalo);
569 				if (ecc != datahi) {
570 					int bits;
571 					bad_ecc |= 1 << (3-offset);
572 					ecc ^= datahi;
573 					bits = hweight8(ecc);
574 					res |= (bits == 1) ? CP0_CERRD_DATA_SBE : CP0_CERRD_DATA_DBE;
575 				}
576 				printk("  %02X-%016llX", datahi, datalo);
577 			}
578 			printk("\n");
579 			if (bad_ecc)
580 				printk("  dwords w/ bad ECC: %d %d %d %d\n",
581 				       !!(bad_ecc & 8), !!(bad_ecc & 4),
582 				       !!(bad_ecc & 2), !!(bad_ecc & 1));
583 		}
584 	}
585 	return res;
586 }
587