~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/sgi-ip22/ip28-berr.c

Version: ~ [ linux-5.11-rc3 ] ~ [ linux-5.10.7 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.89 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.167 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.215 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.251 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.251 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 25 static unsigned int count_be_is_fixup;
 26 static unsigned int count_be_handler;
 27 static unsigned int count_be_interrupt;
 28 static int debug_be_interrupt;
 29 
 30 static unsigned int cpu_err_stat;       /* Status reg for CPU */
 31 static unsigned int gio_err_stat;       /* Status reg for GIO */
 32 static unsigned int cpu_err_addr;       /* Error address reg for CPU */
 33 static unsigned int gio_err_addr;       /* Error address reg for GIO */
 34 static unsigned int extio_stat;
 35 static unsigned int hpc3_berr_stat;     /* Bus error interrupt status */
 36 
 37 struct hpc3_stat {
 38         unsigned long addr;
 39         unsigned int ctrl;
 40         unsigned int cbp;
 41         unsigned int ndptr;
 42 };
 43 
 44 static struct {
 45         struct hpc3_stat pbdma[8];
 46         struct hpc3_stat scsi[2];
 47         struct hpc3_stat ethrx, ethtx;
 48 } hpc3;
 49 
 50 static 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 
 58 static 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 
117 static 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 
166 static 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 
209 static 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 
235 static 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 
305 static 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 
317 static 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 
348 static 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 
365 static 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 
382 static 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 
448 mips_be_fatal:
449         print_buserr(regs);
450         return MIPS_BE_FATAL;
451 }
452 
453 void 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 
467 static 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 
482 void __init ip22_be_init(void)
483 {
484         board_be_handler = ip28_be_handler;
485 }
486 
487 int 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 
496 static 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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp