Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cerr-sb1.c
Go to the documentation of this file.
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 
74 static uint32_t extract_ic(unsigned short addr, int data);
75 static uint32_t extract_dc(unsigned short addr, int data);
76 
77 static 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 
90 static 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 
101 static 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 
144 static 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 */
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
175 extern void check_bus_watcher(void);
176 #endif
177 
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
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 
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. */
273 static 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] */
293 static 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 */
305 static 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 */
319 static 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 
336 static 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 */
440 static 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 
462 struct dc_state {
463  unsigned char val;
464  char *name;
465 };
466 
467 static 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 
481 static 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 
492 static 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 }