summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2007-07-21 17:09:53 +0200
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-21 18:37:07 -0700
commit78b599aed61a1098444558e74c93745f22eda6cb (patch)
treef6132e3cf2a2e39524a5d5edc05161e9682a5811
parent9d531cc1193693f2d2e5ef2532a877481b118be6 (diff)
downloadlinux-78b599aed61a1098444558e74c93745f22eda6cb.tar.bz2
x86_64: Don't rely on a unique IO-APIC ID
Linux 64bit only uses the IO-APIC ID as an internal cookie. In the future there could be some cases where the IO-APIC IDs are not unique because they share an 8 bit space with CPUs and if there are enough CPUs it is difficult to get them that. But Linux needs the io apic ID internally for its data structures. Assign unique IO APIC ids on table parsing. TBD do for 32bit too Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/x86_64/kernel/mpparse.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
index 61ae57eb9e4c..0ec84909d846 100644
--- a/arch/x86_64/kernel/mpparse.c
+++ b/arch/x86_64/kernel/mpparse.c
@@ -649,6 +649,20 @@ static int mp_find_ioapic(int gsi)
return -1;
}
+static u8 uniq_ioapic_id(u8 id)
+{
+ int i;
+ DECLARE_BITMAP(used, 256);
+ bitmap_zero(used, 256);
+ for (i = 0; i < nr_ioapics; i++) {
+ struct mpc_config_ioapic *ia = &mp_ioapics[i];
+ __set_bit(ia->mpc_apicid, used);
+ }
+ if (!test_bit(id, used))
+ return id;
+ return find_first_zero_bit(used, 256);
+}
+
void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
{
int idx = 0;
@@ -656,14 +670,14 @@ void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
if (bad_ioapic(address))
return;
- idx = nr_ioapics++;
+ idx = nr_ioapics;
mp_ioapics[idx].mpc_type = MP_IOAPIC;
mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE;
mp_ioapics[idx].mpc_apicaddr = address;
set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
- mp_ioapics[idx].mpc_apicid = id;
+ mp_ioapics[idx].mpc_apicid = uniq_ioapic_id(id);
mp_ioapics[idx].mpc_apicver = 0;
/*
@@ -680,6 +694,8 @@ void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
mp_ioapics[idx].mpc_apicaddr,
mp_ioapic_routing[idx].gsi_start,
mp_ioapic_routing[idx].gsi_end);
+
+ nr_ioapics++;
}
void __init