Skip to content

Commit 7d65f9e

Browse files
KAGA-KOKOsuryasaimadhu
authored andcommitted
x86/apic: Mark _all_ legacy interrupts when IO/APIC is missing
PIC interrupts do not support affinity setting and they can end up on any online CPU. Therefore, it's required to mark the associated vectors as system-wide reserved. Otherwise, the corresponding irq descriptors are copied to the secondary CPUs but the vectors are not marked as assigned or reserved. This works correctly for the IO/APIC case. When the IO/APIC is disabled via config, kernel command line or lack of enumeration then all legacy interrupts are routed through the PIC, but nothing marks them as system-wide reserved vectors. As a consequence, a subsequent allocation on a secondary CPU can result in allocating one of these vectors, which triggers the BUG() in apic_update_vector() because the interrupt descriptor slot is not empty. Imran tried to work around that by marking those interrupts as allocated when a CPU comes online. But that's wrong in case that the IO/APIC is available and one of the legacy interrupts, e.g. IRQ0, has been switched to PIC mode because then marking them as allocated will fail as they are already marked as system vectors. Stay consistent and update the legacy vectors after attempting IO/APIC initialization and mark them as system vectors in case that no IO/APIC is available. Fixes: 69cde00 ("x86/vector: Use matrix allocator for vector assignment") Reported-by: Imran Khan <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Cc: [email protected] Link: https://lkml.kernel.org/r/[email protected]
1 parent c468154 commit 7d65f9e

File tree

3 files changed

+22
-0
lines changed

3 files changed

+22
-0
lines changed

arch/x86/include/asm/apic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ static inline int apic_is_clustered_box(void)
174174
extern int setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask);
175175
extern void lapic_assign_system_vectors(void);
176176
extern void lapic_assign_legacy_vector(unsigned int isairq, bool replace);
177+
extern void lapic_update_legacy_vectors(void);
177178
extern void lapic_online(void);
178179
extern void lapic_offline(void);
179180
extern bool apic_needs_pit(void);

arch/x86/kernel/apic/apic.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2604,6 +2604,7 @@ static void __init apic_bsp_setup(bool upmode)
26042604
end_local_APIC_setup();
26052605
irq_remap_enable_fault_handling();
26062606
setup_IO_APIC();
2607+
lapic_update_legacy_vectors();
26072608
}
26082609

26092610
#ifdef CONFIG_UP_LATE_INIT

arch/x86/kernel/apic/vector.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,26 @@ void lapic_assign_legacy_vector(unsigned int irq, bool replace)
738738
irq_matrix_assign_system(vector_matrix, ISA_IRQ_VECTOR(irq), replace);
739739
}
740740

741+
void __init lapic_update_legacy_vectors(void)
742+
{
743+
unsigned int i;
744+
745+
if (IS_ENABLED(CONFIG_X86_IO_APIC) && nr_ioapics > 0)
746+
return;
747+
748+
/*
749+
* If the IO/APIC is disabled via config, kernel command line or
750+
* lack of enumeration then all legacy interrupts are routed
751+
* through the PIC. Make sure that they are marked as legacy
752+
* vectors. PIC_CASCADE_IRQ has already been marked in
753+
* lapic_assign_system_vectors().
754+
*/
755+
for (i = 0; i < nr_legacy_irqs(); i++) {
756+
if (i != PIC_CASCADE_IR)
757+
lapic_assign_legacy_vector(i, true);
758+
}
759+
}
760+
741761
void __init lapic_assign_system_vectors(void)
742762
{
743763
unsigned int i, vector = 0;

0 commit comments

Comments
 (0)