aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2006-12-06 20:14:07 -0500
committerAndi Kleen <andi@basil.nowhere.org>2006-12-06 20:14:07 -0500
commit516d2836434d279fef164bb1b964e83425d312d2 (patch)
tree924d47d91b7f75d407aa869dee2650102cc46a95
parentd15512f442ef1ea60f6195b0444fb27b3cf8d0e6 (diff)
[PATCH] x86-64: 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>
-rw-r--r--arch/x86_64/kernel/io_apic.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 88fcc4ebbf6e..eaf0b708e67d 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -174,14 +174,20 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
174 * the interrupt, and we need to make sure the entry is fully populated 174 * the interrupt, and we need to make sure the entry is fully populated
175 * before that happens. 175 * before that happens.
176 */ 176 */
177static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) 177static void
178__ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
178{ 179{
179 unsigned long flags;
180 union entry_union eu; 180 union entry_union eu;
181 eu.entry = e; 181 eu.entry = e;
182 spin_lock_irqsave(&ioapic_lock, flags);
183 io_apic_write(apic, 0x11 + 2*pin, eu.w2); 182 io_apic_write(apic, 0x11 + 2*pin, eu.w2);
184 io_apic_write(apic, 0x10 + 2*pin, eu.w1); 183 io_apic_write(apic, 0x10 + 2*pin, eu.w1);
184}
185
186static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
187{
188 unsigned long flags;
189 spin_lock_irqsave(&ioapic_lock, flags);
190 __ioapic_write_entry(apic, pin, e);
185 spin_unlock_irqrestore(&ioapic_lock, flags); 191 spin_unlock_irqrestore(&ioapic_lock, flags);
186} 192}
187 193