svn commit: r342100 - head/sys/riscv/riscv
Mark Johnston
markj at FreeBSD.org
Fri Dec 14 21:07:13 UTC 2018
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
More information about the svn-src-all
mailing list