mirror-linux/kernel/irq
Mark Rutland 512718bbc5 genirq/chip: Don't call add_interrupt_randomness() for NMIs
Recently handle_percpu_devid_irq() was changed to call
add_interrupt_randomness(). This introduced a potential deadlock when
handle_percpu_devid_irq() is used to handle an NMI, which can be
detected with lockdep, e.g.

    ================================
    WARNING: inconsistent lock state
    7.1.0-rc2-pnmi #465 Not tainted
    --------------------------------
    inconsistent {INITIAL USE} -> {IN-NMI} usage.
    perf/695 [HC1[1]:SC0[0]:HE0:SE1] takes:
    ffff00837dfd3a18 (&base->lock){-.-.}-{2:2}, at: lock_timer_base+0x6c/0xac
    {INITIAL USE} state was registered at:
      _raw_spin_lock_irqsave+0x68/0xb0
      lock_timer_base+0x6c/0xac
      __mod_timer+0x100/0x32c
      add_timer_global+0x2c/0x40
      __queue_delayed_work+0xf0/0x140
      queue_delayed_work_on+0x134/0x138
      mem_cgroup_css_online+0x30c/0x310
      online_css+0x34/0x10c
      cgroup_init_subsys+0x158/0x1c8
      cgroup_init+0x440/0x524
      start_kernel+0x888/0x998

    other info that might help us debug this:
    Possible unsafe locking scenario:
           CPU0
           ----
      lock(&base->lock);
      <Interrupt>
        lock(&base->lock);
        *** DEADLOCK ***

    Call trace:
     _raw_spin_lock_irqsave+0x68/0xb0
     lock_timer_base+0x6c/0xac
     add_timer_on+0x78/0x16c
     add_interrupt_randomness+0x124/0x134
     handle_percpu_devid_irq+0xd4/0x16c
     handle_irq_desc+0x40/0x58
     generic_handle_domain_nmi+0x28/0x50
     __gic_handle_nmi.isra.0+0x4c/0xa0
     gic_handle_irq+0x38/0x2bc
     call_on_irq_stack+0x30/0x48
     do_interrupt_handler+0x80/0x98
     el1_interrupt+0x90/0xac
     el1h_64_irq_handler+0x18/0x24
     el1h_64_irq+0x80/0x84
     [...]

During review, Thomas pointed out it wouldn't be safe for
handle_percpu_devid_irq() to call add_interrupt_randomness() if it was
used to handle NMIs:

  https://lore.kernel.org/lkml/87bjgik042.ffs@tglx/

... but evidently people missed that handle_percpu_devid_irq() *is* used
for NMIs.

While it might seem that NMIs should be handled with a separate
handle_percpu_devid_nmi() function, for various structural reasons this was
impractical, and handle_percpu_devid_irq() has been expected to be used for
NMIs since commits:

  21bbbc50f3 ("irqchip/gic-v3: Switch high priority PPIs over to handle_percpu_devid_irq()")
  5ff78c8de9 ("genirq: Kill handle_percpu_devid_fasteoi_nmi()")

Taking the above into account, avoid the deadlock by not calling
add_interrupt_randomness() when handle_percpu_devid_irq() is called in an
NMI context. This is consistent with other NNI handling flows, which do not
call add_interrupt_randomness().

At the same time, update the kernel-doc comment to make it clear that
handle_percpu_devid_irq() can be called in NMI context. The rest of
handle_percpu_devid_irq() is currently NMI safe and doesn't need to change.

Fixes: fd7400cfcb ("genirq/chip: Invoke add_interrupt_randomness() in handle_percpu_devid_irq()")
Reported-by: Ada Couprie Diaz <ada.coupriediaz@arm.com>
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Reviewed-by: Jinjie Ruan <ruanjinjie@huawei.com>
Reviewed-by: Marc Zyngier <maz@kernel.org>
Link: https://patch.msgid.link/20260507110518.3128248-1-mark.rutland@arm.com
2026-05-11 14:56:04 +02:00
..
Kconfig genirq: Remove IRQ timing tracking infrastructure 2025-12-15 22:20:50 +01:00
Makefile genirq: Remove IRQ timing tracking infrastructure 2025-12-15 22:20:50 +01:00
affinity.c genirq/affinity: Remove cpus_read_lock() while reading cpu_possible_mask 2026-04-01 16:09:05 +02:00
autoprobe.c genirq/autoprobe: Switch to lock guards 2025-05-07 09:08:11 +02:00
chip.c genirq/chip: Don't call add_interrupt_randomness() for NMIs 2026-05-11 14:56:04 +02:00
cpuhotplug.c genirq/cpuhotplug: Notify about affinity changes breaking the affinity mask 2026-01-13 21:18:16 +01:00
debug.h
debugfs.c treewide: Update email address 2026-01-11 06:09:11 -10:00
devres.c genirq/devres: Add error handling in devm_request_*_irq() 2025-08-24 13:00:45 +02:00
dummychip.c irq: Fix typos in comments 2021-03-22 04:23:14 +01:00
generic-chip.c Convert 'alloc_flex' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
handle.c genirq: Remove IRQ timing tracking infrastructure 2025-12-15 22:20:50 +01:00
internals.h genirq/cpuhotplug: Notify about affinity changes breaking the affinity mask 2026-01-13 21:18:16 +01:00
ipi-mux.c genirq/ipi-mux: Use irq_domain_alloc_irqs() 2023-02-06 17:21:15 +00:00
ipi.c genirq/ipi: Fix NULL pointer deref in irq_data_get_affinity_mask() 2023-02-20 13:53:41 +01:00
irq_sim.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
irq_test.c genirq/test: Ensure CPU 1 is online for hotplug test 2025-09-03 17:04:52 +02:00
irqdesc.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
irqdomain.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
kexec.c genirq/kexec: Prevent redundant IRQ masking by checking state before shutdown 2024-12-11 20:32:34 +01:00
manage.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
matrix.c genirq/matrix, LoongArch: Delete IRQ_MATRIX_BITS leftovers 2026-03-17 10:57:03 +01:00
migration.c genirq/migration: Use irqd_get_parent_data() in irq_force_complete_move() 2025-04-04 17:08:36 +02:00
msi.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
pm.c syscore: Pass context data to callbacks 2025-11-14 10:01:52 +01:00
proc.c genirq/proc: Replace snprintf with strscpy in register_handler_proc 2026-01-30 08:53:53 +01:00
resend.c genirq/resend: Switch to lock guards 2025-05-07 09:08:11 +02:00
settings.h genirq: Remove IRQ_MOVE_PCNTXT and related code 2025-01-15 21:38:53 +01:00
spurious.c genirq: Move irq_wait_for_poll() to call site 2025-07-22 14:30:42 +02:00