Skip to content

Commit 5fa5595

Browse files
committed
x86/i8259: Mark legacy PIC interrupts with IRQ_LEVEL
Baoquan reported that after triggering a crash the subsequent crash-kernel fails to boot about half of the time. It triggers a NULL pointer dereference in the periodic tick code. This happens because the legacy timer interrupt (IRQ0) is resent in software which happens in soft interrupt (tasklet) context. In this context get_irq_regs() returns NULL which leads to the NULL pointer dereference. The reason for the resend is a spurious APIC interrupt on the IRQ0 vector which is captured and leads to a resend when the legacy timer interrupt is enabled. This is wrong because the legacy PIC interrupts are level triggered and therefore should never be resent in software, but nothing ever sets the IRQ_LEVEL flag on those interrupts, so the core code does not know about their trigger type. Ensure that IRQ_LEVEL is set when the legacy PCI interrupts are set up. Fixes: a4633ad ("[PATCH] genirq: add genirq sw IRQ-retrigger") Reported-by: Baoquan He <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Tested-by: Baoquan He <[email protected]> Link: https://lore.kernel.org/r/87mt6rjrra.ffs@tglx
1 parent 5dc4c99 commit 5fa5595

File tree

2 files changed

+4
-1
lines changed

2 files changed

+4
-1
lines changed

arch/x86/kernel/i8259.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ static void make_8259A_irq(unsigned int irq)
114114
disable_irq_nosync(irq);
115115
io_apic_irqs &= ~(1<<irq);
116116
irq_set_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
117+
irq_set_status_flags(irq, IRQ_LEVEL);
117118
enable_irq(irq);
118119
lapic_assign_legacy_vector(irq, true);
119120
}

arch/x86/kernel/irqinit.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,10 @@ void __init init_ISA_irqs(void)
6565

6666
legacy_pic->init(0);
6767

68-
for (i = 0; i < nr_legacy_irqs(); i++)
68+
for (i = 0; i < nr_legacy_irqs(); i++) {
6969
irq_set_chip_and_handler(i, chip, handle_level_irq);
70+
irq_set_status_flags(i, IRQ_LEVEL);
71+
}
7072
}
7173

7274
void __init init_IRQ(void)

0 commit comments

Comments
 (0)