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;
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;
* 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)) {
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;
}
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);