summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2001-11-15 17:29:36 +0000
committerjhb <jhb@FreeBSD.org>2001-11-15 17:29:36 +0000
commite189eb8c72b1b31f4adb945631c5ab910d63931f (patch)
tree9faad756ef4ec37d9c9c9c619951443b69b6ba70 /sys/i386
parent369c63dd8d807688c3054131dbb0252341f14302 (diff)
downloadFreeBSD-src-e189eb8c72b1b31f4adb945631c5ab910d63931f.zip
FreeBSD-src-e189eb8c72b1b31f4adb945631c5ab910d63931f.tar.gz
- Don't enable interrupts in trap() if we trapped while holding a spin
lock as this usually makes the problem worse. - If we get a page fault while holding a spin lock, treat it as a fatal trap and don't even bother calling into the VM since calling into the VM will panic when trying to lock Giant before we can get a useful message anyways.
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/i386/trap.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index 714f3f2..23ad3fc 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -190,8 +190,7 @@ trap(frame)
* interrupts and then trapped. Enabling interrupts
* now is wrong, but it is better than running with
* interrupts disabled until they are accidentally
- * enabled later. XXX This is really bad if we trap
- * while holding a spin lock.
+ * enabled later.
*/
type = frame.tf_trapno;
if (ISPL(frame.tf_cs) == SEL_UPL || (frame.tf_eflags & PSL_VM))
@@ -206,10 +205,12 @@ trap(frame)
printf("kernel trap %d with interrupts disabled\n",
type);
/*
- * We should walk p_heldmtx here and see if any are
- * spin mutexes, and not do this if so.
+ * Page faults need interrupts diasabled until later,
+ * and we shouldn't enable interrupts while holding a
+ * spin lock.
*/
- enable_intr();
+ if (type != T_PAGEFLT && PCPU_GET(spinlocks) == NULL)
+ enable_intr();
}
}
@@ -223,9 +224,19 @@ trap(frame)
* an interrupt gate for the pagefault handler. We
* are finally ready to read %cr2 and then must
* reenable interrupts.
+ *
+ * If we get a page fault while holding a spin lock, then
+ * it is most likely a fatal kernel page fault. The kernel
+ * is already going to panic trying to get a sleep lock to
+ * do the VM lookup, so just consider it a fatal trap so the
+ * kernel can print out a useful trap message and even get
+ * to the debugger.
*/
eva = rcr2();
- enable_intr();
+ if (PCPU_GET(spinlocks) == NULL)
+ enable_intr();
+ else
+ trap_fatal(&frame, eva);
}
if ((ISPL(frame.tf_cs) == SEL_UPL) ||
OpenPOWER on IntegriCloud