diff options
author | Andi Kleen <ak@suse.de> | 2006-12-06 20:14:07 -0500 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-12-06 20:14:07 -0500 |
commit | d15512f442ef1ea60f6195b0444fb27b3cf8d0e6 (patch) | |
tree | 71764761d19509d5ffcea0b6ef9965a2f489691c /arch/i386/kernel | |
parent | e6536c1262c56d302e749ab1b44fdb0b9786327d (diff) |
[PATCH] i386: Fix race in IO-APIC routing entry setup.
Interrupt could happen between setting the IO-APIC entry
and setting its interrupt data.
Pointed out by Linus.
Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch/i386/kernel')
-rw-r--r-- | arch/i386/kernel/io_apic.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 3b7a63e0ed1a..e33b7a845299 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c | |||
@@ -153,14 +153,20 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin) | |||
153 | * the interrupt, and we need to make sure the entry is fully populated | 153 | * the interrupt, and we need to make sure the entry is fully populated |
154 | * before that happens. | 154 | * before that happens. |
155 | */ | 155 | */ |
156 | static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) | 156 | static void |
157 | __ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) | ||
157 | { | 158 | { |
158 | unsigned long flags; | ||
159 | union entry_union eu; | 159 | union entry_union eu; |
160 | eu.entry = e; | 160 | eu.entry = e; |
161 | spin_lock_irqsave(&ioapic_lock, flags); | ||
162 | io_apic_write(apic, 0x11 + 2*pin, eu.w2); | 161 | io_apic_write(apic, 0x11 + 2*pin, eu.w2); |
163 | io_apic_write(apic, 0x10 + 2*pin, eu.w1); | 162 | io_apic_write(apic, 0x10 + 2*pin, eu.w1); |
163 | } | ||
164 | |||
165 | static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) | ||
166 | { | ||
167 | unsigned long flags; | ||
168 | spin_lock_irqsave(&ioapic_lock, flags); | ||
169 | __ioapic_write_entry(apic, pin, e); | ||
164 | spin_unlock_irqrestore(&ioapic_lock, flags); | 170 | spin_unlock_irqrestore(&ioapic_lock, flags); |
165 | } | 171 | } |
166 | 172 | ||
@@ -1360,8 +1366,8 @@ static void __init setup_IO_APIC_irqs(void) | |||
1360 | if (!apic && (irq < 16)) | 1366 | if (!apic && (irq < 16)) |
1361 | disable_8259A_irq(irq); | 1367 | disable_8259A_irq(irq); |
1362 | } | 1368 | } |
1363 | ioapic_write_entry(apic, pin, entry); | ||
1364 | spin_lock_irqsave(&ioapic_lock, flags); | 1369 | spin_lock_irqsave(&ioapic_lock, flags); |
1370 | __ioapic_write_entry(apic, pin, entry); | ||
1365 | set_native_irq_info(irq, TARGET_CPUS); | 1371 | set_native_irq_info(irq, TARGET_CPUS); |
1366 | spin_unlock_irqrestore(&ioapic_lock, flags); | 1372 | spin_unlock_irqrestore(&ioapic_lock, flags); |
1367 | } | 1373 | } |
@@ -2856,8 +2862,8 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a | |||
2856 | if (!ioapic && (irq < 16)) | 2862 | if (!ioapic && (irq < 16)) |
2857 | disable_8259A_irq(irq); | 2863 | disable_8259A_irq(irq); |
2858 | 2864 | ||
2859 | ioapic_write_entry(ioapic, pin, entry); | ||
2860 | spin_lock_irqsave(&ioapic_lock, flags); | 2865 | spin_lock_irqsave(&ioapic_lock, flags); |
2866 | __ioapic_write_entry(ioapic, pin, entry); | ||
2861 | set_native_irq_info(irq, TARGET_CPUS); | 2867 | set_native_irq_info(irq, TARGET_CPUS); |
2862 | spin_unlock_irqrestore(&ioapic_lock, flags); | 2868 | spin_unlock_irqrestore(&ioapic_lock, flags); |
2863 | 2869 | ||