X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=arch%2Farm%2Fkernel%2Ftraps.c;h=c9fe6f5f7ee35ac6df900efcf06c85cd908e3a15;hb=758438a7b8da593c9116e95cc7fdff6e9e0b0c40;hp=f6de76e0a45d388e1974f2015f2e3ba7de6c6094;hpb=d95300758bed9e0f783f3e3b4fd037bf0a21abe0;p=linux-2.6-omap-h63xx.git diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index f6de76e0a45..c9fe6f5f7ee 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -23,7 +23,6 @@ #include #include -#include #include #include #include @@ -198,25 +197,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 +214,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 +349,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 +487,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;