diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2016-01-14 02:43:38 -0500 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2016-01-15 07:43:58 -0500 |
| commit | e23b257c293ce4bcc8cabb2aa3097b6ed8a8261a (patch) | |
| tree | e05376f96aaa28babe15029771536483dbf3c108 | |
| parent | 7030a7e9321166eef44c811fe4af4d460360d424 (diff) | |
x86/irq: Call chip->irq_set_affinity in proper context
setup_ioapic_dest() calls irqchip->irq_set_affinity() completely
unprotected. That's wrong in several aspects:
- it opens a race window where irq_set_affinity() can be interrupted and the
irq chip left in unconsistent state.
- it triggers a lockdep splat when we fix the vector race for 4.3+ because
vector lock is taken with interrupts enabled.
The proper calling convention is irq descriptor lock held and interrupts
disabled.
Reported-and-tested-by: Borislav Petkov <bp@alien8.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Jiang Liu <jiang.liu@linux.intel.com>
Cc: Jeremiah Mahler <jmmahler@gmail.com>
Cc: andy.shevchenko@gmail.com
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Joe Lawrence <joe.lawrence@stratus.com>
Cc: stable@vger.kernel.org
Link: http://lkml.kernel.org/r/alpine.DEB.2.11.1601140919420.3575@nanos
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
| -rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index f25321894ad2..fdb0fbfb1197 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
| @@ -2521,6 +2521,7 @@ void __init setup_ioapic_dest(void) | |||
| 2521 | { | 2521 | { |
| 2522 | int pin, ioapic, irq, irq_entry; | 2522 | int pin, ioapic, irq, irq_entry; |
| 2523 | const struct cpumask *mask; | 2523 | const struct cpumask *mask; |
| 2524 | struct irq_desc *desc; | ||
| 2524 | struct irq_data *idata; | 2525 | struct irq_data *idata; |
| 2525 | struct irq_chip *chip; | 2526 | struct irq_chip *chip; |
| 2526 | 2527 | ||
| @@ -2536,7 +2537,9 @@ void __init setup_ioapic_dest(void) | |||
| 2536 | if (irq < 0 || !mp_init_irq_at_boot(ioapic, irq)) | 2537 | if (irq < 0 || !mp_init_irq_at_boot(ioapic, irq)) |
| 2537 | continue; | 2538 | continue; |
| 2538 | 2539 | ||
| 2539 | idata = irq_get_irq_data(irq); | 2540 | desc = irq_to_desc(irq); |
| 2541 | raw_spin_lock_irq(&desc->lock); | ||
| 2542 | idata = irq_desc_get_irq_data(desc); | ||
| 2540 | 2543 | ||
| 2541 | /* | 2544 | /* |
| 2542 | * Honour affinities which have been set in early boot | 2545 | * Honour affinities which have been set in early boot |
| @@ -2550,6 +2553,7 @@ void __init setup_ioapic_dest(void) | |||
| 2550 | /* Might be lapic_chip for irq 0 */ | 2553 | /* Might be lapic_chip for irq 0 */ |
| 2551 | if (chip->irq_set_affinity) | 2554 | if (chip->irq_set_affinity) |
| 2552 | chip->irq_set_affinity(idata, mask, false); | 2555 | chip->irq_set_affinity(idata, mask, false); |
| 2556 | raw_spin_unlock_irq(&desc->lock); | ||
| 2553 | } | 2557 | } |
| 2554 | } | 2558 | } |
| 2555 | #endif | 2559 | #endif |
