diff --git a/sys/riscv/riscv/trap.c b/sys/riscv/riscv/trap.c --- a/sys/riscv/riscv/trap.c +++ b/sys/riscv/riscv/trap.c @@ -227,11 +227,6 @@ pcb = td->td_pcb; stval = frame->tf_stval; - 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 (usermode) { if (!VIRT_IS_VALID(stval)) { call_trapsignal(td, SIGSEGV, SEGV_MAPERR, (void *)stval, @@ -244,7 +239,8 @@ * Enable interrupts for the duration of the page fault. For * user faults this was done already in do_trap_user(). */ - intr_enable(); + if ((frame->tf_sstatus & SSTATUS_SIE) != 0) + intr_enable(); if (stval >= VM_MIN_KERNEL_ADDRESS) { map = kernel_map; @@ -268,6 +264,11 @@ if (VIRT_IS_VALID(va) && pmap_fault(map->pmap, va, ftype)) goto done; + if (td->td_critnest != 0 || td->td_intr_nesting_level != 0 || + WITNESS_CHECK(WARN_SLEEPOK | WARN_GIANTOK, NULL, + "Kernel page fault") != 0) + goto fatal; + error = vm_fault_trap(map, va, ftype, VM_FAULT_NORMAL, &sig, &ucode); if (error != KERN_SUCCESS) { if (usermode) {