VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / arch / sparc64 / mm / fault.c
index 5fc4644..49c3dd2 100644 (file)
@@ -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;
 }