m68k: Handle 68040 bus faults
authorRoman Zippel <zippel@linux-m68k.org>
Mon, 5 May 2008 19:25:48 +0000 (21:25 +0200)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 5 May 2008 19:38:50 +0000 (12:38 -0700)
Fix 68040 bus fault handling, so the standard kernel exception handling
can be used for i/o probing.

Contrary to normal access faults there is nothing to fix, but at least
we have to disable writebacks to avoid recursive faults.

Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/m68k/kernel/traps.c

index fd4858e2dd638d456636dee4dcdc9b9134c34b3c..75b8340b254be08caa07f9e29eac3cbb5e5f0161 100644 (file)
@@ -468,15 +468,26 @@ static inline void access_error040(struct frame *fp)
                         * (if do_page_fault didn't fix the mapping,
                          * the writeback won't do good)
                         */
+disable_wb:
 #ifdef DEBUG
                        printk(".. disabling wb2\n");
 #endif
                        if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
                                fp->un.fmt7.wb2s &= ~WBV_040;
+                       if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr)
+                               fp->un.fmt7.wb3s &= ~WBV_040;
                }
-       } else if (send_fault_sig(&fp->ptregs) > 0) {
-               printk("68040 access error, ssw=%x\n", ssw);
-               trap_c(fp);
+       } else {
+               /* In case of a bus error we either kill the process or expect
+                * the kernel to catch the fault, which then is also responsible
+                * for cleaning up the mess.
+                */
+               current->thread.signo = SIGBUS;
+               current->thread.faddr = fp->un.fmt7.faddr;
+               if (send_fault_sig(&fp->ptregs) >= 0)
+                       printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw,
+                              fp->un.fmt7.faddr);
+               goto disable_wb;
        }
 
        do_040writebacks(fp);