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