Linux Audio

Check our new training course

Loading...
v3.1
  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#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. */
273static 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] */
293static 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 */
305static 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 */
319static 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
336static 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 */
440static 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
462struct dc_state {
463	unsigned char val;
464	char *name;
465};
466
467static 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
481static 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
492static 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}
v3.5.6
  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#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. */
273static 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] */
293static 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 */
305static 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 */
319static 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
336static 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 */
440static 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
462struct dc_state {
463	unsigned char val;
464	char *name;
465};
466
467static 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
481static 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
492static 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}