This avoids taking the kernel lock when ci_inatomic is set. This
might speed up inteldrm(4) a bit. Since uvm_grow() still needs the
kernel lock, some reorganization of the code is necessary.
I'm not sure this actaully has an impact. If we end up here with
ci_inatomic set we're going to return EFAULT and take a slow path
anyway. So maybe it is better to leave this until we make uvm_grow()
mpsafe?
Index: arch/amd64/amd64/trap.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/trap.c,v
retrieving revision 1.81
diff -u -p -r1.81 trap.c
--- arch/amd64/amd64/trap.c 14 Sep 2020 12:51:28 -0000 1.81
+++ arch/amd64/amd64/trap.c 24 Sep 2020 14:21:24 -0000
@@ -173,11 +173,10 @@ pageflttrap(struct trapframe *frame, uin
pcb = &p->p_addr->u_pcb;
va = trunc_page((vaddr_t)cr2);
- KERNEL_LOCK();
-
if (!usermode) {
/* This will only trigger if SMEP is enabled */
if (cr2 <= VM_MAXUSER_ADDRESS && frame->tf_err & PGEX_I) {
+ KERNEL_LOCK();
fault("attempt to execute user address %p "
"in supervisor mode", (void *)cr2);
/* retain kernel lock */
@@ -186,6 +185,7 @@ pageflttrap(struct trapframe *frame, uin
/* This will only trigger if SMAP is enabled */
if (pcb->pcb_onfault == NULL && cr2 <= VM_MAXUSER_ADDRESS &&
frame->tf_err & PGEX_P) {
+ KERNEL_LOCK();
fault("attempt to access user address %p "
"in supervisor mode", (void *)cr2);
/* retain kernel lock */
@@ -216,28 +216,29 @@ pageflttrap(struct trapframe *frame, uin
caddr_t onfault = pcb->pcb_onfault;
pcb->pcb_onfault = NULL;
+ KERNEL_LOCK();
error = uvm_fault(map, va, frame->tf_err & PGEX_P ?
VM_FAULT_PROTECT : VM_FAULT_INVALID, ftype);
+ if (error == 0 && map != kernel_map)
+ uvm_grow(p, va);
+ KERNEL_UNLOCK();
pcb->pcb_onfault = onfault;
} else
error = EFAULT;
- if (error == 0) {
- if (map != kernel_map)
- uvm_grow(p, va);
- } else if (!usermode) {
+ if (error && !usermode) {
if (pcb->pcb_onfault != 0) {
- KERNEL_UNLOCK();
frame->tf_rip = (u_int64_t)pcb->pcb_onfault;
return 1;
} else {
/* bad memory access in the kernel */
+ KERNEL_LOCK();
fault("uvm_fault(%p, 0x%llx, 0, %d) -> %x",
map, cr2, ftype, error);
/* retain kernel lock */
return 0;
}
- } else {
+ } else if (error) {
union sigval sv;
int signal, sicode;
@@ -260,8 +261,6 @@ pageflttrap(struct trapframe *frame, uin
sv.sival_ptr = (void *)cr2;
trapsignal(p, signal, T_PAGEFLT, sicode, sv);
}
-
- KERNEL_UNLOCK();
return 1;
}