Skip to content

Commit df43934

Browse files
KAGA-KOKOIngo Molnar
authored andcommitted
x86/ioapic: Prevent inconsistent state when moving an interrupt
There is an issue with threaded interrupts which are marked ONESHOT and using the fasteoi handler: if (IS_ONESHOT()) mask_irq(); .... cond_unmask_eoi_irq() chip->irq_eoi(); if (setaffinity_pending) { mask_ioapic(); ... move_affinity(); unmask_ioapic(); } So if setaffinity is pending the interrupt will be moved and then unconditionally unmasked at the ioapic level, which is wrong in two aspects: 1) It should be kept masked up to the point where the threaded handler finished. 2) The physical chip state and the software masked state are inconsistent Guard both the mask and the unmask with a check for the software masked state. If the line is marked masked then the ioapic line is also masked, so both mask_ioapic() and unmask_ioapic() can be skipped safely. Signed-off-by: Thomas Gleixner <[email protected]> Cc: Andy Shevchenko <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Sebastian Siewior <[email protected]> Fixes: 3aa551c ("genirq: add threaded interrupt handler support") Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 3b7c59a commit df43934

File tree

1 file changed

+6
-3
lines changed

1 file changed

+6
-3
lines changed

arch/x86/kernel/apic/io_apic.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,9 +1727,10 @@ static bool io_apic_level_ack_pending(struct mp_chip_data *data)
17271727

17281728
static inline bool ioapic_irqd_mask(struct irq_data *data)
17291729
{
1730-
/* If we are moving the irq we need to mask it */
1730+
/* If we are moving the IRQ we need to mask it */
17311731
if (unlikely(irqd_is_setaffinity_pending(data))) {
1732-
mask_ioapic_irq(data);
1732+
if (!irqd_irq_masked(data))
1733+
mask_ioapic_irq(data);
17331734
return true;
17341735
}
17351736
return false;
@@ -1766,7 +1767,9 @@ static inline void ioapic_irqd_unmask(struct irq_data *data, bool masked)
17661767
*/
17671768
if (!io_apic_level_ack_pending(data->chip_data))
17681769
irq_move_masked_irq(data);
1769-
unmask_ioapic_irq(data);
1770+
/* If the IRQ is masked in the core, leave it: */
1771+
if (!irqd_irq_masked(data))
1772+
unmask_ioapic_irq(data);
17701773
}
17711774
}
17721775
#else

0 commit comments

Comments
 (0)