MIPS: c-r4k: Fix sigtramp SMP call to use kmap
[deliverable/linux.git] / arch / mips / mm / cerr-sb1.c
CommitLineData
1da177e4
LT
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 */
1da177e4
LT
18#include <linux/sched.h>
19#include <asm/mipsregs.h>
20#include <asm/sibyte/sb1250.h>
a4b5bd9a 21#include <asm/sibyte/sb1250_regs.h>
1da177e4 22
a4b5bd9a 23#if !defined(CONFIG_SIBYTE_BUS_WATCHER) || defined(CONFIG_SIBYTE_BW_TRACE)
1da177e4 24#include <asm/io.h>
1da177e4
LT
25#include <asm/sibyte/sb1250_scd.h>
26#endif
42a3b4f2 27
a4b5bd9a
AI
28/*
29 * We'd like to dump the L2_ECC_TAG register on errors, but errata make
70342287 30 * that unsafe... So for now we don't. (BCM1250/BCM112x erratum SOC-48.)
a4b5bd9a
AI
31 */
32#undef DUMP_L2_ECC_TAG_ON_ERROR
33
1da177e4
LT
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))
70342287 51#define CP0_CERRI_DATA (CP0_CERRI_DATA_PARITY)
1da177e4
LT
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)
70342287
RB
59#define CP0_CERRD_LOAD (1 << 25)
60#define CP0_CERRD_STORE (1 << 24)
1da177e4
LT
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)
70342287 72#define CP0_CERRD_DATA (CP0_CERRD_DATA_SBE | CP0_CERRD_DATA_DBE)
1da177e4 73
70342287
RB
74static uint32_t extract_ic(unsigned short addr, int data);
75static uint32_t extract_dc(unsigned short addr, int data);
1da177e4
LT
76
77static inline void breakout_errctl(unsigned int val)
78{
79 if (val & CP0_ERRCTL_RECOVERABLE)
36a88530 80 printk(" recoverable");
1da177e4 81 if (val & CP0_ERRCTL_DCACHE)
36a88530 82 printk(" dcache");
1da177e4 83 if (val & CP0_ERRCTL_ICACHE)
36a88530 84 printk(" icache");
1da177e4 85 if (val & CP0_ERRCTL_MULTIBUS)
36a88530
RB
86 printk(" multiple-buserr");
87 printk("\n");
1da177e4
LT
88}
89
90static inline void breakout_cerri(unsigned int val)
91{
92 if (val & CP0_CERRI_TAG_PARITY)
36a88530 93 printk(" tag-parity");
1da177e4 94 if (val & CP0_CERRI_DATA_PARITY)
36a88530 95 printk(" data-parity");
1da177e4 96 if (val & CP0_CERRI_EXTERNAL)
36a88530
RB
97 printk(" external");
98 printk("\n");
1da177e4
LT
99}
100
101static inline void breakout_cerrd(unsigned int val)
102{
103 switch (val & CP0_CERRD_CAUSES) {
104 case CP0_CERRD_LOAD:
36a88530 105 printk(" load,");
1da177e4
LT
106 break;
107 case CP0_CERRD_STORE:
36a88530 108 printk(" store,");
1da177e4
LT
109 break;
110 case CP0_CERRD_FILLWB:
36a88530 111 printk(" fill/wb,");
1da177e4
LT
112 break;
113 case CP0_CERRD_COHERENCY:
36a88530 114 printk(" coherency,");
1da177e4
LT
115 break;
116 case CP0_CERRD_DUPTAG:
36a88530 117 printk(" duptags,");
1da177e4
LT
118 break;
119 default:
36a88530 120 printk(" NO CAUSE,");
1da177e4
LT
121 break;
122 }
123 if (!(val & CP0_CERRD_TYPES))
36a88530 124 printk(" NO TYPE");
1da177e4
LT
125 else {
126 if (val & CP0_CERRD_MULTIPLE)
36a88530 127 printk(" multi-err");
1da177e4 128 if (val & CP0_CERRD_TAG_STATE)
36a88530 129 printk(" tag-state");
1da177e4 130 if (val & CP0_CERRD_TAG_ADDRESS)
36a88530 131 printk(" tag-address");
1da177e4 132 if (val & CP0_CERRD_DATA_SBE)
36a88530 133 printk(" data-SBE");
1da177e4 134 if (val & CP0_CERRD_DATA_DBE)
36a88530 135 printk(" data-DBE");
1da177e4 136 if (val & CP0_CERRD_EXTERNAL)
36a88530 137 printk(" external");
1da177e4 138 }
36a88530 139 printk("\n");
1da177e4
LT
140}
141
142#ifndef CONFIG_SIBYTE_BUS_WATCHER
143
42a3b4f2
RB
144static void check_bus_watcher(void)
145{
1da177e4 146 uint32_t status, l2_err, memio_err;
a4b5bd9a
AI
147#ifdef DUMP_L2_ECC_TAG_ON_ERROR
148 uint64_t l2_tag;
149#endif
1da177e4
LT
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 */
42a3b4f2 154 if (status & ~(1UL << 31)) {
1da177e4 155 l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS));
a4b5bd9a 156#ifdef DUMP_L2_ECC_TAG_ON_ERROR
33b75e5c 157 l2_tag = in64(IOADDR(A_L2_ECC_TAG));
a4b5bd9a 158#endif
1da177e4 159 memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS));
36a88530
RB
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",
1da177e4
LT
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));
a4b5bd9a 167#ifdef DUMP_L2_ECC_TAG_ON_ERROR
36a88530 168 printk("Last L2 tag w/ bad ECC: %016llx\n", l2_tag);
a4b5bd9a 169#endif
42a3b4f2 170 } else {
36a88530 171 printk("Bus watcher indicates no error\n");
42a3b4f2
RB
172 }
173}
174#else
175extern void check_bus_watcher(void);
176#endif
177
1da177e4
LT
178asmlinkage void sb1_cache_error(void)
179{
1da177e4 180 uint32_t errctl, cerr_i, cerr_d, dpalo, dpahi, eepc, res;
41a8198f 181 unsigned long long cerr_dpa;
1da177e4 182
a4b5bd9a
AI
183#ifdef CONFIG_SIBYTE_BW_TRACE
184 /* Freeze the trace buffer now */
33b75e5c 185 csr_out32(M_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG));
36a88530 186 printk("Trace buffer frozen\n");
a4b5bd9a
AI
187#endif
188
36a88530
RB
189 printk("Cache error exception on CPU %x:\n",
190 (read_c0_prid() >> 25) & 0x7);
1da177e4
LT
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;
70342287
RB
208 printk(" c0_errorepc == %08x\n", eepc);
209 printk(" c0_errctl == %08x", errctl);
1da177e4
LT
210 breakout_errctl(errctl);
211 if (errctl & CP0_ERRCTL_ICACHE) {
70342287 212 printk(" c0_cerr_i == %08x", cerr_i);
1da177e4
LT
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)))
36a88530 218 printk(" cerr_i idx doesn't match eepc\n");
1da177e4
LT
219 else {
220 res = extract_ic(cerr_i & SB1_CACHE_INDEX_MASK,
221 (cerr_i & CP0_CERRI_DATA) != 0);
222 if (!(res & cerr_i))
36a88530 223 printk("...didn't see indicated icache problem\n");
1da177e4
LT
224 }
225 }
226 }
227 if (errctl & CP0_ERRCTL_DCACHE) {
70342287 228 printk(" c0_cerr_d == %08x", cerr_d);
1da177e4
LT
229 breakout_cerrd(cerr_d);
230 if (CP0_CERRD_DPA_VALID(cerr_d)) {
36a88530 231 printk(" c0_cerr_dpa == %010llx\n", cerr_dpa);
1da177e4
LT
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))
36a88530 236 printk("...didn't see indicated dcache problem\n");
1da177e4
LT
237 } else {
238 if ((cerr_dpa & SB1_CACHE_INDEX_MASK) != (cerr_d & SB1_CACHE_INDEX_MASK))
36a88530 239 printk(" cerr_d idx doesn't match cerr_dpa\n");
1da177e4
LT
240 else {
241 res = extract_dc(cerr_d & SB1_CACHE_INDEX_MASK,
242 (cerr_d & CP0_CERRD_DATA) != 0);
243 if (!(res & cerr_d))
36a88530 244 printk("...didn't see indicated problem\n");
1da177e4
LT
245 }
246 }
247 }
248 }
249
250 check_bus_watcher();
251
1da177e4 252 /*
a4b5bd9a
AI
253 * Calling panic() when a fatal cache error occurs scrambles the
254 * state of the system (and the cache), making it difficult to
70342287 255 * investigate after the fact. However, if you just stall the CPU,
a4b5bd9a
AI
256 * the other CPU may keep on running, which is typically very
257 * undesirable.
1da177e4 258 */
a4b5bd9a
AI
259#ifdef CONFIG_SB1_CERR_STALL
260 while (1)
261 ;
262#else
263 panic("unhandled cache error");
264#endif
1da177e4
LT
265}
266
267
268/* Parity lookup table. */
269static const uint8_t parity[256] = {
21a151d8
RB
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
1da177e4
LT
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;
1da177e4 336 uint32_t taghi, taglolo, taglohi;
41a8198f
RB
337 unsigned long long taglo, va;
338 uint64_t tlo_tmp;
1da177e4
LT
339 uint8_t lru;
340 int res = 0;
341
36a88530 342 printk("Icache index 0x%04x ", addr);
1da177e4
LT
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;
36a88530 362 printk("[Bank %d Set 0x%02x] LRU > %d %d %d %d > MRU\n",
1da177e4
LT
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)) {
36a88530 377 printk(" ** bad parity in VTag0/G/ASID\n");
1da177e4
LT
378 res |= CP0_CERRI_TAG_PARITY;
379 }
380 if (((taglo >> 11) & 1) ^ range_parity(taglo, 63, 24)) {
36a88530 381 printk(" ** bad parity in R/VTag1\n");
1da177e4
LT
382 res |= CP0_CERRI_TAG_PARITY;
383 }
384 }
385 if (valid ^ ((taghi >> 27) & 1)) {
36a88530 386 printk(" ** bad parity for valid bit\n");
1da177e4
LT
387 res |= CP0_CERRI_TAG_PARITY;
388 }
36a88530 389 printk(" %d [VA %016llx] [Vld? %d] raw tags: %08X-%016llX\n",
1da177e4
LT
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"
70342287 410 " .set pop \n"
1da177e4
LT
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)) {
36a88530 415 printk(" ** bad parity in predecode\n");
1da177e4
LT
416 res |= CP0_CERRI_DATA_PARITY;
417 }
418 /* XXXKW should/could check predecode bits themselves */
419 if (((datahi >> 4) & 0xf) ^ inst_parity(insta)) {
36a88530 420 printk(" ** bad parity in instruction a\n");
1da177e4
LT
421 res |= CP0_CERRI_DATA_PARITY;
422 }
423 if ((datahi & 0xf) ^ inst_parity(instb)) {
36a88530 424 printk(" ** bad parity in instruction b\n");
1da177e4
LT
425 res |= CP0_CERRI_DATA_PARITY;
426 }
36a88530 427 printk(" %05X-%08X%08X", datahi, insta, instb);
1da177e4 428 }
36a88530 429 printk("\n");
1da177e4
LT
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;
70342287
RB
440 uint8_t p;
441 int i;
1da177e4
LT
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) \
a4b5bd9a
AI
474 (((state) == 0x0) || ((state) == 0xf) || ((state) == 0x13) || \
475 ((state) == 0x19) || ((state) == 0x16) || ((state) == 0x1c))
1da177e4
LT
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;
1da177e4 492 uint32_t taghi, taglolo, taglohi;
41a8198f 493 unsigned long long taglo, pa;
1da177e4
LT
494 uint8_t ecc, lru;
495 int res = 0;
496
36a88530 497 printk("Dcache index 0x%04x ", addr);
1da177e4
LT
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;
36a88530 517 printk("[Bank %d Set 0x%02x] LRU > %d %d %d %d > MRU\n",
1da177e4
LT
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);
36a88530 527 printk(" %d [PA %010llx] [state %s (%02x)] raw tags: %08X-%016llX\n",
1da177e4
LT
528 way, pa, dc_state_str(state), state, taghi, taglo);
529 if (valid) {
530 if (((taglo >> 11) & 1) ^ range_parity(taglo, 39, 26)) {
36a88530 531 printk(" ** bad parity in PTag1\n");
1da177e4
LT
532 res |= CP0_CERRD_TAG_ADDRESS;
533 }
534 if (((taglo >> 10) & 1) ^ range_parity(taglo, 25, 13)) {
36a88530 535 printk(" ** bad parity in PTag0\n");
1da177e4
LT
536 res |= CP0_CERRD_TAG_ADDRESS;
537 }
538 } else {
539 res |= CP0_CERRD_TAG_STATE;
540 }
541
542 if (data) {
1da177e4 543 uint32_t datalohi, datalolo, datahi;
41a8198f 544 unsigned long long datalo;
1da177e4 545 int offset;
a4b5bd9a 546 char bad_ecc = 0;
1da177e4
LT
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) {
13e79b46 566 int bits;
a4b5bd9a 567 bad_ecc |= 1 << (3-offset);
1da177e4 568 ecc ^= datahi;
13e79b46 569 bits = hweight8(ecc);
1da177e4
LT
570 res |= (bits == 1) ? CP0_CERRD_DATA_SBE : CP0_CERRD_DATA_DBE;
571 }
36a88530 572 printk(" %02X-%016llX", datahi, datalo);
1da177e4 573 }
36a88530 574 printk("\n");
a4b5bd9a 575 if (bad_ecc)
36a88530
RB
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));
1da177e4
LT
579 }
580 }
581 return res;
582}
This page took 0.797771 seconds and 5 git commands to generate.