Root/arch/mips/mm/cerr-sb1.c

Source at commit 694c7fbe86b8a9c91392e505afcb9fcfc91deccc created 12 years 8 months ago.
By Maarten ter Huurne, MIPS: JZ4740: Add cpufreq support
1/*
2 * Copyright (C) 2001,2002,2003 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18#include <linux/sched.h>
19#include <asm/mipsregs.h>
20#include <asm/sibyte/sb1250.h>
21#include <asm/sibyte/sb1250_regs.h>
22
23#if !defined(CONFIG_SIBYTE_BUS_WATCHER) || defined(CONFIG_SIBYTE_BW_TRACE)
24#include <asm/io.h>
25#include <asm/sibyte/sb1250_scd.h>
26#endif
27
28/*
29 * We'd like to dump the L2_ECC_TAG register on errors, but errata make
30 * that unsafe... So for now we don't. (BCM1250/BCM112x erratum SOC-48.)
31 */
32#undef DUMP_L2_ECC_TAG_ON_ERROR
33
34/* SB1 definitions */
35
36/* XXX should come from config1 XXX */
37#define SB1_CACHE_INDEX_MASK 0x1fe0
38
39#define CP0_ERRCTL_RECOVERABLE (1 << 31)
40#define CP0_ERRCTL_DCACHE (1 << 30)
41#define CP0_ERRCTL_ICACHE (1 << 29)
42#define CP0_ERRCTL_MULTIBUS (1 << 23)
43#define CP0_ERRCTL_MC_TLB (1 << 15)
44#define CP0_ERRCTL_MC_TIMEOUT (1 << 14)
45
46#define CP0_CERRI_TAG_PARITY (1 << 29)
47#define CP0_CERRI_DATA_PARITY (1 << 28)
48#define CP0_CERRI_EXTERNAL (1 << 26)
49
50#define CP0_CERRI_IDX_VALID(c) (!((c) & CP0_CERRI_EXTERNAL))
51#define CP0_CERRI_DATA (CP0_CERRI_DATA_PARITY)
52
53#define CP0_CERRD_MULTIPLE (1 << 31)
54#define CP0_CERRD_TAG_STATE (1 << 30)
55#define CP0_CERRD_TAG_ADDRESS (1 << 29)
56#define CP0_CERRD_DATA_SBE (1 << 28)
57#define CP0_CERRD_DATA_DBE (1 << 27)
58#define CP0_CERRD_EXTERNAL (1 << 26)
59#define CP0_CERRD_LOAD (1 << 25)
60#define CP0_CERRD_STORE (1 << 24)
61#define CP0_CERRD_FILLWB (1 << 23)
62#define CP0_CERRD_COHERENCY (1 << 22)
63#define CP0_CERRD_DUPTAG (1 << 21)
64
65#define CP0_CERRD_DPA_VALID(c) (!((c) & CP0_CERRD_EXTERNAL))
66#define CP0_CERRD_IDX_VALID(c) \
67   (((c) & (CP0_CERRD_LOAD | CP0_CERRD_STORE)) ? (!((c) & CP0_CERRD_EXTERNAL)) : 0)
68#define CP0_CERRD_CAUSES \
69   (CP0_CERRD_LOAD | CP0_CERRD_STORE | CP0_CERRD_FILLWB | CP0_CERRD_COHERENCY | CP0_CERRD_DUPTAG)
70#define CP0_CERRD_TYPES \
71   (CP0_CERRD_TAG_STATE | CP0_CERRD_TAG_ADDRESS | CP0_CERRD_DATA_SBE | CP0_CERRD_DATA_DBE | CP0_CERRD_EXTERNAL)
72#define CP0_CERRD_DATA (CP0_CERRD_DATA_SBE | CP0_CERRD_DATA_DBE)
73
74static uint32_t extract_ic(unsigned short addr, int data);
75static uint32_t extract_dc(unsigned short addr, int data);
76
77static inline void breakout_errctl(unsigned int val)
78{
79    if (val & CP0_ERRCTL_RECOVERABLE)
80        printk(" recoverable");
81    if (val & CP0_ERRCTL_DCACHE)
82        printk(" dcache");
83    if (val & CP0_ERRCTL_ICACHE)
84        printk(" icache");
85    if (val & CP0_ERRCTL_MULTIBUS)
86        printk(" multiple-buserr");
87    printk("\n");
88}
89
90static inline void breakout_cerri(unsigned int val)
91{
92    if (val & CP0_CERRI_TAG_PARITY)
93        printk(" tag-parity");
94    if (val & CP0_CERRI_DATA_PARITY)
95        printk(" data-parity");
96    if (val & CP0_CERRI_EXTERNAL)
97        printk(" external");
98    printk("\n");
99}
100
101static inline void breakout_cerrd(unsigned int val)
102{
103    switch (val & CP0_CERRD_CAUSES) {
104    case CP0_CERRD_LOAD:
105        printk(" load,");
106        break;
107    case CP0_CERRD_STORE:
108        printk(" store,");
109        break;
110    case CP0_CERRD_FILLWB:
111        printk(" fill/wb,");
112        break;
113    case CP0_CERRD_COHERENCY:
114        printk(" coherency,");
115        break;
116    case CP0_CERRD_DUPTAG:
117        printk(" duptags,");
118        break;
119    default:
120        printk(" NO CAUSE,");
121        break;
122    }
123    if (!(val & CP0_CERRD_TYPES))
124        printk(" NO TYPE");
125    else {
126        if (val & CP0_CERRD_MULTIPLE)
127            printk(" multi-err");
128        if (val & CP0_CERRD_TAG_STATE)
129            printk(" tag-state");
130        if (val & CP0_CERRD_TAG_ADDRESS)
131            printk(" tag-address");
132        if (val & CP0_CERRD_DATA_SBE)
133            printk(" data-SBE");
134        if (val & CP0_CERRD_DATA_DBE)
135            printk(" data-DBE");
136        if (val & CP0_CERRD_EXTERNAL)
137            printk(" external");
138    }
139    printk("\n");
140}
141
142#ifndef CONFIG_SIBYTE_BUS_WATCHER
143
144static void check_bus_watcher(void)
145{
146    uint32_t status, l2_err, memio_err;
147#ifdef DUMP_L2_ECC_TAG_ON_ERROR
148    uint64_t l2_tag;
149#endif
150
151    /* Destructive read, clears register and interrupt */
152    status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS));
153    /* Bit 31 is always on, but there's no #define for that */
154    if (status & ~(1UL << 31)) {
155        l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS));
156#ifdef DUMP_L2_ECC_TAG_ON_ERROR
157        l2_tag = in64(IOADDR(A_L2_ECC_TAG));
158#endif
159        memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS));
160        printk("Bus watcher error counters: %08x %08x\n", l2_err, memio_err);
161        printk("\nLast recorded signature:\n");
162        printk("Request %02x from %d, answered by %d with Dcode %d\n",
163               (unsigned int)(G_SCD_BERR_TID(status) & 0x3f),
164               (int)(G_SCD_BERR_TID(status) >> 6),
165               (int)G_SCD_BERR_RID(status),
166               (int)G_SCD_BERR_DCODE(status));
167#ifdef DUMP_L2_ECC_TAG_ON_ERROR
168        printk("Last L2 tag w/ bad ECC: %016llx\n", l2_tag);
169#endif
170    } else {
171        printk("Bus watcher indicates no error\n");
172    }
173}
174#else
175extern void check_bus_watcher(void);
176#endif
177
178asmlinkage void sb1_cache_error(void)
179{
180    uint32_t errctl, cerr_i, cerr_d, dpalo, dpahi, eepc, res;
181    unsigned long long cerr_dpa;
182
183#ifdef CONFIG_SIBYTE_BW_TRACE
184    /* Freeze the trace buffer now */
185    csr_out32(M_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG));
186    printk("Trace buffer frozen\n");
187#endif
188
189    printk("Cache error exception on CPU %x:\n",
190           (read_c0_prid() >> 25) & 0x7);
191
192    __asm__ __volatile__ (
193    " .set push\n\t"
194    " .set mips64\n\t"
195    " .set noat\n\t"
196    " mfc0 %0, $26\n\t"
197    " mfc0 %1, $27\n\t"
198    " mfc0 %2, $27, 1\n\t"
199    " dmfc0 $1, $27, 3\n\t"
200    " dsrl32 %3, $1, 0 \n\t"
201    " sll %4, $1, 0 \n\t"
202    " mfc0 %5, $30\n\t"
203    " .set pop"
204    : "=r" (errctl), "=r" (cerr_i), "=r" (cerr_d),
205      "=r" (dpahi), "=r" (dpalo), "=r" (eepc));
206
207    cerr_dpa = (((uint64_t)dpahi) << 32) | dpalo;
208    printk(" c0_errorepc == %08x\n", eepc);
209    printk(" c0_errctl == %08x", errctl);
210    breakout_errctl(errctl);
211    if (errctl & CP0_ERRCTL_ICACHE) {
212        printk(" c0_cerr_i == %08x", cerr_i);
213        breakout_cerri(cerr_i);
214        if (CP0_CERRI_IDX_VALID(cerr_i)) {
215            /* Check index of EPC, allowing for delay slot */
216            if (((eepc & SB1_CACHE_INDEX_MASK) != (cerr_i & SB1_CACHE_INDEX_MASK)) &&
217                ((eepc & SB1_CACHE_INDEX_MASK) != ((cerr_i & SB1_CACHE_INDEX_MASK) - 4)))
218                printk(" cerr_i idx doesn't match eepc\n");
219            else {
220                res = extract_ic(cerr_i & SB1_CACHE_INDEX_MASK,
221                         (cerr_i & CP0_CERRI_DATA) != 0);
222                if (!(res & cerr_i))
223                    printk("...didn't see indicated icache problem\n");
224            }
225        }
226    }
227    if (errctl & CP0_ERRCTL_DCACHE) {
228        printk(" c0_cerr_d == %08x", cerr_d);
229        breakout_cerrd(cerr_d);
230        if (CP0_CERRD_DPA_VALID(cerr_d)) {
231            printk(" c0_cerr_dpa == %010llx\n", cerr_dpa);
232            if (!CP0_CERRD_IDX_VALID(cerr_d)) {
233                res = extract_dc(cerr_dpa & SB1_CACHE_INDEX_MASK,
234                         (cerr_d & CP0_CERRD_DATA) != 0);
235                if (!(res & cerr_d))
236                    printk("...didn't see indicated dcache problem\n");
237            } else {
238                if ((cerr_dpa & SB1_CACHE_INDEX_MASK) != (cerr_d & SB1_CACHE_INDEX_MASK))
239                    printk(" cerr_d idx doesn't match cerr_dpa\n");
240                else {
241                    res = extract_dc(cerr_d & SB1_CACHE_INDEX_MASK,
242                             (cerr_d & CP0_CERRD_DATA) != 0);
243                    if (!(res & cerr_d))
244                        printk("...didn't see indicated problem\n");
245                }
246            }
247        }
248    }
249
250    check_bus_watcher();
251
252    /*
253     * Calling panic() when a fatal cache error occurs scrambles the
254     * state of the system (and the cache), making it difficult to
255     * investigate after the fact. However, if you just stall the CPU,
256     * the other CPU may keep on running, which is typically very
257     * undesirable.
258     */
259#ifdef CONFIG_SB1_CERR_STALL
260    while (1)
261        ;
262#else
263    panic("unhandled cache error");
264#endif
265}
266
267
268/* Parity lookup table. */
269static const uint8_t parity[256] = {
270    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
271    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
272    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
273    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
274    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
275    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
276    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
277    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
278    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
279    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
280    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
281    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
282    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
283    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
284    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
285    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0
286};
287
288/* Masks to select bits for Hamming parity, mask_72_64[i] for bit[i] */
289static const uint64_t mask_72_64[8] = {
290    0x0738C808099264FFULL,
291    0x38C808099264FF07ULL,
292    0xC808099264FF0738ULL,
293    0x08099264FF0738C8ULL,
294    0x099264FF0738C808ULL,
295    0x9264FF0738C80809ULL,
296    0x64FF0738C8080992ULL,
297    0xFF0738C808099264ULL
298};
299
300/* Calculate the parity on a range of bits */
301static char range_parity(uint64_t dword, int max, int min)
302{
303    char parity = 0;
304    int i;
305    dword >>= min;
306    for (i=max-min; i>=0; i--) {
307        if (dword & 0x1)
308            parity = !parity;
309        dword >>= 1;
310    }
311    return parity;
312}
313
314/* Calculate the 4-bit even byte-parity for an instruction */
315static unsigned char inst_parity(uint32_t word)
316{
317    int i, j;
318    char parity = 0;
319    for (j=0; j<4; j++) {
320        char byte_parity = 0;
321        for (i=0; i<8; i++) {
322            if (word & 0x80000000)
323                byte_parity = !byte_parity;
324            word <<= 1;
325        }
326        parity <<= 1;
327        parity |= byte_parity;
328    }
329    return parity;
330}
331
332static uint32_t extract_ic(unsigned short addr, int data)
333{
334    unsigned short way;
335    int valid;
336    uint32_t taghi, taglolo, taglohi;
337    unsigned long long taglo, va;
338    uint64_t tlo_tmp;
339    uint8_t lru;
340    int res = 0;
341
342    printk("Icache index 0x%04x ", addr);
343    for (way = 0; way < 4; way++) {
344        /* Index-load-tag-I */
345        __asm__ __volatile__ (
346        " .set push \n\t"
347        " .set noreorder \n\t"
348        " .set mips64 \n\t"
349        " .set noat \n\t"
350        " cache 4, 0(%3) \n\t"
351        " mfc0 %0, $29 \n\t"
352        " dmfc0 $1, $28 \n\t"
353        " dsrl32 %1, $1, 0 \n\t"
354        " sll %2, $1, 0 \n\t"
355        " .set pop"
356        : "=r" (taghi), "=r" (taglohi), "=r" (taglolo)
357        : "r" ((way << 13) | addr));
358
359        taglo = ((unsigned long long)taglohi << 32) | taglolo;
360        if (way == 0) {
361            lru = (taghi >> 14) & 0xff;
362            printk("[Bank %d Set 0x%02x] LRU > %d %d %d %d > MRU\n",
363                    ((addr >> 5) & 0x3), /* bank */
364                    ((addr >> 7) & 0x3f), /* index */
365                    (lru & 0x3),
366                    ((lru >> 2) & 0x3),
367                    ((lru >> 4) & 0x3),
368                    ((lru >> 6) & 0x3));
369        }
370        va = (taglo & 0xC0000FFFFFFFE000ULL) | addr;
371        if ((taglo & (1 << 31)) && (((taglo >> 62) & 0x3) == 3))
372            va |= 0x3FFFF00000000000ULL;
373        valid = ((taghi >> 29) & 1);
374        if (valid) {
375            tlo_tmp = taglo & 0xfff3ff;
376            if (((taglo >> 10) & 1) ^ range_parity(tlo_tmp, 23, 0)) {
377                printk(" ** bad parity in VTag0/G/ASID\n");
378                res |= CP0_CERRI_TAG_PARITY;
379            }
380            if (((taglo >> 11) & 1) ^ range_parity(taglo, 63, 24)) {
381                printk(" ** bad parity in R/VTag1\n");
382                res |= CP0_CERRI_TAG_PARITY;
383            }
384        }
385        if (valid ^ ((taghi >> 27) & 1)) {
386            printk(" ** bad parity for valid bit\n");
387            res |= CP0_CERRI_TAG_PARITY;
388        }
389        printk(" %d [VA %016llx] [Vld? %d] raw tags: %08X-%016llX\n",
390                way, va, valid, taghi, taglo);
391
392        if (data) {
393            uint32_t datahi, insta, instb;
394            uint8_t predecode;
395            int offset;
396
397            /* (hit all banks and ways) */
398            for (offset = 0; offset < 4; offset++) {
399                /* Index-load-data-I */
400                __asm__ __volatile__ (
401                " .set push\n\t"
402                " .set noreorder\n\t"
403                " .set mips64\n\t"
404                " .set noat\n\t"
405                " cache 6, 0(%3) \n\t"
406                " mfc0 %0, $29, 1\n\t"
407                " dmfc0 $1, $28, 1\n\t"
408                " dsrl32 %1, $1, 0 \n\t"
409                " sll %2, $1, 0 \n\t"
410                " .set pop \n"
411                : "=r" (datahi), "=r" (insta), "=r" (instb)
412                : "r" ((way << 13) | addr | (offset << 3)));
413                predecode = (datahi >> 8) & 0xff;
414                if (((datahi >> 16) & 1) != (uint32_t)range_parity(predecode, 7, 0)) {
415                    printk(" ** bad parity in predecode\n");
416                    res |= CP0_CERRI_DATA_PARITY;
417                }
418                /* XXXKW should/could check predecode bits themselves */
419                if (((datahi >> 4) & 0xf) ^ inst_parity(insta)) {
420                    printk(" ** bad parity in instruction a\n");
421                    res |= CP0_CERRI_DATA_PARITY;
422                }
423                if ((datahi & 0xf) ^ inst_parity(instb)) {
424                    printk(" ** bad parity in instruction b\n");
425                    res |= CP0_CERRI_DATA_PARITY;
426                }
427                printk(" %05X-%08X%08X", datahi, insta, instb);
428            }
429            printk("\n");
430        }
431    }
432    return res;
433}
434
435/* Compute the ECC for a data doubleword */
436static uint8_t dc_ecc(uint64_t dword)
437{
438    uint64_t t;
439    uint32_t w;
440    uint8_t p;
441    int i;
442
443    p = 0;
444    for (i = 7; i >= 0; i--)
445    {
446        p <<= 1;
447        t = dword & mask_72_64[i];
448        w = (uint32_t)(t >> 32);
449        p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF]
450              ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]);
451        w = (uint32_t)(t & 0xFFFFFFFF);
452        p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF]
453              ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]);
454    }
455    return p;
456}
457
458struct dc_state {
459    unsigned char val;
460    char *name;
461};
462
463static struct dc_state dc_states[] = {
464    { 0x00, "INVALID" },
465    { 0x0f, "COH-SHD" },
466    { 0x13, "NCO-E-C" },
467    { 0x19, "NCO-E-D" },
468    { 0x16, "COH-E-C" },
469    { 0x1c, "COH-E-D" },
470    { 0xff, "*ERROR*" }
471};
472
473#define DC_TAG_VALID(state) \
474    (((state) == 0x0) || ((state) == 0xf) || ((state) == 0x13) || \
475     ((state) == 0x19) || ((state) == 0x16) || ((state) == 0x1c))
476
477static char *dc_state_str(unsigned char state)
478{
479    struct dc_state *dsc = dc_states;
480    while (dsc->val != 0xff) {
481        if (dsc->val == state)
482            break;
483        dsc++;
484    }
485    return dsc->name;
486}
487
488static uint32_t extract_dc(unsigned short addr, int data)
489{
490    int valid, way;
491    unsigned char state;
492    uint32_t taghi, taglolo, taglohi;
493    unsigned long long taglo, pa;
494    uint8_t ecc, lru;
495    int res = 0;
496
497    printk("Dcache index 0x%04x ", addr);
498    for (way = 0; way < 4; way++) {
499        __asm__ __volatile__ (
500        " .set push\n\t"
501        " .set noreorder\n\t"
502        " .set mips64\n\t"
503        " .set noat\n\t"
504        " cache 5, 0(%3)\n\t" /* Index-load-tag-D */
505        " mfc0 %0, $29, 2\n\t"
506        " dmfc0 $1, $28, 2\n\t"
507        " dsrl32 %1, $1, 0\n\t"
508        " sll %2, $1, 0\n\t"
509        " .set pop"
510        : "=r" (taghi), "=r" (taglohi), "=r" (taglolo)
511        : "r" ((way << 13) | addr));
512
513        taglo = ((unsigned long long)taglohi << 32) | taglolo;
514        pa = (taglo & 0xFFFFFFE000ULL) | addr;
515        if (way == 0) {
516            lru = (taghi >> 14) & 0xff;
517            printk("[Bank %d Set 0x%02x] LRU > %d %d %d %d > MRU\n",
518                    ((addr >> 11) & 0x2) | ((addr >> 5) & 1), /* bank */
519                    ((addr >> 6) & 0x3f), /* index */
520                    (lru & 0x3),
521                    ((lru >> 2) & 0x3),
522                    ((lru >> 4) & 0x3),
523                    ((lru >> 6) & 0x3));
524        }
525        state = (taghi >> 25) & 0x1f;
526        valid = DC_TAG_VALID(state);
527        printk(" %d [PA %010llx] [state %s (%02x)] raw tags: %08X-%016llX\n",
528                way, pa, dc_state_str(state), state, taghi, taglo);
529        if (valid) {
530            if (((taglo >> 11) & 1) ^ range_parity(taglo, 39, 26)) {
531                printk(" ** bad parity in PTag1\n");
532                res |= CP0_CERRD_TAG_ADDRESS;
533            }
534            if (((taglo >> 10) & 1) ^ range_parity(taglo, 25, 13)) {
535                printk(" ** bad parity in PTag0\n");
536                res |= CP0_CERRD_TAG_ADDRESS;
537            }
538        } else {
539            res |= CP0_CERRD_TAG_STATE;
540        }
541
542        if (data) {
543            uint32_t datalohi, datalolo, datahi;
544            unsigned long long datalo;
545            int offset;
546            char bad_ecc = 0;
547
548            for (offset = 0; offset < 4; offset++) {
549                /* Index-load-data-D */
550                __asm__ __volatile__ (
551                " .set push\n\t"
552                " .set noreorder\n\t"
553                " .set mips64\n\t"
554                " .set noat\n\t"
555                " cache 7, 0(%3)\n\t" /* Index-load-data-D */
556                " mfc0 %0, $29, 3\n\t"
557                " dmfc0 $1, $28, 3\n\t"
558                " dsrl32 %1, $1, 0 \n\t"
559                " sll %2, $1, 0 \n\t"
560                " .set pop"
561                : "=r" (datahi), "=r" (datalohi), "=r" (datalolo)
562                : "r" ((way << 13) | addr | (offset << 3)));
563                datalo = ((unsigned long long)datalohi << 32) | datalolo;
564                ecc = dc_ecc(datalo);
565                if (ecc != datahi) {
566                    int bits;
567                    bad_ecc |= 1 << (3-offset);
568                    ecc ^= datahi;
569                    bits = hweight8(ecc);
570                    res |= (bits == 1) ? CP0_CERRD_DATA_SBE : CP0_CERRD_DATA_DBE;
571                }
572                printk(" %02X-%016llX", datahi, datalo);
573            }
574            printk("\n");
575            if (bad_ecc)
576                printk(" dwords w/ bad ECC: %d %d %d %d\n",
577                       !!(bad_ecc & 8), !!(bad_ecc & 4),
578                       !!(bad_ecc & 2), !!(bad_ecc & 1));
579        }
580    }
581    return res;
582}
583

Archive Download this file



interactive