[PATCH] ppc32: update xmon help text
[linux-3.10.git] / arch / ia64 / mm / fault.c
index da859125aaeff3b9952221b0761b3f8190623183..3c32af910d604732283ab91ebb10aa50cbcdee6b 100644 (file)
@@ -9,11 +9,13 @@
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
+#include <linux/kprobes.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/kdebug.h>
 
 extern void die (char *, struct pt_regs *, long);
 
@@ -75,7 +77,7 @@ mapped_kernel_page_is_present (unsigned long address)
        return pte_present(pte);
 }
 
-void
+void __kprobes
 ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
 {
        int signal = SIGSEGV, code = SEGV_MAPERR;
@@ -102,6 +104,13 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
                goto bad_area_no_up;
 #endif
 
+       /*
+        * This is to handle the kprobes on user space access instructions
+        */
+       if (notify_die(DIE_PAGE_FAULT, "page fault", regs, code, TRAP_BRKPT,
+                                       SIGSEGV) == NOTIFY_STOP)
+               return;
+
        down_read(&mm->mmap_sem);
 
        vma = find_vma_prev(mm, address, &prev_vma);
@@ -209,18 +218,18 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
        }
 
   no_context:
-       if (isr & IA64_ISR_SP) {
+       if ((isr & IA64_ISR_SP)
+           || ((isr & IA64_ISR_NA) && (isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH))
+       {
                /*
-                * This fault was due to a speculative load set the "ed" bit in the psr to
-                * ensure forward progress (target register will get a NaT).
+                * This fault was due to a speculative load or lfetch.fault, set the "ed"
+                * bit in the psr to ensure forward progress.  (Target register will get a
+                * NaT for ld.s, lfetch will be canceled.)
                 */
                ia64_psr(regs)->ed = 1;
                return;
        }
 
-       if (ia64_done_with_exception(regs))
-               return;
-
        /*
         * Since we have no vma's for region 5, we might get here even if the address is
         * valid, due to the VHPT walker inserting a non present translation that becomes
@@ -231,6 +240,9 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
        if (REGION_NUMBER(address) == 5 && mapped_kernel_page_is_present(address))
                return;
 
+       if (ia64_done_with_exception(regs))
+               return;
+
        /*
         * Oops. The kernel tried to access some bad page. We'll have to terminate things
         * with extreme prejudice.