aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2012-03-12 14:36:33 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-04-02 12:27:10 -0400
commitc2ec63edaf48c90c3495eeb0b75bb05102fbf71a (patch)
tree085c4f399818be95bec7931c8dcce482a8082b7f /arch/x86/kernel/apic
parentec97d16dc99a40232f7c6ea7dc36b4819be3790e (diff)
x86/ioapic: Add register level checks to detect bogus io-apic entries
commit 73d63d038ee9f769f5e5b46792d227fe20e442c5 upstream. With the recent changes to clear_IO_APIC_pin() which tries to clear remoteIRR bit explicitly, some of the users started to see "Unable to reset IRR for apic .." messages. Close look shows that these are related to bogus IO-APIC entries which return's all 1's for their io-apic registers. And the above mentioned error messages are benign. But kernel should have ignored such io-apic's in the first place. Check if register 0, 1, 2 of the listed io-apic are all 1's and ignore such io-apic. Reported-by: Álvaro Castillo <midgoon@gmail.com> Tested-by: Jon Dufresne <jon@jondufresne.org> Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Cc: yinghai@kernel.org Cc: kernel-team@fedoraproject.org Cc: Josh Boyer <jwboyer@redhat.com> Link: http://lkml.kernel.org/r/1331577393.31585.94.camel@sbsiddha-desk.sc.intel.com [ Performed minor cleanup of affected code. ] Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch/x86/kernel/apic')
-rw-r--r--arch/x86/kernel/apic/io_apic.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index e5293394b54..16e9d94bfdd 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3927,18 +3927,36 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi)
3927static __init int bad_ioapic(unsigned long address) 3927static __init int bad_ioapic(unsigned long address)
3928{ 3928{
3929 if (nr_ioapics >= MAX_IO_APICS) { 3929 if (nr_ioapics >= MAX_IO_APICS) {
3930 printk(KERN_WARNING "WARNING: Max # of I/O APICs (%d) exceeded " 3930 pr_warn("WARNING: Max # of I/O APICs (%d) exceeded (found %d), skipping\n",
3931 "(found %d), skipping\n", MAX_IO_APICS, nr_ioapics); 3931 MAX_IO_APICS, nr_ioapics);
3932 return 1; 3932 return 1;
3933 } 3933 }
3934 if (!address) { 3934 if (!address) {
3935 printk(KERN_WARNING "WARNING: Bogus (zero) I/O APIC address" 3935 pr_warn("WARNING: Bogus (zero) I/O APIC address found in table, skipping!\n");
3936 " found in table, skipping!\n");
3937 return 1; 3936 return 1;
3938 } 3937 }
3939 return 0; 3938 return 0;
3940} 3939}
3941 3940
3941static __init int bad_ioapic_register(int idx)
3942{
3943 union IO_APIC_reg_00 reg_00;
3944 union IO_APIC_reg_01 reg_01;
3945 union IO_APIC_reg_02 reg_02;
3946
3947 reg_00.raw = io_apic_read(idx, 0);
3948 reg_01.raw = io_apic_read(idx, 1);
3949 reg_02.raw = io_apic_read(idx, 2);
3950
3951 if (reg_00.raw == -1 && reg_01.raw == -1 && reg_02.raw == -1) {
3952 pr_warn("I/O APIC 0x%x registers return all ones, skipping!\n",
3953 mpc_ioapic_addr(idx));
3954 return 1;
3955 }
3956
3957 return 0;
3958}
3959
3942void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) 3960void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
3943{ 3961{
3944 int idx = 0; 3962 int idx = 0;
@@ -3955,6 +3973,12 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
3955 ioapics[idx].mp_config.apicaddr = address; 3973 ioapics[idx].mp_config.apicaddr = address;
3956 3974
3957 set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); 3975 set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
3976
3977 if (bad_ioapic_register(idx)) {
3978 clear_fixmap(FIX_IO_APIC_BASE_0 + idx);
3979 return;
3980 }
3981
3958 ioapics[idx].mp_config.apicid = io_apic_unique_id(id); 3982 ioapics[idx].mp_config.apicid = io_apic_unique_id(id);
3959 ioapics[idx].mp_config.apicver = io_apic_get_version(idx); 3983 ioapics[idx].mp_config.apicver = io_apic_get_version(idx);
3960 3984
@@ -3975,10 +3999,10 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
3975 if (gsi_cfg->gsi_end >= gsi_top) 3999 if (gsi_cfg->gsi_end >= gsi_top)
3976 gsi_top = gsi_cfg->gsi_end + 1; 4000 gsi_top = gsi_cfg->gsi_end + 1;
3977 4001
3978 printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " 4002 pr_info("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, GSI %d-%d\n",
3979 "GSI %d-%d\n", idx, mpc_ioapic_id(idx), 4003 idx, mpc_ioapic_id(idx),
3980 mpc_ioapic_ver(idx), mpc_ioapic_addr(idx), 4004 mpc_ioapic_ver(idx), mpc_ioapic_addr(idx),
3981 gsi_cfg->gsi_base, gsi_cfg->gsi_end); 4005 gsi_cfg->gsi_base, gsi_cfg->gsi_end);
3982 4006
3983 nr_ioapics++; 4007 nr_ioapics++;
3984} 4008}