linux/arch/mips/sgi-ip22/ip28-berr.c
<<
>>
Prefs
   1/*
   2 * ip28-berr.c: Bus error handling.
   3 *
   4 * Copyright (C) 2002, 2003 Ladislav Michl (ladis@linux-mips.org)
   5 * Copyright (C) 2005 Peter Fuerst (pf@net.alphadv.de) - IP28
   6 */
   7
   8#include <linux/init.h>
   9#include <linux/kernel.h>
  10#include <linux/sched.h>
  11#include <linux/seq_file.h>
  12
  13#include <asm/addrspace.h>
  14#include <asm/traps.h>
  15#include <asm/branch.h>
  16#include <asm/irq_regs.h>
  17#include <asm/sgi/mc.h>
  18#include <asm/sgi/hpc3.h>
  19#include <asm/sgi/ioc.h>
  20#include <asm/sgi/ip22.h>
  21#include <asm/r4kcache.h>
  22#include <asm/uaccess.h>
  23#include <asm/bootinfo.h>
  24
  25static unsigned int count_be_is_fixup;
  26static unsigned int count_be_handler;
  27static unsigned int count_be_interrupt;
  28static int debug_be_interrupt;
  29
  30static unsigned int cpu_err_stat;       /* Status reg for CPU */
  31static unsigned int gio_err_stat;       /* Status reg for GIO */
  32static unsigned int cpu_err_addr;       /* Error address reg for CPU */
  33static unsigned int gio_err_addr;       /* Error address reg for GIO */
  34static unsigned int extio_stat;
  35static unsigned int hpc3_berr_stat;     /* Bus error interrupt status */
  36
  37struct hpc3_stat {
  38        unsigned long addr;
  39        unsigned int ctrl;
  40        unsigned int cbp;
  41        unsigned int ndptr;
  42};
  43
  44static struct {
  45        struct hpc3_stat pbdma[8];
  46        struct hpc3_stat scsi[2];
  47        struct hpc3_stat ethrx, ethtx;
  48} hpc3;
  49
  50static struct {
  51        unsigned long err_addr;
  52        struct {
  53                u32 lo;
  54                u32 hi;
  55        } tags[1][2], tagd[4][2], tagi[4][2]; /* Way 0/1 */
  56} cache_tags;
  57
  58static inline void save_cache_tags(unsigned busaddr)
  59{
  60        unsigned long addr = CAC_BASE | busaddr;
  61        int i;
  62        cache_tags.err_addr = addr;
  63
  64        /*
  65         * Starting with a bus-address, save secondary cache (indexed by
  66         * PA[23..18:7..6]) tags first.
  67         */
  68        addr &= ~1L;
  69#define tag cache_tags.tags[0]
  70        cache_op(Index_Load_Tag_S, addr);
  71        tag[0].lo = read_c0_taglo();    /* PA[35:18], VA[13:12] */
  72        tag[0].hi = read_c0_taghi();    /* PA[39:36] */
  73        cache_op(Index_Load_Tag_S, addr | 1L);
  74        tag[1].lo = read_c0_taglo();    /* PA[35:18], VA[13:12] */
  75        tag[1].hi = read_c0_taghi();    /* PA[39:36] */
  76#undef tag
  77
  78        /*
  79         * Save all primary data cache (indexed by VA[13:5]) tags which
  80         * might fit to this bus-address, knowing that VA[11:0] == PA[11:0].
  81         * Saving all tags and evaluating them later is easier and safer
  82         * than relying on VA[13:12] from the secondary cache tags to pick
  83         * matching primary tags here already.
  84         */
  85        addr &= (0xffL << 56) | ((1 << 12) - 1);
  86#define tag cache_tags.tagd[i]
  87        for (i = 0; i < 4; ++i, addr += (1 << 12)) {
  88                cache_op(Index_Load_Tag_D, addr);
  89                tag[0].lo = read_c0_taglo();    /* PA[35:12] */
  90                tag[0].hi = read_c0_taghi();    /* PA[39:36] */
  91                cache_op(Index_Load_Tag_D, addr | 1L);
  92                tag[1].lo = read_c0_taglo();    /* PA[35:12] */
  93                tag[1].hi = read_c0_taghi();    /* PA[39:36] */
  94        }
  95#undef tag
  96
  97        /*
  98         * Save primary instruction cache (indexed by VA[13:6]) tags
  99         * the same way.
 100         */
 101        addr &= (0xffL << 56) | ((1 << 12) - 1);
 102#define tag cache_tags.tagi[i]
 103        for (i = 0; i < 4; ++i, addr += (1 << 12)) {
 104                cache_op(Index_Load_Tag_I, addr);
 105                tag[0].lo = read_c0_taglo();    /* PA[35:12] */
 106                tag[0].hi = read_c0_taghi();    /* PA[39:36] */
 107                cache_op(Index_Load_Tag_I, addr | 1L);
 108                tag[1].lo = read_c0_taglo();    /* PA[35:12] */
 109                tag[1].hi = read_c0_taghi();    /* PA[39:36] */
 110        }
 111#undef tag
 112}
 113
 114#define GIO_ERRMASK     0xff00
 115#define CPU_ERRMASK     0x3f00
 116
 117static void save_and_clear_buserr(void)
 118{
 119        int i;
 120
 121        /* save status registers */
 122        cpu_err_addr = sgimc->cerr;
 123        cpu_err_stat = sgimc->cstat;
 124        gio_err_addr = sgimc->gerr;
 125        gio_err_stat = sgimc->gstat;
 126        extio_stat = sgioc->extio;
 127        hpc3_berr_stat = hpc3c0->bestat;
 128
 129        hpc3.scsi[0].addr  = (unsigned long)&hpc3c0->scsi_chan0;
 130        hpc3.scsi[0].ctrl  = hpc3c0->scsi_chan0.ctrl; /* HPC3_SCTRL_ACTIVE ? */
 131        hpc3.scsi[0].cbp   = hpc3c0->scsi_chan0.cbptr;
 132        hpc3.scsi[0].ndptr = hpc3c0->scsi_chan0.ndptr;
 133
 134        hpc3.scsi[1].addr  = (unsigned long)&hpc3c0->scsi_chan1;
 135        hpc3.scsi[1].ctrl  = hpc3c0->scsi_chan1.ctrl; /* HPC3_SCTRL_ACTIVE ? */
 136        hpc3.scsi[1].cbp   = hpc3c0->scsi_chan1.cbptr;
 137        hpc3.scsi[1].ndptr = hpc3c0->scsi_chan1.ndptr;
 138
 139        hpc3.ethrx.addr  = (unsigned long)&hpc3c0->ethregs.rx_cbptr;
 140        hpc3.ethrx.ctrl  = hpc3c0->ethregs.rx_ctrl; /* HPC3_ERXCTRL_ACTIVE ? */
 141        hpc3.ethrx.cbp   = hpc3c0->ethregs.rx_cbptr;
 142        hpc3.ethrx.ndptr = hpc3c0->ethregs.rx_ndptr;
 143
 144        hpc3.ethtx.addr  = (unsigned long)&hpc3c0->ethregs.tx_cbptr;
 145        hpc3.ethtx.ctrl  = hpc3c0->ethregs.tx_ctrl; /* HPC3_ETXCTRL_ACTIVE ? */
 146        hpc3.ethtx.cbp   = hpc3c0->ethregs.tx_cbptr;
 147        hpc3.ethtx.ndptr = hpc3c0->ethregs.tx_ndptr;
 148
 149        for (i = 0; i < 8; ++i) {
 150                /* HPC3_PDMACTRL_ISACT ? */
 151                hpc3.pbdma[i].addr  = (unsigned long)&hpc3c0->pbdma[i];
 152                hpc3.pbdma[i].ctrl  = hpc3c0->pbdma[i].pbdma_ctrl;
 153                hpc3.pbdma[i].cbp   = hpc3c0->pbdma[i].pbdma_bptr;
 154                hpc3.pbdma[i].ndptr = hpc3c0->pbdma[i].pbdma_dptr;
 155        }
 156        i = 0;
 157        if (gio_err_stat & CPU_ERRMASK)
 158                i = gio_err_addr;
 159        if (cpu_err_stat & CPU_ERRMASK)
 160                i = cpu_err_addr;
 161        save_cache_tags(i);
 162
 163        sgimc->cstat = sgimc->gstat = 0;
 164}
 165
 166static void print_cache_tags(void)
 167{
 168        u32 scb, scw;
 169        int i;
 170
 171        printk(KERN_ERR "Cache tags @ %08x:\n", (unsigned)cache_tags.err_addr);
 172
 173        /* PA[31:12] shifted to PTag0 (PA[35:12]) format */
 174        scw = (cache_tags.err_addr >> 4) & 0x0fffff00;
 175
 176        scb = cache_tags.err_addr & ((1 << 12) - 1) & ~((1 << 5) - 1);
 177        for (i = 0; i < 4; ++i) { /* for each possible VA[13:12] value */
 178                if ((cache_tags.tagd[i][0].lo & 0x0fffff00) != scw &&
 179                    (cache_tags.tagd[i][1].lo & 0x0fffff00) != scw)
 180                    continue;
 181                printk(KERN_ERR
 182                       "D: 0: %08x %08x, 1: %08x %08x  (VA[13:5]  %04x)\n",
 183                        cache_tags.tagd[i][0].hi, cache_tags.tagd[i][0].lo,
 184                        cache_tags.tagd[i][1].hi, cache_tags.tagd[i][1].lo,
 185                        scb | (1 << 12)*i);
 186        }
 187        scb = cache_tags.err_addr & ((1 << 12) - 1) & ~((1 << 6) - 1);
 188        for (i = 0; i < 4; ++i) { /* for each possible VA[13:12] value */
 189                if ((cache_tags.tagi[i][0].lo & 0x0fffff00) != scw &&
 190                    (cache_tags.tagi[i][1].lo & 0x0fffff00) != scw)
 191                    continue;
 192                printk(KERN_ERR
 193                       "I: 0: %08x %08x, 1: %08x %08x  (VA[13:6]  %04x)\n",
 194                        cache_tags.tagi[i][0].hi, cache_tags.tagi[i][0].lo,
 195                        cache_tags.tagi[i][1].hi, cache_tags.tagi[i][1].lo,
 196                        scb | (1 << 12)*i);
 197        }
 198        i = read_c0_config();
 199        scb = i & (1 << 13) ? 7:6;      /* scblksize = 2^[7..6] */
 200        scw = ((i >> 16) & 7) + 19 - 1; /* scwaysize = 2^[24..19] / 2 */
 201
 202        i = ((1 << scw) - 1) & ~((1 << scb) - 1);
 203        printk(KERN_ERR "S: 0: %08x %08x, 1: %08x %08x  (PA[%u:%u] %05x)\n",
 204                cache_tags.tags[0][0].hi, cache_tags.tags[0][0].lo,
 205                cache_tags.tags[0][1].hi, cache_tags.tags[0][1].lo,
 206                scw-1, scb, i & (unsigned)cache_tags.err_addr);
 207}
 208
 209static inline const char *cause_excode_text(int cause)
 210{
 211        static const char *txt[32] =
 212        {       "Interrupt",
 213                "TLB modification",
 214                "TLB (load or instruction fetch)",
 215                "TLB (store)",
 216                "Address error (load or instruction fetch)",
 217                "Address error (store)",
 218                "Bus error (instruction fetch)",
 219                "Bus error (data: load or store)",
 220                "Syscall",
 221                "Breakpoint",
 222                "Reserved instruction",
 223                "Coprocessor unusable",
 224                "Arithmetic Overflow",
 225                "Trap",
 226                "14",
 227                "Floating-Point",
 228                "16", "17", "18", "19", "20", "21", "22",
 229                "Watch Hi/Lo",
 230                "24", "25", "26", "27", "28", "29", "30", "31",
 231        };
 232        return txt[(cause & 0x7c) >> 2];
 233}
 234
 235static void print_buserr(const struct pt_regs *regs)
 236{
 237        const int field = 2 * sizeof(unsigned long);
 238        int error = 0;
 239
 240        if (extio_stat & EXTIO_MC_BUSERR) {
 241                printk(KERN_ERR "MC Bus Error\n");
 242                error |= 1;
 243        }
 244        if (extio_stat & EXTIO_HPC3_BUSERR) {
 245                printk(KERN_ERR "HPC3 Bus Error 0x%x:<id=0x%x,%s,lane=0x%x>\n",
 246                        hpc3_berr_stat,
 247                        (hpc3_berr_stat & HPC3_BESTAT_PIDMASK) >>
 248                                          HPC3_BESTAT_PIDSHIFT,
 249                        (hpc3_berr_stat & HPC3_BESTAT_CTYPE) ? "PIO" : "DMA",
 250                        hpc3_berr_stat & HPC3_BESTAT_BLMASK);
 251                error |= 2;
 252        }
 253        if (extio_stat & EXTIO_EISA_BUSERR) {
 254                printk(KERN_ERR "EISA Bus Error\n");
 255                error |= 4;
 256        }
 257        if (cpu_err_stat & CPU_ERRMASK) {
 258                printk(KERN_ERR "CPU error 0x%x<%s%s%s%s%s%s> @ 0x%08x\n",
 259                        cpu_err_stat,
 260                        cpu_err_stat & SGIMC_CSTAT_RD ? "RD " : "",
 261                        cpu_err_stat & SGIMC_CSTAT_PAR ? "PAR " : "",
 262                        cpu_err_stat & SGIMC_CSTAT_ADDR ? "ADDR " : "",
 263                        cpu_err_stat & SGIMC_CSTAT_SYSAD_PAR ? "SYSAD " : "",
 264                        cpu_err_stat & SGIMC_CSTAT_SYSCMD_PAR ? "SYSCMD " : "",
 265                        cpu_err_stat & SGIMC_CSTAT_BAD_DATA ? "BAD_DATA " : "",
 266                        cpu_err_addr);
 267                error |= 8;
 268        }
 269        if (gio_err_stat & GIO_ERRMASK) {
 270                printk(KERN_ERR "GIO error 0x%x:<%s%s%s%s%s%s%s%s> @ 0x%08x\n",
 271                        gio_err_stat,
 272                        gio_err_stat & SGIMC_GSTAT_RD ? "RD " : "",
 273                        gio_err_stat & SGIMC_GSTAT_WR ? "WR " : "",
 274                        gio_err_stat & SGIMC_GSTAT_TIME ? "TIME " : "",
 275                        gio_err_stat & SGIMC_GSTAT_PROM ? "PROM " : "",
 276                        gio_err_stat & SGIMC_GSTAT_ADDR ? "ADDR " : "",
 277                        gio_err_stat & SGIMC_GSTAT_BC ? "BC " : "",
 278                        gio_err_stat & SGIMC_GSTAT_PIO_RD ? "PIO_RD " : "",
 279                        gio_err_stat & SGIMC_GSTAT_PIO_WR ? "PIO_WR " : "",
 280                        gio_err_addr);
 281                error |= 16;
 282        }
 283        if (!error)
 284                printk(KERN_ERR "MC: Hmm, didn't find any error condition.\n");
 285        else {
 286                printk(KERN_ERR "CP0: config %08x,  "
 287                        "MC: cpuctrl0/1: %08x/%05x, giopar: %04x\n"
 288                        "MC: cpu/gio_memacc: %08x/%05x, memcfg0/1: %08x/%08x\n",
 289                        read_c0_config(),
 290                        sgimc->cpuctrl0, sgimc->cpuctrl0, sgimc->giopar,
 291                        sgimc->cmacc, sgimc->gmacc,
 292                        sgimc->mconfig0, sgimc->mconfig1);
 293                print_cache_tags();
 294        }
 295        printk(KERN_ALERT "%s, epc == %0*lx, ra == %0*lx\n",
 296               cause_excode_text(regs->cp0_cause),
 297               field, regs->cp0_epc, field, regs->regs[31]);
 298}
 299
 300/*
 301 * Check, whether MC's (virtual) DMA address caused the bus error.
 302 * See "Virtual DMA Specification", Draft 1.5, Feb 13 1992, SGI
 303 */
 304
 305static int addr_is_ram(unsigned long addr, unsigned sz)
 306{
 307        int i;
 308
 309        for (i = 0; i < boot_mem_map.nr_map; i++) {
 310                unsigned long a = boot_mem_map.map[i].addr;
 311                if (a <= addr && addr+sz <= a+boot_mem_map.map[i].size)
 312                        return 1;
 313        }
 314        return 0;
 315}
 316
 317static int check_microtlb(u32 hi, u32 lo, unsigned long vaddr)
 318{
 319        /* This is likely rather similar to correct code ;-) */
 320
 321        vaddr &= 0x7fffffff; /* Doc. states that top bit is ignored */
 322
 323        /* If tlb-entry is valid and VPN-high (bits [30:21] ?) matches... */
 324        if ((lo & 2) && (vaddr >> 21) == ((hi<<1) >> 22)) {
 325                u32 ctl = sgimc->dma_ctrl;
 326                if (ctl & 1) {
 327                        unsigned int pgsz = (ctl & 2) ? 14:12; /* 16k:4k */
 328                        /* PTEIndex is VPN-low (bits [22:14]/[20:12] ?) */
 329                        unsigned long pte = (lo >> 6) << 12; /* PTEBase */
 330                        pte += 8*((vaddr >> pgsz) & 0x1ff);
 331                        if (addr_is_ram(pte, 8)) {
 332                                /*
 333                                 * Note: Since DMA hardware does look up
 334                                 * translation on its own, this PTE *must*
 335                                 * match the TLB/EntryLo-register format !
 336                                 */
 337                                unsigned long a = *(unsigned long *)
 338                                                PHYS_TO_XKSEG_UNCACHED(pte);
 339                                a = (a & 0x3f) << 6; /* PFN */
 340                                a += vaddr & ((1 << pgsz) - 1);
 341                                return (cpu_err_addr == a);
 342                        }
 343                }
 344        }
 345        return 0;
 346}
 347
 348static int check_vdma_memaddr(void)
 349{
 350        if (cpu_err_stat & CPU_ERRMASK) {
 351                u32 a = sgimc->maddronly;
 352
 353                if (!(sgimc->dma_ctrl & 0x100)) /* Xlate-bit clear ? */
 354                        return (cpu_err_addr == a);
 355
 356                if (check_microtlb(sgimc->dtlb_hi0, sgimc->dtlb_lo0, a) ||
 357                    check_microtlb(sgimc->dtlb_hi1, sgimc->dtlb_lo1, a) ||
 358                    check_microtlb(sgimc->dtlb_hi2, sgimc->dtlb_lo2, a) ||
 359                    check_microtlb(sgimc->dtlb_hi3, sgimc->dtlb_lo3, a))
 360                        return 1;
 361        }
 362        return 0;
 363}
 364
 365static int check_vdma_gioaddr(void)
 366{
 367        if (gio_err_stat & GIO_ERRMASK) {
 368                u32 a = sgimc->gio_dma_trans;
 369                a = (sgimc->gmaddronly & ~a) | (sgimc->gio_dma_sbits & a);
 370                return (gio_err_addr == a);
 371        }
 372        return 0;
 373}
 374
 375/*
 376 * MC sends an interrupt whenever bus or parity errors occur. In addition,
 377 * if the error happened during a CPU read, it also asserts the bus error
 378 * pin on the R4K. Code in bus error handler save the MC bus error registers
 379 * and then clear the interrupt when this happens.
 380 */
 381
 382static int ip28_be_interrupt(const struct pt_regs *regs)
 383{
 384        int i;
 385
 386        save_and_clear_buserr();
 387        /*
 388         * Try to find out, whether we got here by a mispredicted speculative
 389         * load/store operation.  If so, it's not fatal, we can go on.
 390         */
 391        /* Any cause other than "Interrupt" (ExcCode 0) is fatal. */
 392        if (regs->cp0_cause & CAUSEF_EXCCODE)
 393                goto mips_be_fatal;
 394
 395        /* Any cause other than "Bus error interrupt" (IP6) is weird. */
 396        if ((regs->cp0_cause & CAUSEF_IP6) != CAUSEF_IP6)
 397                goto mips_be_fatal;
 398
 399        if (extio_stat & (EXTIO_HPC3_BUSERR | EXTIO_EISA_BUSERR))
 400                goto mips_be_fatal;
 401
 402        /* Any state other than "Memory bus error" is fatal. */
 403        if (cpu_err_stat & CPU_ERRMASK & ~SGIMC_CSTAT_ADDR)
 404                goto mips_be_fatal;
 405
 406        /* GIO errors other than timeouts are fatal */
 407        if (gio_err_stat & GIO_ERRMASK & ~SGIMC_GSTAT_TIME)
 408                goto mips_be_fatal;
 409
 410        /*
 411         * Now we have an asynchronous bus error, speculatively or DMA caused.
 412         * Need to search all DMA descriptors for the error address.
 413         */
 414        for (i = 0; i < sizeof(hpc3)/sizeof(struct hpc3_stat); ++i) {
 415                struct hpc3_stat *hp = (struct hpc3_stat *)&hpc3 + i;
 416                if ((cpu_err_stat & CPU_ERRMASK) &&
 417                    (cpu_err_addr == hp->ndptr || cpu_err_addr == hp->cbp))
 418                        break;
 419                if ((gio_err_stat & GIO_ERRMASK) &&
 420                    (gio_err_addr == hp->ndptr || gio_err_addr == hp->cbp))
 421                        break;
 422        }
 423        if (i < sizeof(hpc3)/sizeof(struct hpc3_stat)) {
 424                struct hpc3_stat *hp = (struct hpc3_stat *)&hpc3 + i;
 425                printk(KERN_ERR "at DMA addresses: HPC3 @ %08lx:"
 426                       " ctl %08x, ndp %08x, cbp %08x\n",
 427                       CPHYSADDR(hp->addr), hp->ctrl, hp->ndptr, hp->cbp);
 428                goto mips_be_fatal;
 429        }
 430        /* Check MC's virtual DMA stuff. */
 431        if (check_vdma_memaddr()) {
 432                printk(KERN_ERR "at GIO DMA: mem address 0x%08x.\n",
 433                        sgimc->maddronly);
 434                goto mips_be_fatal;
 435        }
 436        if (check_vdma_gioaddr()) {
 437                printk(KERN_ERR "at GIO DMA: gio address 0x%08x.\n",
 438                        sgimc->gmaddronly);
 439                goto mips_be_fatal;
 440        }
 441        /* A speculative bus error... */
 442        if (debug_be_interrupt) {
 443                print_buserr(regs);
 444                printk(KERN_ERR "discarded!\n");
 445        }
 446        return MIPS_BE_DISCARD;
 447
 448mips_be_fatal:
 449        print_buserr(regs);
 450        return MIPS_BE_FATAL;
 451}
 452
 453void ip22_be_interrupt(int irq)
 454{
 455        struct pt_regs *regs = get_irq_regs();
 456
 457        count_be_interrupt++;
 458
 459        if (ip28_be_interrupt(regs) != MIPS_BE_DISCARD) {
 460                /* Assume it would be too dangerous to continue ... */
 461                die_if_kernel("Oops", regs);
 462                force_sig(SIGBUS, current);
 463        } else if (debug_be_interrupt)
 464                show_regs((struct pt_regs *)regs);
 465}
 466
 467static int ip28_be_handler(struct pt_regs *regs, int is_fixup)
 468{
 469        /*
 470         * We arrive here only in the unusual case of do_be() invocation,
 471         * i.e. by a bus error exception without a bus error interrupt.
 472         */
 473        if (is_fixup) {
 474                count_be_is_fixup++;
 475                save_and_clear_buserr();
 476                return MIPS_BE_FIXUP;
 477        }
 478        count_be_handler++;
 479        return ip28_be_interrupt(regs);
 480}
 481
 482void __init ip22_be_init(void)
 483{
 484        board_be_handler = ip28_be_handler;
 485}
 486
 487int ip28_show_be_info(struct seq_file *m)
 488{
 489        seq_printf(m, "IP28 be fixups\t\t: %u\n", count_be_is_fixup);
 490        seq_printf(m, "IP28 be interrupts\t: %u\n", count_be_interrupt);
 491        seq_printf(m, "IP28 be handler\t\t: %u\n", count_be_handler);
 492
 493        return 0;
 494}
 495
 496static int __init debug_be_setup(char *str)
 497{
 498        debug_be_interrupt++;
 499        return 1;
 500}
 501__setup("ip28_debug_be", debug_be_setup);
 502