]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/sh/mm/fault.c
Pull ec into release branch
[linux-2.6-omap-h63xx.git] / arch / sh / mm / fault.c
index 0ecc117cade4525042e98b8240e1a0ebcda9b882..04a39aa7f1f97029a8c182b93077c9f2a7a67e57 100644 (file)
 #include <linux/mm.h>
 #include <linux/hardirq.h>
 #include <linux/kprobes.h>
-#include <asm/kdebug.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 #include <asm/kgdb.h>
 
-#ifdef CONFIG_KPROBES
-ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
-
-/* Hook to register for page fault notifications */
-int register_page_fault_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
-}
-
-int unregister_page_fault_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
-}
-
-static inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
-                                   int trap, int sig)
-{
-       struct die_args args = {
-               .regs = regs,
-               .trapnr = trap,
-       };
-       return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
-}
-#else
-static inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
-                                   int trap, int sig)
-{
-       return NOTIFY_DONE;
-}
-#endif
-
 /*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
@@ -64,16 +32,11 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
        struct task_struct *tsk;
        struct mm_struct *mm;
        struct vm_area_struct * vma;
-       unsigned long page;
        int si_code;
+       int fault;
        siginfo_t info;
 
        trace_hardirqs_on();
-
-       if (notify_page_fault(DIE_PAGE_FAULT, regs,
-                             writeaccess, SIGSEGV) == NOTIFY_STOP)
-               return;
-
        local_irq_enable();
 
 #ifdef CONFIG_SH_KGDB
@@ -162,20 +125,18 @@ good_area:
         * the fault.
         */
 survive:
-       switch (handle_mm_fault(mm, vma, address, writeaccess)) {
-               case VM_FAULT_MINOR:
-                       tsk->min_flt++;
-                       break;
-               case VM_FAULT_MAJOR:
-                       tsk->maj_flt++;
-                       break;
-               case VM_FAULT_SIGBUS:
-                       goto do_sigbus;
-               case VM_FAULT_OOM:
+       fault = handle_mm_fault(mm, vma, address, writeaccess);
+       if (unlikely(fault & VM_FAULT_ERROR)) {
+               if (fault & VM_FAULT_OOM)
                        goto out_of_memory;
-               default:
-                       BUG();
+               else if (fault & VM_FAULT_SIGBUS)
+                       goto do_sigbus;
+               BUG();
        }
+       if (fault & VM_FAULT_MAJOR)
+               tsk->maj_flt++;
+       else
+               tsk->min_flt++;
 
        up_read(&mm->mmap_sem);
        return;
@@ -207,24 +168,37 @@ no_context:
  * terminate things with extreme prejudice.
  *
  */
-       if (address < PAGE_SIZE)
-               printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
-       else
-               printk(KERN_ALERT "Unable to handle kernel paging request");
-       printk(" at virtual address %08lx\n", address);
-       printk(KERN_ALERT "pc = %08lx\n", regs->pc);
-       page = (unsigned long)get_TTB();
-       if (page) {
-               page = ((unsigned long *) page)[address >> PGDIR_SHIFT];
-               printk(KERN_ALERT "*pde = %08lx\n", page);
-               if (page & _PAGE_PRESENT) {
-                       page &= PAGE_MASK;
-                       address &= 0x003ff000;
-                       page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
-                       printk(KERN_ALERT "*pte = %08lx\n", page);
+
+       bust_spinlocks(1);
+
+       if (oops_may_print()) {
+               __typeof__(pte_val(__pte(0))) page;
+
+               if (address < PAGE_SIZE)
+                       printk(KERN_ALERT "Unable to handle kernel NULL "
+                                         "pointer dereference");
+               else
+                       printk(KERN_ALERT "Unable to handle kernel paging "
+                                         "request");
+               printk(" at virtual address %08lx\n", address);
+               printk(KERN_ALERT "pc = %08lx\n", regs->pc);
+               page = (unsigned long)get_TTB();
+               if (page) {
+                       page = ((__typeof__(page) *)page)[address >> PGDIR_SHIFT];
+                       printk(KERN_ALERT "*pde = %08lx\n", page);
+                       if (page & _PAGE_PRESENT) {
+                               page &= PAGE_MASK;
+                               address &= 0x003ff000;
+                               page = ((__typeof__(page) *)
+                                               __va(page))[address >>
+                                                           PAGE_SHIFT];
+                               printk(KERN_ALERT "*pte = %08lx\n", page);
+                       }
                }
        }
+
        die("Oops", regs, writeaccess);
+       bust_spinlocks(0);
        do_exit(SIGKILL);
 
 /*
@@ -285,7 +259,7 @@ asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs,
        pte_t *pte;
        pte_t entry;
        struct mm_struct *mm = current->mm;
-       spinlock_t *ptl;
+       spinlock_t *ptl = NULL;
        int ret = 1;
 
 #ifdef CONFIG_SH_KGDB