[PATCH v3 0/5] watchdog: qcom: Support NMI pretimeout warnings

From: Mayank Rungta

Date: Wed Sep 02 2026 - 21:59:45 EST


On ARM64 Qualcomm SoCs, when a system freezes completely due to hard
locked CPUs with standard interrupts disabled, a standard watchdog
pretimeout warning interrupt (bark) fails to fire. To diagnose total
system lockups, we need to transition the Qualcomm hardware watchdog
pretimeout bark interrupt into an NMI (or pseudo-NMI).

Enabling NMI pretimeout handlers within a loadable driver module requires
addressing NMI teardown synchronization, exporting NMI registration
APIs, and ensuring watchdog pretimeout governor dispatch is NMI-safe.

This 5-patch series achieves NMI pretimeout enablement for qcom-wdt:
1) Enforces that interrupt controllers claiming NMI support must
implement ->irq_get_irqchip_state(), and synchronizes in-flight NMI
handlers during teardown (__cleanup_nmi) to prevent use-after-free
bugs during module unload or driver unbind.
2) Implements synchronous disable_nmi() to ensure in-flight handlers on
other CPUs complete before returning.
3) Exports request_nmi(), free_nmi(), enable_nmi(), disable_nmi(), and
disable_nmi_nosync() to GPL loadable kernel modules.
4) Replaces spinlocks in watchdog_notify_pretimeout() with RCU to
guarantee safe governor execution from NMI context.
5) Updates qcom-wdt to request its pretimeout bark interrupt as an
NMI (or pseudo-NMI) with fallback to standard IRQ.

Testing & Verification:
- Built and tested on ARM64 Qualcomm Snapdragon SoC (Google CoachZ)
loadable module configurations (CONFIG_QCOM_WDT=m).
- With GICv3 pseudo-NMI enabled, simulated hard CPU lockups and
IRQ-disabled hang conditions via lkdtm. Confirmed that qcom-wdt traps
the watchdog pretimeout bark interrupt as a pseudo-NMI and safely
executes watchdog_notify_pretimeout() without deadlocks.
- Verified that runtime transitions between pretimeout governors in
sysfs execute safely.
- Booted with pseudo-NMIs disabled and confirmed that qcom-wdt detects
unsupported NMI and cleanly falls back to standard IRQ.

Signed-off-by: Mayank Rungta <mrungta@xxxxxxxxxx>
---
Changes in v3:
- In __cleanup_nmi() (Patch 1), serialized teardown under desc->request_mutex
matching __free_irq(), preventing concurrent request_nmi() from racing with
teardown.
- In __cleanup_nmi() (Patch 1), kept desc->action intact across
__synchronize_hardirq() to prevent lockless NMI handlers on other CPUs
from encountering a NULL pointer.
- In __cleanup_nmi() (Patch 1), moved irq_proc_update_valid() under
desc->lock in the second phase so it observes desc->action == NULL.
- In qcom-wdt (Patch 5), enabled the NMI once during probe (enable_nmi())
to balance IRQF_NO_AUTOEN and removed interrupt enable/disable calls
from qcom_wdt_start() / qcom_wdt_stop(), avoiding unbalanced enable
warnings on WDIOC_SETTIMEOUT / WDIOC_SETPRETIMEOUT (Douglas Anderson).
- In qcom-wdt (Patch 5), simplified teardown to unconditionally call
disable_nmi() and free_nmi(), dropping is_nmi tracking and watchdog_active()
checks.
- Link to v2: https://lore.kernel.org/r/20260828-qcom-wdt-nmi-series-v2-0-363979fe6b6b@xxxxxxxxxx

Changes in v2:
- Added patch to require ->irq_get_irqchip_state() for NMI-capable
controllers in irq_supports_nmi(), and synchronize in-flight NMI
handlers via __synchronize_hardirq() in __cleanup_nmi() to prevent
use-after-free races during teardown.
- Added patch implementing synchronous disable_nmi() wrapping
disable_irq().
- Exported disable_nmi() alongside other NMI APIs in genirq export patch.
- Re-ordered series to cluster genirq core changes (patches 1-3) followed
by watchdog core and driver changes (patches 4-5).
- Fixed compiler warnings in watchdog pretimeout RCU patch by adding const
qualifiers to local governor pointers.
- Dropped `irq_enabled` tracking from struct qcom_wdt in patch 5 since
watchdog_dev.c strictly pairs ops->start and ops->stop calls.
- Used disable_nmi() in qcom_wdt_disable_irq() for synchronous stop.
- Link to v1: https://lore.kernel.org/r/20260730-qcom-wdt-nmi-series-v1-0-3aa86d162914@xxxxxxxxxx

---
Mayank Rungta (5):
genirq: Synchronize in-flight handlers during NMI teardown
genirq: Implement synchronous disable_nmi()
genirq: Export NMI APIs
watchdog: pretimeout: Protect governor access with RCU for NMI safety
watchdog: qcom: Register pretimeout interrupt as NMI

drivers/watchdog/qcom-wdt.c | 33 +++++++++++++++++++---
drivers/watchdog/watchdog_pretimeout.c | 45 +++++++++++++++++-------------
include/linux/interrupt.h | 1 +
include/linux/watchdog.h | 2 +-
kernel/irq/manage.c | 51 ++++++++++++++++++++++++++++++----
5 files changed, 101 insertions(+), 31 deletions(-)
---
base-commit: 77ae27fd98f3b548797c9f22c10ab5cf1c4ada53
change-id: 20260724-qcom-wdt-nmi-series-06a48da7b415

Best regards,
--
Mayank Rungta <mrungta@xxxxxxxxxx>