Skip to content

Commit abc3fce

Browse files
npigginmpe
authored andcommitted
Revert "powerpc/64: irq_work avoid interrupt when called with hardware irqs enabled"
This reverts commit ebb37cf. That commit does not play well with soft-masked irq state manipulations in idle, interrupt replay, and possibly others due to tracing code sometimes using irq_work_queue (e.g., in trace_hardirqs_on()). That can cause PACA_IRQ_DEC to become set when it is not expected, and be ignored or cleared or cause warnings. The net result seems to be missing an irq_work until the next timer interrupt in the worst case which is usually not going to be noticed, however it could be a long time if the tick is disabled, which is against the spirit of irq_work and might cause real problems. The idea is still solid, but it would need more work. It's not really clear if it would be worth added complexity, so revert this for now (not a straight revert, but replace with a comment explaining why we might see interrupts happening, and gives git blame something to find). Fixes: ebb37cf ("powerpc/64: irq_work avoid interrupt when called with hardware irqs enabled") Signed-off-by: Nicholas Piggin <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 6008306 commit abc3fce

File tree

1 file changed

+13
-31
lines changed

1 file changed

+13
-31
lines changed

arch/powerpc/kernel/time.c

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -522,35 +522,6 @@ static inline void clear_irq_work_pending(void)
522522
"i" (offsetof(struct paca_struct, irq_work_pending)));
523523
}
524524

525-
void arch_irq_work_raise(void)
526-
{
527-
preempt_disable();
528-
set_irq_work_pending_flag();
529-
/*
530-
* Non-nmi code running with interrupts disabled will replay
531-
* irq_happened before it re-enables interrupts, so setthe
532-
* decrementer there instead of causing a hardware exception
533-
* which would immediately hit the masked interrupt handler
534-
* and have the net effect of setting the decrementer in
535-
* irq_happened.
536-
*
537-
* NMI interrupts can not check this when they return, so the
538-
* decrementer hardware exception is raised, which will fire
539-
* when interrupts are next enabled.
540-
*
541-
* BookE does not support this yet, it must audit all NMI
542-
* interrupt handlers to ensure they call nmi_enter() so this
543-
* check would be correct.
544-
*/
545-
if (IS_ENABLED(CONFIG_BOOKE) || !irqs_disabled() || in_nmi()) {
546-
set_dec(1);
547-
} else {
548-
hard_irq_disable();
549-
local_paca->irq_happened |= PACA_IRQ_DEC;
550-
}
551-
preempt_enable();
552-
}
553-
554525
#else /* 32-bit */
555526

556527
DEFINE_PER_CPU(u8, irq_work_pending);
@@ -559,16 +530,27 @@ DEFINE_PER_CPU(u8, irq_work_pending);
559530
#define test_irq_work_pending() __this_cpu_read(irq_work_pending)
560531
#define clear_irq_work_pending() __this_cpu_write(irq_work_pending, 0)
561532

533+
#endif /* 32 vs 64 bit */
534+
562535
void arch_irq_work_raise(void)
563536
{
537+
/*
538+
* 64-bit code that uses irq soft-mask can just cause an immediate
539+
* interrupt here that gets soft masked, if this is called under
540+
* local_irq_disable(). It might be possible to prevent that happening
541+
* by noticing interrupts are disabled and setting decrementer pending
542+
* to be replayed when irqs are enabled. The problem there is that
543+
* tracing can call irq_work_raise, including in code that does low
544+
* level manipulations of irq soft-mask state (e.g., trace_hardirqs_on)
545+
* which could get tangled up if we're messing with the same state
546+
* here.
547+
*/
564548
preempt_disable();
565549
set_irq_work_pending_flag();
566550
set_dec(1);
567551
preempt_enable();
568552
}
569553

570-
#endif /* 32 vs 64 bit */
571-
572554
#else /* CONFIG_IRQ_WORK */
573555

574556
#define test_irq_work_pending() 0

0 commit comments

Comments
 (0)