Browse Source

[PATCH] x86_64: serialize assign_irq_vector() use of static variables

Since assign_irq_vector() can be called at runtime, its access of static
variables should be protected by a lock.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Jan Beulich 19 years ago
parent
commit
0a1ad60d7a
2 changed files with 32 additions and 10 deletions
  1. 18 6
      arch/i386/kernel/io_apic.c
  2. 14 4
      arch/x86_64/kernel/io_apic.c

+ 18 - 6
arch/i386/kernel/io_apic.c

@@ -50,6 +50,7 @@ atomic_t irq_mis_count;
 static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
 static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
 
 
 static DEFINE_SPINLOCK(ioapic_lock);
 static DEFINE_SPINLOCK(ioapic_lock);
+static DEFINE_SPINLOCK(vector_lock);
 
 
 int timer_over_8254 __initdata = 1;
 int timer_over_8254 __initdata = 1;
 
 
@@ -1161,10 +1162,16 @@ u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
 int assign_irq_vector(int irq)
 int assign_irq_vector(int irq)
 {
 {
 	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
 	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
+	int vector;
+
+	BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
+
+	spin_lock(&vector_lock);
 
 
-	BUG_ON(irq >= NR_IRQ_VECTORS);
-	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
+	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
+		spin_unlock(&vector_lock);
 		return IO_APIC_VECTOR(irq);
 		return IO_APIC_VECTOR(irq);
+	}
 next:
 next:
 	current_vector += 8;
 	current_vector += 8;
 	if (current_vector == SYSCALL_VECTOR)
 	if (current_vector == SYSCALL_VECTOR)
@@ -1172,16 +1179,21 @@ next:
 
 
 	if (current_vector >= FIRST_SYSTEM_VECTOR) {
 	if (current_vector >= FIRST_SYSTEM_VECTOR) {
 		offset++;
 		offset++;
-		if (!(offset%8))
+		if (!(offset%8)) {
+			spin_unlock(&vector_lock);
 			return -ENOSPC;
 			return -ENOSPC;
+		}
 		current_vector = FIRST_DEVICE_VECTOR + offset;
 		current_vector = FIRST_DEVICE_VECTOR + offset;
 	}
 	}
 
 
-	vector_irq[current_vector] = irq;
+	vector = current_vector;
+	vector_irq[vector] = irq;
 	if (irq != AUTO_ASSIGN)
 	if (irq != AUTO_ASSIGN)
-		IO_APIC_VECTOR(irq) = current_vector;
+		IO_APIC_VECTOR(irq) = vector;
+
+	spin_unlock(&vector_lock);
 
 
-	return current_vector;
+	return vector;
 }
 }
 
 
 static struct hw_interrupt_type ioapic_level_type;
 static struct hw_interrupt_type ioapic_level_type;

+ 14 - 4
arch/x86_64/kernel/io_apic.c

@@ -56,6 +56,7 @@ int timer_over_8254 __initdata = 0;
 static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
 static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
 
 
 static DEFINE_SPINLOCK(ioapic_lock);
 static DEFINE_SPINLOCK(ioapic_lock);
+static DEFINE_SPINLOCK(vector_lock);
 
 
 /*
 /*
  * # of IRQ routing registers
  * # of IRQ routing registers
@@ -834,10 +835,16 @@ u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
 int assign_irq_vector(int irq)
 int assign_irq_vector(int irq)
 {
 {
 	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
 	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
+	int vector;
 
 
 	BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
 	BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
-	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
+
+	spin_lock(&vector_lock);
+
+	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
+		spin_unlock(&vector_lock);
 		return IO_APIC_VECTOR(irq);
 		return IO_APIC_VECTOR(irq);
+	}
 next:
 next:
 	current_vector += 8;
 	current_vector += 8;
 	if (current_vector == IA32_SYSCALL_VECTOR)
 	if (current_vector == IA32_SYSCALL_VECTOR)
@@ -849,11 +856,14 @@ next:
 		current_vector = FIRST_DEVICE_VECTOR + offset;
 		current_vector = FIRST_DEVICE_VECTOR + offset;
 	}
 	}
 
 
-	vector_irq[current_vector] = irq;
+	vector = current_vector;
+	vector_irq[vector] = irq;
 	if (irq != AUTO_ASSIGN)
 	if (irq != AUTO_ASSIGN)
-		IO_APIC_VECTOR(irq) = current_vector;
+		IO_APIC_VECTOR(irq) = vector;
+
+	spin_unlock(&vector_lock);
 
 
-	return current_vector;
+	return vector;
 }
 }
 
 
 extern void (*interrupt[NR_IRQS])(void);
 extern void (*interrupt[NR_IRQS])(void);