Linux Audio

Check our new training course

Loading...
v6.8
  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
 61static uint32_t extract_ic(unsigned short addr, int data);
 62static uint32_t extract_dc(unsigned short addr, int data);
 63
 64static 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
 77static 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
 88static 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
131static 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
162extern void check_bus_watcher(void);
163#endif
164
165asmlinkage 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. */
256static 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] */
276static 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 */
288static 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 */
302static 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
319static 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 */
423static 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
445struct dc_state {
446	unsigned char val;
447	char *name;
448};
449
450static 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
464static 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
475static 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}
v4.17
 
  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}