Merge branch 'linus' into sched/devel
[linux-2.6] / arch / mips / mm / cerr-sb1.c
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 */
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
175 extern void check_bus_watcher(void);
176 #endif
177
178 asmlinkage 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. */
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 = 0;
571                                         bad_ecc |= 1 << (3-offset);
572                                         ecc ^= datahi;
573                                         while (ecc) {
574                                                 if (ecc & 1) bits++;
575                                                 ecc >>= 1;
576                                         }
577                                         res |= (bits == 1) ? CP0_CERRD_DATA_SBE : CP0_CERRD_DATA_DBE;
578                                 }
579                                 printk("  %02X-%016llX", datahi, datalo);
580                         }
581                         printk("\n");
582                         if (bad_ecc)
583                                 printk("  dwords w/ bad ECC: %d %d %d %d\n",
584                                        !!(bad_ecc & 8), !!(bad_ecc & 4),
585                                        !!(bad_ecc & 2), !!(bad_ecc & 1));
586                 }
587         }
588         return res;
589 }