Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Dec 2018 21:07:12 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r342100 - head/sys/riscv/riscv
Message-ID:  <201812142107.wBEL7CxP003346@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201812142107.wBEL7CxP003346>