staticunsignedint cpu_err_stat; /* Status reg for CPU */ staticunsignedint gio_err_stat; /* Status reg for GIO */ staticunsignedint cpu_err_addr; /* Error address reg for CPU */ staticunsignedint gio_err_addr; /* Error address reg for GIO */ staticunsignedint extio_stat; staticunsignedint hpc3_berr_stat; /* Bus error interrupt status */
/* * Starting with a bus-address, save secondary cache (indexed by * PA[23..18:7..6]) tags first.
*/
addr &= ~1L; #define tag cache_tags.tags[0]
cache_op(Index_Load_Tag_S, addr);
tag[0].lo = read_c0_taglo(); /* PA[35:18], VA[13:12] */
tag[0].hi = read_c0_taghi(); /* PA[39:36] */
cache_op(Index_Load_Tag_S, addr | 1L);
tag[1].lo = read_c0_taglo(); /* PA[35:18], VA[13:12] */
tag[1].hi = read_c0_taghi(); /* PA[39:36] */ #undef tag
/* * Save all primary data cache (indexed by VA[13:5]) tags which * might fit to this bus-address, knowing that VA[11:0] == PA[11:0]. * Saving all tags and evaluating them later is easier and safer * than relying on VA[13:12] from the secondary cache tags to pick * matching primary tags here already.
*/
addr &= (0xffL << 56) | ((1 << 12) - 1); #define tag cache_tags.tagd[i] for (i = 0; i < 4; ++i, addr += (1 << 12)) {
cache_op(Index_Load_Tag_D, addr);
tag[0].lo = read_c0_taglo(); /* PA[35:12] */
tag[0].hi = read_c0_taghi(); /* PA[39:36] */
cache_op(Index_Load_Tag_D, addr | 1L);
tag[1].lo = read_c0_taglo(); /* PA[35:12] */
tag[1].hi = read_c0_taghi(); /* PA[39:36] */
} #undef tag
/* * Save primary instruction cache (indexed by VA[13:6]) tags * the same way.
*/
addr &= (0xffL << 56) | ((1 << 12) - 1); #define tag cache_tags.tagi[i] for (i = 0; i < 4; ++i, addr += (1 << 12)) {
cache_op(Index_Load_Tag_I, addr);
tag[0].lo = read_c0_taglo(); /* PA[35:12] */
tag[0].hi = read_c0_taghi(); /* PA[39:36] */
cache_op(Index_Load_Tag_I, addr | 1L);
tag[1].lo = read_c0_taglo(); /* PA[35:12] */
tag[1].hi = read_c0_taghi(); /* PA[39:36] */
} #undef tag
}
if (check_microtlb(sgimc->dtlb_hi0, sgimc->dtlb_lo0, a) ||
check_microtlb(sgimc->dtlb_hi1, sgimc->dtlb_lo1, a) ||
check_microtlb(sgimc->dtlb_hi2, sgimc->dtlb_lo2, a) ||
check_microtlb(sgimc->dtlb_hi3, sgimc->dtlb_lo3, a)) return 1;
} return 0;
}
staticint check_vdma_gioaddr(void)
{ if (gio_err_stat & GIO_ERRMASK) {
u32 a = sgimc->gio_dma_trans;
a = (sgimc->gmaddronly & ~a) | (sgimc->gio_dma_sbits & a); return gio_err_addr == a;
} return 0;
}
/* * MC sends an interrupt whenever bus or parity errors occur. In addition, * if the error happened during a CPU read, it also asserts the bus error * pin on the R4K. Code in bus error handler save the MC bus error registers * and then clear the interrupt when this happens.
*/
staticint ip28_be_interrupt(conststruct pt_regs *regs)
{ int i;
save_and_clear_buserr(); /* * Try to find out, whether we got here by a mispredicted speculative * load/store operation. If so, it's not fatal, we can go on.
*/ /* Any cause other than "Interrupt" (ExcCode 0) is fatal. */ if (regs->cp0_cause & CAUSEF_EXCCODE) goto mips_be_fatal;
/* Any cause other than "Bus error interrupt" (IP6) is weird. */ if ((regs->cp0_cause & CAUSEF_IP6) != CAUSEF_IP6) goto mips_be_fatal;
if (extio_stat & (EXTIO_HPC3_BUSERR | EXTIO_EISA_BUSERR)) goto mips_be_fatal;
/* Any state other than "Memory bus error" is fatal. */ if (cpu_err_stat & CPU_ERRMASK & ~SGIMC_CSTAT_ADDR) goto mips_be_fatal;
/* GIO errors other than timeouts are fatal */ if (gio_err_stat & GIO_ERRMASK & ~SGIMC_GSTAT_TIME) goto mips_be_fatal;
/* * Now we have an asynchronous bus error, speculatively or DMA caused. * Need to search all DMA descriptors for the error address.
*/ for (i = 0; i < sizeof(hpc3)/sizeof(struct hpc3_stat); ++i) { struct hpc3_stat *hp = (struct hpc3_stat *)&hpc3 + i; if ((cpu_err_stat & CPU_ERRMASK) &&
(cpu_err_addr == hp->ndptr || cpu_err_addr == hp->cbp)) break; if ((gio_err_stat & GIO_ERRMASK) &&
(gio_err_addr == hp->ndptr || gio_err_addr == hp->cbp)) break;
} if (i < sizeof(hpc3)/sizeof(struct hpc3_stat)) { struct hpc3_stat *hp = (struct hpc3_stat *)&hpc3 + i;
printk(KERN_ERR "at DMA addresses: HPC3 @ %08lx:" " ctl %08x, ndp %08x, cbp %08x\n",
CPHYSADDR(hp->addr), hp->ctrl, hp->ndptr, hp->cbp); goto mips_be_fatal;
} /* Check MC's virtual DMA stuff. */ if (check_vdma_memaddr()) {
printk(KERN_ERR "at GIO DMA: mem address 0x%08x.\n",
sgimc->maddronly); goto mips_be_fatal;
} if (check_vdma_gioaddr()) {
printk(KERN_ERR "at GIO DMA: gio address 0x%08x.\n",
sgimc->gmaddronly); goto mips_be_fatal;
} /* A speculative bus error... */ if (debug_be_interrupt) {
print_buserr(regs);
printk(KERN_ERR "discarded!\n");
} return MIPS_BE_DISCARD;
if (ip28_be_interrupt(regs) != MIPS_BE_DISCARD) { /* Assume it would be too dangerous to continue ... */
die_if_kernel("Oops", regs);
force_sig(SIGBUS);
} elseif (debug_be_interrupt)
show_regs(regs);
}
staticint ip28_be_handler(struct pt_regs *regs, int is_fixup)
{ /* * We arrive here only in the unusual case of do_be() invocation, * i.e. by a bus error exception without a bus error interrupt.
*/ if (is_fixup) {
count_be_is_fixup++;
save_and_clear_buserr(); return MIPS_BE_FIXUP;
}
count_be_handler++; return ip28_be_interrupt(regs);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.