From: Shrikanth Hegde <sshegde@linux.ibm.com>
To: "Mukesh Kumar Chaurasiya (IBM)" <mkchauras@gmail.com>,
maddy@linux.ibm.com, mpe@ellerman.id.au, npiggin@gmail.com,
chleroy@kernel.org, ritesh.list@gmail.com,
mkchauras@linux.ibm.com, ruanjinjie@huawei.com,
linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org
Cc: Venkat Rao Bagalkote <venkat88@linux.ibm.com>
Subject: Re: [PATCH] powerpc: fix NMI exit ordering: restore soft masks after irqentry_nmi_exit()
Date: Tue, 29 Sep 2026 15:14:06 +0530 [thread overview]
Message-ID: <9a2c2187-f0ea-42e1-a9da-81088f5065ac@linux.ibm.com> (raw)
In-Reply-To: <20260929071600.2963954-1-mkchauras@gmail.com>
Hi Mukesh.
On 9/29/26 12:46 PM, Mukesh Kumar Chaurasiya (IBM) wrote:
> When running with CONFIG_PPC_IRQ_SOFT_MASK_DEBUG=y and LOCKDEP=y, an
> Oops is triggered during NMI exit:
>
> [ 202.258332] Oops: Exception in kernel mode, sig: 4 [#1]
> NIP [000000000003e178] 0x3e178
> LR [c00000000003e174] arch_local_irq_restore+0x2a4/0x328
> TRAP: 0700 MSR: 0000000000081000 <ME>
>
> The faulting instruction at NIP is a 'trap' (0fe00000) inside the
> rfi_flush_fallback trampoline at a userspace-looking low address, reached
> after a bad rfid caused by an incorrect SRR0 value.
>
> Root cause
> ----------
> DEFINE_INTERRUPT_HANDLER_NMI used to call arch_interrupt_nmi_exit_prepare()
> *before* irqentry_nmi_exit(), giving this sequence:
>
> arch_interrupt_nmi_enter_prepare() // saves irq_soft_mask, irq_happened
> irqentry_nmi_enter() // __nmi_enter() -> nmi_count++, in_nmi()=true
> ____func(regs) // NMI handler body
> arch_interrupt_nmi_exit_prepare() // RESTORES irq_soft_mask=0 (IRQS_ENABLED)
> // RESTORES irq_happened with pending bits
> irqentry_nmi_exit() // instrumentation block runs here...
> trace_hardirqs_on_prepare() // ...with in_nmi()==true still
> lockdep_hardirqs_on_prepare() // ...and irq_soft_mask already restored to 0
> -> arch_local_irq_restore(0) // mask=0 -> enable path entered
> WARN_ON_ONCE(in_nmi()) // FIRES: __nmi_exit() hasn't run yet
> __nmi_exit() // nmi_count-- (too late)
>
> arch_interrupt_nmi_exit_prepare() restores irq_soft_mask to whatever
> the interrupted thread had (IRQS_ENABLED / 0) and restores irq_happened
> with any pending deferred-interrupt bits that were present when the NMI
> fired. This is correct and necessary before rfid back to the interrupted
> context, but it must not happen until irqentry_nmi_exit() has fully
> completed.
>
> With irq_soft_mask=0 and pending bits in irq_happened, the
> trace_hardirqs_on_prepare() call inside irqentry_nmi_exit()'s
> instrumentation block reaches lockdep_hardirqs_on_prepare() which
> calls __trace_hardirqs_on_caller(), which eventually calls
> arch_local_irq_restore(0) (the IRQS_ENABLED / enable path).
>
> arch_local_irq_restore() with mask=0 hits the CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
> guards at irq_64.c:217:
>
> WARN_ON_ONCE(in_nmi()); // TRUE: __nmi_exit() not yet called
>
> The WARN_ON_ONCE fires a 'trap' instruction (tw 31,0,0 / 0fe00000) in
> kernel mode with MSR_PR=0, MSR_IR=0 (real-mode). The program check
> handler (TRAP 0700) takes the sig:4 (SIGILL) path via do_program_check()
> and calls die(), producing the Oops.
>
> The RESTART_TABLE mechanism in arch_local_irq_restore then causes the
> bad rfid that lands at the userspace-looking address visible in the NIP.
>
> The bug is invisible with LOCKDEP=n because trace_hardirqs_on_prepare()
> is a no-op when CONFIG_TRACE_IRQFLAGS is not set (TRACE_IRQFLAGS is
> selected by PROVE_LOCKING which selects LOCKDEP).
>
> Fix
> ---
> Move arch_interrupt_nmi_exit_prepare() to after the irqentry_nmi_exit()
> block, so that:
>
> irqentry_nmi_exit() // __nmi_exit() -> nmi_count--, in_nmi()=false
> arch_interrupt_nmi_exit_prepare() // now safe to restore soft mask state
>
> The instrumentation inside irqentry_nmi_exit() now executes while
> in_nmi() is still true (nmi_count not yet decremented), but
> irq_soft_mask is still IRQS_ALL_DISABLED (NMI-entry value), so
> arch_local_irq_restore() is never called with mask=0 from that path.
> After __nmi_exit() returns, arch_interrupt_nmi_exit_prepare() restores
> the pre-NMI soft mask and irq_happened, which is the correct state for
> the rfid back to the interrupted context.
>
> Reported-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com>
> Closes: https://lore.kernel.org/all/d4cccba9-ce5c-424b-864c-2248fb0d99e6@linux.ibm.com/
> Fixes: bee25f97ad24 ("powerpc: Enable GENERIC_ENTRY feature")
> Signed-off-by: Mukesh Kumar Chaurasiya (IBM) <mkchauras@gmail.com>
> ---
> arch/powerpc/include/asm/interrupt.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/powerpc/include/asm/interrupt.h b/arch/powerpc/include/asm/interrupt.h
> index 1b45a49e9bed..56f855c6f07e 100644
> --- a/arch/powerpc/include/asm/interrupt.h
> +++ b/arch/powerpc/include/asm/interrupt.h
> @@ -301,7 +301,6 @@ interrupt_handler long func(struct pt_regs *regs) \
> state = irqentry_nmi_enter(regs); \
> } \
> ret = ____##func (regs); \
> - arch_interrupt_nmi_exit_prepare(regs, &nmi_state); \
> if (mfmsr() & MSR_DR) { \
> /* nmi_exit if relocations are on */ \
> irqentry_nmi_exit(regs, state); \
> @@ -317,6 +316,7 @@ interrupt_handler long func(struct pt_regs *regs) \
> } else { \
> irqentry_nmi_exit(regs, state); \
> } \
> + arch_interrupt_nmi_exit_prepare(regs, &nmi_state); \
> \
> return ret; \
> } \
Thanks for the fix.
Ordering also seems right now visually and it reflects similar to code previous
to generic entry.
arch_interrupt_nmi_enter_prepare
irqentry_nmi_enter
irqentry_nmi_exit
arch_interrupt_nmi_exit_prepare
So,
Reviewed-by: Shrikanth Hegde <sshegde@linux.ibm.com>
prev parent reply other threads:[~2026-09-29 9:44 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-29 7:16 Mukesh Kumar Chaurasiya (IBM)
2026-09-29 8:50 ` Venkat Rao Bagalkote
2026-09-29 9:44 ` Shrikanth Hegde [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9a2c2187-f0ea-42e1-a9da-81088f5065ac@linux.ibm.com \
--to=sshegde@linux.ibm.com \
--cc=chleroy@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=maddy@linux.ibm.com \
--cc=mkchauras@gmail.com \
--cc=mkchauras@linux.ibm.com \
--cc=mpe@ellerman.id.au \
--cc=npiggin@gmail.com \
--cc=ritesh.list@gmail.com \
--cc=ruanjinjie@huawei.com \
--cc=venkat88@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®