Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/sgi-ip22/ip28-berr.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* ip28-berr.c: Bus error handling.
4
*
5
* Copyright (C) 2002, 2003 Ladislav Michl ([email protected])
6
* Copyright (C) 2005 Peter Fuerst ([email protected]) - IP28
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; /* Status reg for CPU */
35
static unsigned int gio_err_stat; /* Status reg for GIO */
36
static unsigned int cpu_err_addr; /* Error address reg for CPU */
37
static unsigned int gio_err_addr; /* Error address reg for GIO */
38
static unsigned int extio_stat;
39
static unsigned int hpc3_berr_stat; /* Bus error interrupt status */
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]; /* Way 0/1 */
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
* Starting with a bus-address, save secondary cache (indexed by
70
* PA[23..18:7..6]) tags first.
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(); /* PA[35:18], VA[13:12] */
76
tag[0].hi = read_c0_taghi(); /* PA[39:36] */
77
cache_op(Index_Load_Tag_S, addr | 1L);
78
tag[1].lo = read_c0_taglo(); /* PA[35:18], VA[13:12] */
79
tag[1].hi = read_c0_taghi(); /* PA[39:36] */
80
#undef tag
81
82
/*
83
* Save all primary data cache (indexed by VA[13:5]) tags which
84
* might fit to this bus-address, knowing that VA[11:0] == PA[11:0].
85
* Saving all tags and evaluating them later is easier and safer
86
* than relying on VA[13:12] from the secondary cache tags to pick
87
* matching primary tags here already.
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(); /* PA[35:12] */
94
tag[0].hi = read_c0_taghi(); /* PA[39:36] */
95
cache_op(Index_Load_Tag_D, addr | 1L);
96
tag[1].lo = read_c0_taglo(); /* PA[35:12] */
97
tag[1].hi = read_c0_taghi(); /* PA[39:36] */
98
}
99
#undef tag
100
101
/*
102
* Save primary instruction cache (indexed by VA[13:6]) tags
103
* the same way.
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(); /* PA[35:12] */
110
tag[0].hi = read_c0_taghi(); /* PA[39:36] */
111
cache_op(Index_Load_Tag_I, addr | 1L);
112
tag[1].lo = read_c0_taglo(); /* PA[35:12] */
113
tag[1].hi = read_c0_taghi(); /* PA[39:36] */
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
/* save status registers */
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; /* HPC3_SCTRL_ACTIVE ? */
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; /* HPC3_SCTRL_ACTIVE ? */
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; /* HPC3_ERXCTRL_ACTIVE ? */
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; /* HPC3_ETXCTRL_ACTIVE ? */
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
/* HPC3_PDMACTRL_ISACT ? */
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
/* PA[31:12] shifted to PTag0 (PA[35:12]) format */
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) { /* for each possible VA[13:12] value */
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) { /* for each possible VA[13:12] value */
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; /* scblksize = 2^[7..6] */
204
scw = ((i >> 16) & 7) + 19 - 1; /* scwaysize = 2^[24..19] / 2 */
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
/* This is likely rather similar to correct code ;-) */
307
308
vaddr &= 0x7fffffff; /* Doc. states that top bit is ignored */
309
310
/* If tlb-entry is valid and VPN-high (bits [30:21] ?) matches... */
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; /* 16k:4k */
315
/* PTEIndex is VPN-low (bits [22:14]/[20:12] ?) */
316
unsigned long pte = (lo >> 6) << 12; /* PTEBase */
317
pte += 8*((vaddr >> pgsz) & 0x1ff);
318
if (page_is_ram(PFN_DOWN(pte))) {
319
/*
320
* Note: Since DMA hardware does look up
321
* translation on its own, this PTE *must*
322
* match the TLB/EntryLo-register format !
323
*/
324
unsigned long a = *(unsigned long *)
325
PHYS_TO_XKSEG_UNCACHED(pte);
326
a = (a & 0x3f) << 6; /* PFN */
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)) /* Xlate-bit clear ? */
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
* MC sends an interrupt whenever bus or parity errors occur. In addition,
364
* if the error happened during a CPU read, it also asserts the bus error
365
* pin on the R4K. Code in bus error handler save the MC bus error registers
366
* and then clear the interrupt when this happens.
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
* Try to find out, whether we got here by a mispredicted speculative
376
* load/store operation. If so, it's not fatal, we can go on.
377
*/
378
/* Any cause other than "Interrupt" (ExcCode 0) is fatal. */
379
if (regs->cp0_cause & CAUSEF_EXCCODE)
380
goto mips_be_fatal;
381
382
/* Any cause other than "Bus error interrupt" (IP6) is weird. */
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
/* Any state other than "Memory bus error" is fatal. */
390
if (cpu_err_stat & CPU_ERRMASK & ~SGIMC_CSTAT_ADDR)
391
goto mips_be_fatal;
392
393
/* GIO errors other than timeouts are fatal */
394
if (gio_err_stat & GIO_ERRMASK & ~SGIMC_GSTAT_TIME)
395
goto mips_be_fatal;
396
397
/*
398
* Now we have an asynchronous bus error, speculatively or DMA caused.
399
* Need to search all DMA descriptors for the error address.
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
/* Check MC's virtual DMA stuff. */
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
/* A speculative bus error... */
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
/* Assume it would be too dangerous to continue ... */
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
* We arrive here only in the unusual case of do_be() invocation,
458
* i.e. by a bus error exception without a bus error interrupt.
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
mips_set_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);
489
490