Author: markj
Date: Fri Dec 14 21:07:12 2018
New Revision: 342100
URL: https://svnweb.freebsd.org/changeset/base/342100

Log:
  Add some more checking to the RISC-V page fault handler.
  
  - Panic immediately if witness says we're holding non-sleepable locks.
    This helps ensure that we don't recurse on the pmap lock in
    pmap_fault_fixup().
  - Panic if the kernel faults on a user address without setting an
    onfault handler.
  - Panic if the fault occurred in a critical section or interrupt
    handler, like we do on other platforms.
  - Fix some style issues in trap_pfault().
  
  Reviewed by:  jhb
  MFC after:    1 week
  Sponsored by: The FreeBSD Foundation
  Differential Revision:        https://reviews.freebsd.org/D18561

Modified:
  head/sys/riscv/riscv/trap.c

Modified: head/sys/riscv/riscv/trap.c
==============================================================================
--- head/sys/riscv/riscv/trap.c Fri Dec 14 21:04:30 2018        (r342099)
+++ head/sys/riscv/riscv/trap.c Fri Dec 14 21:07:12 2018        (r342100)
@@ -167,7 +167,7 @@ svc_handler(struct trapframe *frame)
 }
 
 static void
-data_abort(struct trapframe *frame, int lower)
+data_abort(struct trapframe *frame, int usermode)
 {
        struct vm_map *map;
        uint64_t sbadaddr;
@@ -176,9 +176,7 @@ data_abort(struct trapframe *frame, int lower)
        vm_prot_t ftype;
        vm_offset_t va;
        struct proc *p;
-       int ucode;
-       int error;
-       int sig;
+       int error, sig, ucode;
 
 #ifdef KDB
        if (kdb_active) {
@@ -188,19 +186,23 @@ data_abort(struct trapframe *frame, int lower)
 #endif
 
        td = curthread;
+       p = td->td_proc;
        pcb = td->td_pcb;
        sbadaddr = frame->tf_sbadaddr;
 
-       p = td->td_proc;
+       if (td->td_critnest != 0 || td->td_intr_nesting_level != 0 ||
+           WITNESS_CHECK(WARN_SLEEPOK | WARN_GIANTOK, NULL,
+           "Kernel page fault") != 0)
+               goto fatal;
 
-       if (lower)
+       if (usermode)
                map = &td->td_proc->p_vmspace->vm_map;
+       else if (sbadaddr >= VM_MAX_USER_ADDRESS)
+               map = kernel_map;
        else {
-               /* The top bit tells us which range to use */
-               if ((sbadaddr >> 63) == 1)
-                       map = kernel_map;
-               else
-                       map = &td->td_proc->p_vmspace->vm_map;
+               if (pcb->pcb_onfault == 0)
+                       goto fatal;
+               map = &td->td_proc->p_vmspace->vm_map;
        }
 
        va = trunc_page(sbadaddr);
@@ -241,7 +243,7 @@ data_abort(struct trapframe *frame, int lower)
        }
 
        if (error != KERN_SUCCESS) {
-               if (lower) {
+               if (usermode) {
                        sig = SIGSEGV;
                        if (error == KERN_PROTECTION_FAILURE)
                                ucode = SEGV_ACCERR;
@@ -249,21 +251,23 @@ data_abort(struct trapframe *frame, int lower)
                                ucode = SEGV_MAPERR;
                        call_trapsignal(td, sig, ucode, (void *)sbadaddr);
                } else {
-                       if (td->td_intr_nesting_level == 0 &&
-                           pcb->pcb_onfault != 0) {
+                       if (pcb->pcb_onfault != 0) {
                                frame->tf_a[0] = error;
                                frame->tf_sepc = pcb->pcb_onfault;
                                return;
                        }
-                       dump_regs(frame);
-                       panic("vm_fault failed: %lx, va 0x%016lx",
-                               frame->tf_sepc, sbadaddr);
+                       goto fatal;
                }
        }
 
 done:
-       if (lower)
+       if (usermode)
                userret(td, frame);
+       return;
+
+fatal:
+       dump_regs(frame);
+       panic("Fatal page fault at %#lx: %#016lx", frame->tf_sepc, sbadaddr);
 }
 
 void
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to