X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fsparc64%2Fmm%2Ffault.c;h=45edb9459bcdf7bc85dc01dc1c3971bd0b36c34a;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=63b989f3fe47f44d4284d6fe3f0b5edfe5fa62a5;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index 63b989f3f..45edb9459 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -175,6 +175,7 @@ static void bad_kernel_pc(struct pt_regs *regs) static unsigned int get_user_insn(unsigned long tpc) { pgd_t *pgdp = pgd_offset(current->mm, tpc); + pud_t *pudp; pmd_t *pmdp; pte_t *ptep, pte; unsigned long pa; @@ -183,7 +184,10 @@ static unsigned int get_user_insn(unsigned long tpc) if (pgd_none(*pgdp)) goto outret; - pmdp = pmd_offset(pgdp, tpc); + pudp = pud_offset(pgdp, tpc); + if (pud_none(*pudp)) + goto outret; + pmdp = pmd_offset(pudp, tpc); if (pmd_none(*pmdp)) goto outret; @@ -352,7 +356,7 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs) * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto intr_or_no_mm; if (test_thread_flag(TIF_32BIT)) { @@ -361,7 +365,15 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs) address &= 0xffffffff; } - down_read(&mm->mmap_sem); + if (!down_read_trylock(&mm->mmap_sem)) { + if ((regs->tstate & TSTATE_PRIV) && + !search_exception_tables(regs->tpc)) { + insn = get_fault_insn(regs, insn); + goto handle_kernel_fault; + } + down_read(&mm->mmap_sem); + } + vma = find_vma(mm, address); if (!vma) goto bad_area; @@ -446,16 +458,18 @@ good_area: } switch (handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE))) { - case 1: + case VM_FAULT_MINOR: current->min_flt++; break; - case 2: + case VM_FAULT_MAJOR: current->maj_flt++; break; - case 0: + case VM_FAULT_SIGBUS: goto do_sigbus; - default: + case VM_FAULT_OOM: goto out_of_memory; + default: + BUG(); } up_read(&mm->mmap_sem);