]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - arch/x86/mm/fault.c
Merge branch 'linus' into tracing/mmiotrace
[linux-2.6.git] / arch / x86 / mm / fault.c
index 621afb6343dc359d4205a56021658380b1dda427..0a778e3c43ee42df8b71405c9f5e35bd49a411e4 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <linux/ptrace.h>
+#include <linux/mmiotrace.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
 #define PF_RSVD                (1<<3)
 #define PF_INSTR       (1<<4)
 
+static inline int kmmio_fault(struct pt_regs *regs, unsigned long addr)
+{
+#ifdef CONFIG_MMIOTRACE_HOOKS
+       if (unlikely(is_kmmio_active()))
+               if (kmmio_handler(regs, addr) == 1)
+                       return -1;
+#endif
+       return 0;
+}
+
 static inline int notify_page_fault(struct pt_regs *regs)
 {
 #ifdef CONFIG_KPROBES
@@ -91,12 +102,10 @@ static int is_prefetch(struct pt_regs *regs, unsigned long addr,
        int prefetch = 0;
        unsigned char *max_instr;
 
-#ifdef CONFIG_X86_32
-       if (!(__supported_pte_mask & _PAGE_NX))
-               return 0;
-#endif
-
-       /* If it was a exec fault on NX page, ignore */
+       /*
+        * If it was a exec (instruction fetch) fault on NX page, then
+        * do not ignore the fault:
+        */
        if (error_code & PF_INSTR)
                return 0;
 
@@ -186,7 +195,7 @@ static int bad_address(void *p)
 }
 #endif
 
-void dump_pagetable(unsigned long address)
+static void dump_pagetable(unsigned long address)
 {
 #ifdef CONFIG_X86_32
        __typeof__(pte_val(__pte(0))) page;
@@ -499,6 +508,11 @@ static int vmalloc_fault(unsigned long address)
        unsigned long pgd_paddr;
        pmd_t *pmd_k;
        pte_t *pte_k;
+
+       /* Make sure we are in vmalloc area */
+       if (!(address >= VMALLOC_START && address < VMALLOC_END))
+               return -1;
+
        /*
         * Synchronize this task's top level page-table
         * with the 'reference' page table.
@@ -603,6 +617,8 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
 
        if (notify_page_fault(regs))
                return;
+       if (unlikely(kmmio_fault(regs, address)))
+               return;
 
        /*
         * We fault-in kernel-space virtual memory on-demand. The
@@ -641,7 +657,7 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
 #ifdef CONFIG_X86_32
        /* It's safe to allow irq's after cr2 has been saved and the vmalloc
           fault has been handled. */
-       if (regs->flags & (X86_EFLAGS_IF|VM_MASK))
+       if (regs->flags & (X86_EFLAGS_IF | X86_VM_MASK))
                local_irq_enable();
 
        /*
@@ -978,9 +994,5 @@ void vmalloc_sync_all(void)
                if (address == start)
                        start = address + PGDIR_SIZE;
        }
-       /* Check that there is no need to do the same for the modules area. */
-       BUILD_BUG_ON(!(MODULES_VADDR > __START_KERNEL));
-       BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) ==
-                               (__START_KERNEL & PGDIR_MASK)));
 #endif
 }