Loading...
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}
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}