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