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
74static uint32_t extract_ic(unsigned short addr, int data);
75static uint32_t extract_dc(unsigned short addr, int data);
76
77static 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
90static 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
101static 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
144static 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
175extern void check_bus_watcher(void);
176#endif
177
178asmlinkage 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. */
269static 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] */
289static 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 */
301static 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 */
315static 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
332static 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 */
436static 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
458struct dc_state {
459	unsigned char val;
460	char *name;
461};
462
463static 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
477static 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
488static 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