X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fsparc64%2Fmm%2Ffault.c;h=49c3dd29a5b69ed39ed1b7fe73c3a22b0221c689;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=5fc4644aad99f9697e1ced589a375ceb9e974463;hpb=db216c3d5e4c040e557a50f8f5d35d5c415e8c1c;p=linux-2.6.git diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index 5fc4644aa..49c3dd29a 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -218,9 +218,9 @@ static void do_fault_siginfo(int code, int sig, struct pt_regs *regs, info.si_signo = sig; info.si_errno = 0; if (fault_code & FAULT_CODE_ITLB) - info.si_addr = (void *) regs->tpc; + info.si_addr = (void __user *) regs->tpc; else - info.si_addr = (void *) + info.si_addr = (void __user *) compute_effective_address(regs, insn, 0); info.si_trapno = 0; force_sig_info(sig, &info, current); @@ -257,7 +257,7 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code, * in that case. */ - if (!(fault_code & FAULT_CODE_WRITE) && + if (!(fault_code & (FAULT_CODE_WRITE|FAULT_CODE_ITLB)) && (insn & 0xc0800000) == 0xc0800000) { if (insn & 0x2000) asi = (regs->tstate >> 24); @@ -408,6 +408,16 @@ continue_fault: */ good_area: si_code = SEGV_ACCERR; + + /* If we took a ITLB miss on a non-executable page, catch + * that here. + */ + if ((fault_code & FAULT_CODE_ITLB) && !(vma->vm_flags & VM_EXEC)) { + BUG_ON(address != regs->tpc); + BUG_ON(regs->tstate & TSTATE_PRIV); + goto bad_area; + } + if (fault_code & FAULT_CODE_WRITE) { if (!(vma->vm_flags & VM_WRITE)) goto bad_area; @@ -418,7 +428,8 @@ good_area: if (tlb_type == spitfire && (vma->vm_flags & VM_EXEC) != 0 && vma->vm_file != NULL) - set_thread_flag(TIF_BLKCOMMIT); + set_thread_fault_code(fault_code | + FAULT_CODE_BLKCOMMIT); } else { /* Allow reads even for write-only mappings */ if (!(vma->vm_flags & (VM_READ | VM_EXEC))) @@ -487,6 +498,5 @@ do_sigbus: fault_done: /* These values are no longer needed, clear them. */ set_thread_fault_code(0); - clear_thread_flag(TIF_BLKCOMMIT); current_thread_info()->fault_address = 0; }