]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/sh/mm/fault_32.c
Merge branch 'core/xen' into x86/xen
[linux-2.6-omap-h63xx.git] / arch / sh / mm / fault_32.c
index 33b43d20e9f6f06a5a967dc11da3b4d8e3f26f59..0c776fdfbddae6800480dc0a3dc7be54103509b3 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/mm.h>
 #include <linux/hardirq.h>
 #include <linux/kprobes.h>
+#include <asm/io_trapped.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
@@ -36,16 +37,12 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
        int fault;
        siginfo_t info;
 
-       trace_hardirqs_on();
-       local_irq_enable();
-
 #ifdef CONFIG_SH_KGDB
        if (kgdb_nofault && kgdb_bus_err_hook)
                kgdb_bus_err_hook();
 #endif
 
        tsk = current;
-       mm = tsk->mm;
        si_code = SEGV_MAPERR;
 
        if (unlikely(address >= TASK_SIZE)) {
@@ -87,6 +84,14 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
                return;
        }
 
+       /* Only enable interrupts if they were on before the fault */
+       if ((regs->sr & SR_IMASK) != SR_IMASK) {
+               trace_hardirqs_on();
+               local_irq_enable();
+       }
+
+       mm = tsk->mm;
+
        /*
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
@@ -163,6 +168,8 @@ no_context:
        if (fixup_exception(regs))
                return;
 
+       if (handle_trapped_io(regs, address))
+               return;
 /*
  * Oops. The kernel tried to access some bad page. We'll have to
  * terminate things with extreme prejudice.
@@ -296,6 +303,14 @@ asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs,
                entry = pte_mkdirty(entry);
        entry = pte_mkyoung(entry);
 
+#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SMP)
+       /*
+        * ITLB is not affected by "ldtlb" instruction.
+        * So, we need to flush the entry by ourselves.
+        */
+       local_flush_tlb_one(get_asid(), address & PAGE_MASK);
+#endif
+
        set_pte(pte, entry);
        update_mmu_cache(NULL, address, entry);