git: e18449fbe273 - main - amd64: move code to check for traps with interrupts disabled into helpers
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 20 Mar 2026 22:49:50 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=e18449fbe2731399862e82e61fffaadd6739642c
commit e18449fbe2731399862e82e61fffaadd6739642c
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-03-11 12:04:55 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-03-20 21:05:15 +0000
amd64: move code to check for traps with interrupts disabled into helpers
Reviewed by: jhb, markj
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D55809
---
sys/amd64/amd64/trap.c | 96 ++++++++++++++++++++++++++++++--------------------
1 file changed, 58 insertions(+), 38 deletions(-)
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 3a9323936d2d..e4e4e98fbf7d 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -260,6 +260,62 @@ trap_clear_step(struct thread *td, struct trapframe *frame)
PROC_UNLOCK(td->td_proc);
}
+/*
+ * Warn with a message on the user's tty if application code has
+ * disabled interrupts and then trapped.
+ */
+static void
+trap_check_intr_user(struct thread *td, struct trapframe *frame)
+{
+ MPASS(TRAPF_USERMODE(frame));
+
+ if (__predict_true((frame->tf_rflags & PSL_I) != 0))
+ return;
+
+ uprintf("pid %ld (%s): trap %d (%s) with interrupts disabled\n",
+ (long)td->td_proc->p_pid, td->td_name, frame->tf_trapno,
+ trap_msg[frame->tf_trapno]);
+}
+
+/*
+ * Some exceptions can occur on kernel attempt to reload a corrupted
+ * user context, which is done with interrupts enabled. Interrupts
+ * such as NMIs and debugging faults can be also taken in the kernel
+ * while interrupts are disabled. Other traps shouldn't occur with
+ * interrupts disabled unless the kernel has a bug. Re-enable
+ * interrupts in case this occurs, unless the interrupted thread holds
+ * a spin lock.
+ */
+static void
+trap_check_intr_kernel(struct thread *td, struct trapframe *frame)
+{
+ MPASS(!TRAPF_USERMODE(frame));
+
+ if (__predict_true((frame->tf_rflags & PSL_I) != 0))
+ return;
+
+ switch (frame->tf_trapno) {
+ case T_NMI:
+ case T_BPTFLT:
+ case T_TRCTRAP:
+ case T_PROTFLT:
+ case T_SEGNPFLT:
+ case T_STKFLT:
+ break;
+ default:
+ printf("kernel trap %d with interrupts disabled\n",
+ frame->tf_trapno);
+
+ /*
+ * We shouldn't enable interrupts while holding a
+ * spin lock.
+ */
+ if (td->td_md.md_spinlock_count == 0)
+ enable_intr();
+ break;
+ }
+}
+
/*
* Table of handlers for various segment load faults.
*/
@@ -337,46 +393,9 @@ trap(struct trapframe *frame)
return;
}
- if ((frame->tf_rflags & PSL_I) == 0) {
- /*
- * Buggy application or kernel code has disabled
- * interrupts and then trapped. Enabling interrupts
- * now is wrong, but it is better than running with
- * interrupts disabled until they are accidentally
- * enabled later.
- */
- if (TRAPF_USERMODE(frame)) {
- uprintf(
- "pid %ld (%s): trap %d (%s) "
- "with interrupts disabled\n",
- (long)curproc->p_pid, curthread->td_name, type,
- trap_msg[type]);
- } else {
- switch (type) {
- case T_NMI:
- case T_BPTFLT:
- case T_TRCTRAP:
- case T_PROTFLT:
- case T_SEGNPFLT:
- case T_STKFLT:
- break;
- default:
- printf(
- "kernel trap %d with interrupts disabled\n",
- type);
-
- /*
- * We shouldn't enable interrupts while holding a
- * spin lock.
- */
- if (td->td_md.md_spinlock_count == 0)
- enable_intr();
- }
- }
- }
-
if (TRAPF_USERMODE(frame)) {
/* user trap */
+ trap_check_intr_user(td, frame);
td->td_pticks = 0;
td->td_frame = frame;
@@ -497,6 +516,7 @@ trap(struct trapframe *frame)
}
} else {
/* kernel trap */
+ trap_check_intr_kernel(td, frame);
KASSERT(cold || td->td_ucred != NULL,
("kernel trap doesn't have ucred"));