This source file includes following definitions.
- save_cache_tags
- save_and_clear_buserr
- print_cache_tags
- cause_excode_text
- print_buserr
- check_microtlb
- check_vdma_memaddr
- check_vdma_gioaddr
- ip28_be_interrupt
- ip22_be_interrupt
- ip28_be_handler
- ip22_be_init
- ip28_show_be_info
- debug_be_setup
1
2
3
4
5
6
7
8
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11 #include <linux/mm.h>
12 #include <linux/sched.h>
13 #include <linux/sched/debug.h>
14 #include <linux/sched/signal.h>
15 #include <linux/seq_file.h>
16
17 #include <asm/addrspace.h>
18 #include <asm/traps.h>
19 #include <asm/branch.h>
20 #include <asm/irq_regs.h>
21 #include <asm/sgi/mc.h>
22 #include <asm/sgi/hpc3.h>
23 #include <asm/sgi/ioc.h>
24 #include <asm/sgi/ip22.h>
25 #include <asm/r4kcache.h>
26 #include <linux/uaccess.h>
27 #include <asm/bootinfo.h>
28
29 static unsigned int count_be_is_fixup;
30 static unsigned int count_be_handler;
31 static unsigned int count_be_interrupt;
32 static int debug_be_interrupt;
33
34 static unsigned int cpu_err_stat;
35 static unsigned int gio_err_stat;
36 static unsigned int cpu_err_addr;
37 static unsigned int gio_err_addr;
38 static unsigned int extio_stat;
39 static unsigned int hpc3_berr_stat;
40
41 struct hpc3_stat {
42 unsigned long addr;
43 unsigned int ctrl;
44 unsigned int cbp;
45 unsigned int ndptr;
46 };
47
48 static struct {
49 struct hpc3_stat pbdma[8];
50 struct hpc3_stat scsi[2];
51 struct hpc3_stat ethrx, ethtx;
52 } hpc3;
53
54 static struct {
55 unsigned long err_addr;
56 struct {
57 u32 lo;
58 u32 hi;
59 } tags[1][2], tagd[4][2], tagi[4][2];
60 } cache_tags;
61
62 static inline void save_cache_tags(unsigned busaddr)
63 {
64 unsigned long addr = CAC_BASE | busaddr;
65 int i;
66 cache_tags.err_addr = addr;
67
68
69
70
71
72 addr &= ~1L;
73 #define tag cache_tags.tags[0]
74 cache_op(Index_Load_Tag_S, addr);
75 tag[0].lo = read_c0_taglo();
76 tag[0].hi = read_c0_taghi();
77 cache_op(Index_Load_Tag_S, addr | 1L);
78 tag[1].lo = read_c0_taglo();
79 tag[1].hi = read_c0_taghi();
80 #undef tag
81
82
83
84
85
86
87
88
89 addr &= (0xffL << 56) | ((1 << 12) - 1);
90 #define tag cache_tags.tagd[i]
91 for (i = 0; i < 4; ++i, addr += (1 << 12)) {
92 cache_op(Index_Load_Tag_D, addr);
93 tag[0].lo = read_c0_taglo();
94 tag[0].hi = read_c0_taghi();
95 cache_op(Index_Load_Tag_D, addr | 1L);
96 tag[1].lo = read_c0_taglo();
97 tag[1].hi = read_c0_taghi();
98 }
99 #undef tag
100
101
102
103
104
105 addr &= (0xffL << 56) | ((1 << 12) - 1);
106 #define tag cache_tags.tagi[i]
107 for (i = 0; i < 4; ++i, addr += (1 << 12)) {
108 cache_op(Index_Load_Tag_I, addr);
109 tag[0].lo = read_c0_taglo();
110 tag[0].hi = read_c0_taghi();
111 cache_op(Index_Load_Tag_I, addr | 1L);
112 tag[1].lo = read_c0_taglo();
113 tag[1].hi = read_c0_taghi();
114 }
115 #undef tag
116 }
117
118 #define GIO_ERRMASK 0xff00
119 #define CPU_ERRMASK 0x3f00
120
121 static void save_and_clear_buserr(void)
122 {
123 int i;
124
125
126 cpu_err_addr = sgimc->cerr;
127 cpu_err_stat = sgimc->cstat;
128 gio_err_addr = sgimc->gerr;
129 gio_err_stat = sgimc->gstat;
130 extio_stat = sgioc->extio;
131 hpc3_berr_stat = hpc3c0->bestat;
132
133 hpc3.scsi[0].addr = (unsigned long)&hpc3c0->scsi_chan0;
134 hpc3.scsi[0].ctrl = hpc3c0->scsi_chan0.ctrl;
135 hpc3.scsi[0].cbp = hpc3c0->scsi_chan0.cbptr;
136 hpc3.scsi[0].ndptr = hpc3c0->scsi_chan0.ndptr;
137
138 hpc3.scsi[1].addr = (unsigned long)&hpc3c0->scsi_chan1;
139 hpc3.scsi[1].ctrl = hpc3c0->scsi_chan1.ctrl;
140 hpc3.scsi[1].cbp = hpc3c0->scsi_chan1.cbptr;
141 hpc3.scsi[1].ndptr = hpc3c0->scsi_chan1.ndptr;
142
143 hpc3.ethrx.addr = (unsigned long)&hpc3c0->ethregs.rx_cbptr;
144 hpc3.ethrx.ctrl = hpc3c0->ethregs.rx_ctrl;
145 hpc3.ethrx.cbp = hpc3c0->ethregs.rx_cbptr;
146 hpc3.ethrx.ndptr = hpc3c0->ethregs.rx_ndptr;
147
148 hpc3.ethtx.addr = (unsigned long)&hpc3c0->ethregs.tx_cbptr;
149 hpc3.ethtx.ctrl = hpc3c0->ethregs.tx_ctrl;
150 hpc3.ethtx.cbp = hpc3c0->ethregs.tx_cbptr;
151 hpc3.ethtx.ndptr = hpc3c0->ethregs.tx_ndptr;
152
153 for (i = 0; i < 8; ++i) {
154
155 hpc3.pbdma[i].addr = (unsigned long)&hpc3c0->pbdma[i];
156 hpc3.pbdma[i].ctrl = hpc3c0->pbdma[i].pbdma_ctrl;
157 hpc3.pbdma[i].cbp = hpc3c0->pbdma[i].pbdma_bptr;
158 hpc3.pbdma[i].ndptr = hpc3c0->pbdma[i].pbdma_dptr;
159 }
160 i = 0;
161 if (gio_err_stat & CPU_ERRMASK)
162 i = gio_err_addr;
163 if (cpu_err_stat & CPU_ERRMASK)
164 i = cpu_err_addr;
165 save_cache_tags(i);
166
167 sgimc->cstat = sgimc->gstat = 0;
168 }
169
170 static void print_cache_tags(void)
171 {
172 u32 scb, scw;
173 int i;
174
175 printk(KERN_ERR "Cache tags @ %08x:\n", (unsigned)cache_tags.err_addr);
176
177
178 scw = (cache_tags.err_addr >> 4) & 0x0fffff00;
179
180 scb = cache_tags.err_addr & ((1 << 12) - 1) & ~((1 << 5) - 1);
181 for (i = 0; i < 4; ++i) {
182 if ((cache_tags.tagd[i][0].lo & 0x0fffff00) != scw &&
183 (cache_tags.tagd[i][1].lo & 0x0fffff00) != scw)
184 continue;
185 printk(KERN_ERR
186 "D: 0: %08x %08x, 1: %08x %08x (VA[13:5] %04x)\n",
187 cache_tags.tagd[i][0].hi, cache_tags.tagd[i][0].lo,
188 cache_tags.tagd[i][1].hi, cache_tags.tagd[i][1].lo,
189 scb | (1 << 12)*i);
190 }
191 scb = cache_tags.err_addr & ((1 << 12) - 1) & ~((1 << 6) - 1);
192 for (i = 0; i < 4; ++i) {
193 if ((cache_tags.tagi[i][0].lo & 0x0fffff00) != scw &&
194 (cache_tags.tagi[i][1].lo & 0x0fffff00) != scw)
195 continue;
196 printk(KERN_ERR
197 "I: 0: %08x %08x, 1: %08x %08x (VA[13:6] %04x)\n",
198 cache_tags.tagi[i][0].hi, cache_tags.tagi[i][0].lo,
199 cache_tags.tagi[i][1].hi, cache_tags.tagi[i][1].lo,
200 scb | (1 << 12)*i);
201 }
202 i = read_c0_config();
203 scb = i & (1 << 13) ? 7:6;
204 scw = ((i >> 16) & 7) + 19 - 1;
205
206 i = ((1 << scw) - 1) & ~((1 << scb) - 1);
207 printk(KERN_ERR "S: 0: %08x %08x, 1: %08x %08x (PA[%u:%u] %05x)\n",
208 cache_tags.tags[0][0].hi, cache_tags.tags[0][0].lo,
209 cache_tags.tags[0][1].hi, cache_tags.tags[0][1].lo,
210 scw-1, scb, i & (unsigned)cache_tags.err_addr);
211 }
212
213 static inline const char *cause_excode_text(int cause)
214 {
215 static const char *txt[32] =
216 { "Interrupt",
217 "TLB modification",
218 "TLB (load or instruction fetch)",
219 "TLB (store)",
220 "Address error (load or instruction fetch)",
221 "Address error (store)",
222 "Bus error (instruction fetch)",
223 "Bus error (data: load or store)",
224 "Syscall",
225 "Breakpoint",
226 "Reserved instruction",
227 "Coprocessor unusable",
228 "Arithmetic Overflow",
229 "Trap",
230 "14",
231 "Floating-Point",
232 "16", "17", "18", "19", "20", "21", "22",
233 "Watch Hi/Lo",
234 "24", "25", "26", "27", "28", "29", "30", "31",
235 };
236 return txt[(cause & 0x7c) >> 2];
237 }
238
239 static void print_buserr(const struct pt_regs *regs)
240 {
241 const int field = 2 * sizeof(unsigned long);
242 int error = 0;
243
244 if (extio_stat & EXTIO_MC_BUSERR) {
245 printk(KERN_ERR "MC Bus Error\n");
246 error |= 1;
247 }
248 if (extio_stat & EXTIO_HPC3_BUSERR) {
249 printk(KERN_ERR "HPC3 Bus Error 0x%x:<id=0x%x,%s,lane=0x%x>\n",
250 hpc3_berr_stat,
251 (hpc3_berr_stat & HPC3_BESTAT_PIDMASK) >>
252 HPC3_BESTAT_PIDSHIFT,
253 (hpc3_berr_stat & HPC3_BESTAT_CTYPE) ? "PIO" : "DMA",
254 hpc3_berr_stat & HPC3_BESTAT_BLMASK);
255 error |= 2;
256 }
257 if (extio_stat & EXTIO_EISA_BUSERR) {
258 printk(KERN_ERR "EISA Bus Error\n");
259 error |= 4;
260 }
261 if (cpu_err_stat & CPU_ERRMASK) {
262 printk(KERN_ERR "CPU error 0x%x<%s%s%s%s%s%s> @ 0x%08x\n",
263 cpu_err_stat,
264 cpu_err_stat & SGIMC_CSTAT_RD ? "RD " : "",
265 cpu_err_stat & SGIMC_CSTAT_PAR ? "PAR " : "",
266 cpu_err_stat & SGIMC_CSTAT_ADDR ? "ADDR " : "",
267 cpu_err_stat & SGIMC_CSTAT_SYSAD_PAR ? "SYSAD " : "",
268 cpu_err_stat & SGIMC_CSTAT_SYSCMD_PAR ? "SYSCMD " : "",
269 cpu_err_stat & SGIMC_CSTAT_BAD_DATA ? "BAD_DATA " : "",
270 cpu_err_addr);
271 error |= 8;
272 }
273 if (gio_err_stat & GIO_ERRMASK) {
274 printk(KERN_ERR "GIO error 0x%x:<%s%s%s%s%s%s%s%s> @ 0x%08x\n",
275 gio_err_stat,
276 gio_err_stat & SGIMC_GSTAT_RD ? "RD " : "",
277 gio_err_stat & SGIMC_GSTAT_WR ? "WR " : "",
278 gio_err_stat & SGIMC_GSTAT_TIME ? "TIME " : "",
279 gio_err_stat & SGIMC_GSTAT_PROM ? "PROM " : "",
280 gio_err_stat & SGIMC_GSTAT_ADDR ? "ADDR " : "",
281 gio_err_stat & SGIMC_GSTAT_BC ? "BC " : "",
282 gio_err_stat & SGIMC_GSTAT_PIO_RD ? "PIO_RD " : "",
283 gio_err_stat & SGIMC_GSTAT_PIO_WR ? "PIO_WR " : "",
284 gio_err_addr);
285 error |= 16;
286 }
287 if (!error)
288 printk(KERN_ERR "MC: Hmm, didn't find any error condition.\n");
289 else {
290 printk(KERN_ERR "CP0: config %08x, "
291 "MC: cpuctrl0/1: %08x/%05x, giopar: %04x\n"
292 "MC: cpu/gio_memacc: %08x/%05x, memcfg0/1: %08x/%08x\n",
293 read_c0_config(),
294 sgimc->cpuctrl0, sgimc->cpuctrl0, sgimc->giopar,
295 sgimc->cmacc, sgimc->gmacc,
296 sgimc->mconfig0, sgimc->mconfig1);
297 print_cache_tags();
298 }
299 printk(KERN_ALERT "%s, epc == %0*lx, ra == %0*lx\n",
300 cause_excode_text(regs->cp0_cause),
301 field, regs->cp0_epc, field, regs->regs[31]);
302 }
303
304 static int check_microtlb(u32 hi, u32 lo, unsigned long vaddr)
305 {
306
307
308 vaddr &= 0x7fffffff;
309
310
311 if ((lo & 2) && (vaddr >> 21) == ((hi<<1) >> 22)) {
312 u32 ctl = sgimc->dma_ctrl;
313 if (ctl & 1) {
314 unsigned int pgsz = (ctl & 2) ? 14:12;
315
316 unsigned long pte = (lo >> 6) << 12;
317 pte += 8*((vaddr >> pgsz) & 0x1ff);
318 if (page_is_ram(PFN_DOWN(pte))) {
319
320
321
322
323
324 unsigned long a = *(unsigned long *)
325 PHYS_TO_XKSEG_UNCACHED(pte);
326 a = (a & 0x3f) << 6;
327 a += vaddr & ((1 << pgsz) - 1);
328 return cpu_err_addr == a;
329 }
330 }
331 }
332 return 0;
333 }
334
335 static int check_vdma_memaddr(void)
336 {
337 if (cpu_err_stat & CPU_ERRMASK) {
338 u32 a = sgimc->maddronly;
339
340 if (!(sgimc->dma_ctrl & 0x100))
341 return cpu_err_addr == a;
342
343 if (check_microtlb(sgimc->dtlb_hi0, sgimc->dtlb_lo0, a) ||
344 check_microtlb(sgimc->dtlb_hi1, sgimc->dtlb_lo1, a) ||
345 check_microtlb(sgimc->dtlb_hi2, sgimc->dtlb_lo2, a) ||
346 check_microtlb(sgimc->dtlb_hi3, sgimc->dtlb_lo3, a))
347 return 1;
348 }
349 return 0;
350 }
351
352 static int check_vdma_gioaddr(void)
353 {
354 if (gio_err_stat & GIO_ERRMASK) {
355 u32 a = sgimc->gio_dma_trans;
356 a = (sgimc->gmaddronly & ~a) | (sgimc->gio_dma_sbits & a);
357 return gio_err_addr == a;
358 }
359 return 0;
360 }
361
362
363
364
365
366
367
368
369 static int ip28_be_interrupt(const struct pt_regs *regs)
370 {
371 int i;
372
373 save_and_clear_buserr();
374
375
376
377
378
379 if (regs->cp0_cause & CAUSEF_EXCCODE)
380 goto mips_be_fatal;
381
382
383 if ((regs->cp0_cause & CAUSEF_IP6) != CAUSEF_IP6)
384 goto mips_be_fatal;
385
386 if (extio_stat & (EXTIO_HPC3_BUSERR | EXTIO_EISA_BUSERR))
387 goto mips_be_fatal;
388
389
390 if (cpu_err_stat & CPU_ERRMASK & ~SGIMC_CSTAT_ADDR)
391 goto mips_be_fatal;
392
393
394 if (gio_err_stat & GIO_ERRMASK & ~SGIMC_GSTAT_TIME)
395 goto mips_be_fatal;
396
397
398
399
400
401 for (i = 0; i < sizeof(hpc3)/sizeof(struct hpc3_stat); ++i) {
402 struct hpc3_stat *hp = (struct hpc3_stat *)&hpc3 + i;
403 if ((cpu_err_stat & CPU_ERRMASK) &&
404 (cpu_err_addr == hp->ndptr || cpu_err_addr == hp->cbp))
405 break;
406 if ((gio_err_stat & GIO_ERRMASK) &&
407 (gio_err_addr == hp->ndptr || gio_err_addr == hp->cbp))
408 break;
409 }
410 if (i < sizeof(hpc3)/sizeof(struct hpc3_stat)) {
411 struct hpc3_stat *hp = (struct hpc3_stat *)&hpc3 + i;
412 printk(KERN_ERR "at DMA addresses: HPC3 @ %08lx:"
413 " ctl %08x, ndp %08x, cbp %08x\n",
414 CPHYSADDR(hp->addr), hp->ctrl, hp->ndptr, hp->cbp);
415 goto mips_be_fatal;
416 }
417
418 if (check_vdma_memaddr()) {
419 printk(KERN_ERR "at GIO DMA: mem address 0x%08x.\n",
420 sgimc->maddronly);
421 goto mips_be_fatal;
422 }
423 if (check_vdma_gioaddr()) {
424 printk(KERN_ERR "at GIO DMA: gio address 0x%08x.\n",
425 sgimc->gmaddronly);
426 goto mips_be_fatal;
427 }
428
429 if (debug_be_interrupt) {
430 print_buserr(regs);
431 printk(KERN_ERR "discarded!\n");
432 }
433 return MIPS_BE_DISCARD;
434
435 mips_be_fatal:
436 print_buserr(regs);
437 return MIPS_BE_FATAL;
438 }
439
440 void ip22_be_interrupt(int irq)
441 {
442 struct pt_regs *regs = get_irq_regs();
443
444 count_be_interrupt++;
445
446 if (ip28_be_interrupt(regs) != MIPS_BE_DISCARD) {
447
448 die_if_kernel("Oops", regs);
449 force_sig(SIGBUS);
450 } else if (debug_be_interrupt)
451 show_regs(regs);
452 }
453
454 static int ip28_be_handler(struct pt_regs *regs, int is_fixup)
455 {
456
457
458
459
460 if (is_fixup) {
461 count_be_is_fixup++;
462 save_and_clear_buserr();
463 return MIPS_BE_FIXUP;
464 }
465 count_be_handler++;
466 return ip28_be_interrupt(regs);
467 }
468
469 void __init ip22_be_init(void)
470 {
471 board_be_handler = ip28_be_handler;
472 }
473
474 int ip28_show_be_info(struct seq_file *m)
475 {
476 seq_printf(m, "IP28 be fixups\t\t: %u\n", count_be_is_fixup);
477 seq_printf(m, "IP28 be interrupts\t: %u\n", count_be_interrupt);
478 seq_printf(m, "IP28 be handler\t\t: %u\n", count_be_handler);
479
480 return 0;
481 }
482
483 static int __init debug_be_setup(char *str)
484 {
485 debug_be_interrupt++;
486 return 1;
487 }
488 __setup("ip28_debug_be", debug_be_setup);