Re: [PATCH 2/2] alpha: annotate hardirqs-off on IPL 7 interrupt entry

Magnus Lindholm <[email protected]>
Newsgroups org.kernel.vger.linux-alpha,org.kernel.vger.linux-kernel
Message-ID <CA+=Fv5SWCg0BcJsEY2tA95tb5CY=EPwm2ZG8CCY9m=06ngz+aQ@mail.gmail.com>
On Mon, Aug 10, 2026 at 10:28 PM Matt Turner <[email protected]> wrote:
>
> do_entInt() opens with local_irq_disable(), which with
> CONFIG_TRACE_IRQFLAGS only calls trace_hardirqs_off() if interrupts were
> not already off:
>
>         #define local_irq_disable()                             \
>                 do {                                            \
>                         bool was_disabled = raw_irqs_disabled();\
>                         raw_local_irq_disable();                \
>                         if (!was_disabled)                      \
>                                 trace_hardirqs_off();           \
>                 } while (0)
>
> On alpha raw_irqs_disabled() is (rdps() & 7) == IPL_MAX, i.e. IPL 7.
> PALcode raises PS.IPL to the level of the interrupt before entInt runs,
> so for an IPL 7 entry - a processor machine check (vector 0x660) or a
> system event (vector 0x680), both IPL_MCHECK == IPL_MAX - the gate is
> already true and the annotation is skipped.  lockdep keeps whatever
> hardirq state the interrupted context had.  If that context had
> interrupts enabled, lockdep believes they are still enabled for the
> duration of the handler, and every lockdep_assert_irqs_disabled() in the
> interrupt path fires:
>
>   WARNING: kernel/context_tracking.c:346 at ct_irq_enter+0xc4/0xd0, CPU#0: swapper/0/0
>   [...]
>   [<fffffc0001ef74d4>] ct_irq_enter+0xc4/0xd0
>   [<fffffc000105ebd0>] irq_enter+0x20/0x50
>   [<fffffc000103707c>] do_entInt+0x1dc/0x2e0
>   [<fffffc0001031d60>] ret_from_exception+0x0/0x10
>
>   irq event stamp: 735356346
>   hardirqs last  enabled at (735356346): trace_hardirqs_on+0x68/0x220
>   hardirqs last disabled at (735356345): do_idle+0xf0/0x270
>
> The stamps show the problem directly: the most recent event is the
> enable from the interrupted idle loop, and do_entInt() recorded no
> disable at all.  ct_irq_exit() warns the same way on the way out.
>
> Ordinary device interrupts arrive at IPL 3-5 and IPIs and performance
> counter interrupts at IPL 6, so was_disabled is false for them and the
> annotation happens normally.  Only the two IPL 7 vectors are affected,
> which is why this needs an environmental event to show up.
>
> Take the hardware IPL out of the decision and drive the annotation from
> lockdep's own state instead.
>
> This corrects the annotation only.  An IPL 7 event can also interrupt a
> region that has legitimately disabled interrupts, where irq_enter() and
> irq_exit() are not the right primitives and NMI semantics are needed;
> that is a larger change and is left alone here.
>
> Tested on an AlphaServer ES47 (Marvel/EV7) by injecting system events
> through the system management path: fifteen injections, idle and under
> load, with no splat.  The same injection on a freshly booted kernel
> without this change reproduces both warnings.
>
> Signed-off-by: Matt Turner <[email protected]>
> ---
>  arch/alpha/kernel/irq_alpha.c | 13 ++++++++++++-
>  1 file changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c
> index cb4d58079d83..014c1e98e922 100644
> --- a/arch/alpha/kernel/irq_alpha.c
> +++ b/arch/alpha/kernel/irq_alpha.c
> @@ -52,8 +52,19 @@ do_entInt(unsigned long type, unsigned long vector,
>          * Note that there is no matching local_irq_enable() due to
>          * severe problems with RTI at IPL0 and some MILO PALcode
>          * (namely LX164).
> +        *
> +        * PALcode has already raised PS.IPL to the level of the interrupt
> +        * being delivered.  For an IPL 7 entry - a machine check or a system
> +        * event - that is IPL_MAX, which is what arch_irqs_disabled() tests
> +        * for, so local_irq_disable() would decide interrupts were already
> +        * off and skip trace_hardirqs_off().  lockdep would then spend the
> +        * whole handler believing interrupts are enabled.  Drive the
> +        * annotation from lockdep's own state rather than the hardware IPL.
>          */
> -       local_irq_disable();
> +       raw_local_irq_disable();
> +       if (lockdep_hardirqs_enabled())
> +               trace_hardirqs_off();
> +
>         old_regs = set_irq_regs(regs);
>
>         switch (type) {
> --

Hi Matt,

Nice catch! On an SMP AlphaServer ES40 with GENERIC_ENTRY and lockdep enabled,
a PSU state change generates vector 0x680 and reliably triggers the
lockdep/check_flags
and ct_irq_enter warnings without this patch. With the patch applied,
repeated PSU state
changes generate the expected 0x680 reports without any lockdep warnings.

I also exercised normal IRQ traffic under load; lockdep remained enabled with no
redundant hardirq transitions or other regressions.

For verbose machine checks on tsunami I had also applies this patch:
https://lore.kernel.org/linux-alpha/[email protected]/

Reviewed-by: Magnus Lindholm <[email protected]>
Tested-by: Magnus Lindholm <[email protected]>

Thanks,
Magnus
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.