[tip: locking/core] irq: Add {over,under}flow detection for local_interrupt_{enable,disable}
From: tip-bot2 for Boqun Feng
Date: Mon Oct 12 2026 - 10:00:13 EST
The following commit has been merged into the locking/core branch of tip:
Commit-ID: 9e174422f6f15a1d88994a07067f66c920d2f947
Gitweb: https://git.kernel.org/tip/9e174422f6f15a1d88994a07067f66c920d2f947
Author: Boqun Feng <boqun@xxxxxxxxxx>
AuthorDate: Thu, 01 Oct 2026 10:25:16 +02:00
Committer: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
CommitterDate: Fri, 02 Oct 2026 11:47:13 +02:00
irq: Add {over,under}flow detection for local_interrupt_{enable,disable}
Currently there is no way to detect overflow and underflow inside the
HARDIRQ_DISABLE_MASK part of preempt_count. Add these detection guarded
by DEBUG_PREEMPT similar to the detection for PREEMPT_MASK
{over,under}flow.
Suggested-by: Shrikanth Hegde <sshegde@xxxxxxxxxxxxx>
Signed-off-by: Boqun Feng <boqun@xxxxxxxxxx>
Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
Reviewed-by: Shrikanth Hegde <sshegde@xxxxxxxxxxxxx>
Link: https://patch.msgid.link/20261001082519.16195-3-boqun@xxxxxxxxxx
---
include/linux/interrupt_rc.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/include/linux/interrupt_rc.h b/include/linux/interrupt_rc.h
index a9ed937..d385ab0 100644
--- a/include/linux/interrupt_rc.h
+++ b/include/linux/interrupt_rc.h
@@ -11,6 +11,7 @@
* make it easier to include without hitting circular header dependencies.
*/
+#include <linux/debug_locks.h>
#include <linux/irqflags.h>
#include <linux/preempt.h>
#include <linux/processor.h>
@@ -65,6 +66,13 @@ static inline void local_interrupt_disable(void)
local_irq_save(flags);
new_count = hardirq_disable_enter();
+ /* Is hardirq disable count overflow soon? */
+ if (IS_ENABLED(CONFIG_DEBUG_PREEMPT) &&
+ DEBUG_LOCKS_WARN_ON(((new_count & HARDIRQ_DISABLE_MASK) +
+ (10 << HARDIRQ_DISABLE_SHIFT)) >=
+ HARDIRQ_DISABLE_MASK))
+ return;
+
if ((new_count & HARDIRQ_DISABLE_MASK) == HARDIRQ_DISABLE_OFFSET)
_local_interrupt_save_state(flags);
}
@@ -73,6 +81,11 @@ static inline void local_interrupt_enable(void)
{
int new_count;
+ /* Unpaired local_interrupt_enable()? Warn and abort. */
+ if (IS_ENABLED(CONFIG_DEBUG_PREEMPT) &&
+ DEBUG_LOCKS_WARN_ON((preempt_count() & HARDIRQ_DISABLE_MASK) == 0))
+ return;
+
new_count = hardirq_disable_exit();
if ((new_count & HARDIRQ_DISABLE_MASK) == 0)