Pull release into acpica branch
[pandora-kernel.git] / arch / arm / kernel / traps.c
index f6de76e..45e9ea6 100644 (file)
@@ -198,25 +198,16 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
        barrier();
 }
 
-DEFINE_SPINLOCK(die_lock);
-
-/*
- * This function is protected against re-entrancy.
- */
-NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
+static void __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)
 {
-       struct task_struct *tsk = current;
+       struct task_struct *tsk = thread->task;
        static int die_counter;
 
-       console_verbose();
-       spin_lock_irq(&die_lock);
-       bust_spinlocks(1);
-
        printk("Internal error: %s: %x [#%d]\n", str, err, ++die_counter);
        print_modules();
        __show_regs(regs);
        printk("Process %s (pid: %d, stack limit = 0x%p)\n",
-               tsk->comm, tsk->pid, tsk->thread_info + 1);
+               tsk->comm, tsk->pid, thread + 1);
 
        if (!user_mode(regs) || in_interrupt()) {
                dump_mem("Stack: ", regs->ARM_sp,
@@ -224,7 +215,21 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
                dump_backtrace(regs, tsk);
                dump_instr(regs);
        }
+}
+
+DEFINE_SPINLOCK(die_lock);
+
+/*
+ * This function is protected against re-entrancy.
+ */
+NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
+{
+       struct thread_info *thread = current_thread_info();
 
+       console_verbose();
+       spin_lock_irq(&die_lock);
+       bust_spinlocks(1);
+       __die(str, err, thread, regs);
        bust_spinlocks(0);
        spin_unlock_irq(&die_lock);
        do_exit(SIGSEGV);
@@ -345,7 +350,9 @@ static int bad_syscall(int n, struct pt_regs *regs)
        struct thread_info *thread = current_thread_info();
        siginfo_t info;
 
-       if (current->personality != PER_LINUX && thread->exec_domain->handler) {
+       if (current->personality != PER_LINUX &&
+           current->personality != PER_LINUX_32BIT &&
+           thread->exec_domain->handler) {
                thread->exec_domain->handler(n, regs);
                return regs->ARM_r0;
        }
@@ -481,29 +488,33 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
                unsigned long addr = regs->ARM_r2;
                struct mm_struct *mm = current->mm;
                pgd_t *pgd; pmd_t *pmd; pte_t *pte;
+               spinlock_t *ptl;
 
                regs->ARM_cpsr &= ~PSR_C_BIT;
-               spin_lock(&mm->page_table_lock);
+               down_read(&mm->mmap_sem);
                pgd = pgd_offset(mm, addr);
                if (!pgd_present(*pgd))
                        goto bad_access;
                pmd = pmd_offset(pgd, addr);
                if (!pmd_present(*pmd))
                        goto bad_access;
-               pte = pte_offset_map(pmd, addr);
-               if (!pte_present(*pte) || !pte_write(*pte))
+               pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+               if (!pte_present(*pte) || !pte_write(*pte)) {
+                       pte_unmap_unlock(pte, ptl);
                        goto bad_access;
+               }
                val = *(unsigned long *)addr;
                val -= regs->ARM_r0;
                if (val == 0) {
                        *(unsigned long *)addr = regs->ARM_r1;
                        regs->ARM_cpsr |= PSR_C_BIT;
                }
-               spin_unlock(&mm->page_table_lock);
+               pte_unmap_unlock(pte, ptl);
+               up_read(&mm->mmap_sem);
                return val;
 
                bad_access:
-               spin_unlock(&mm->page_table_lock);
+               up_read(&mm->mmap_sem);
                /* simulate a write access fault */
                do_DataAbort(addr, 15 + (1 << 11), regs);
                return -1;