diff options
author | Andi Kleen <ak@suse.de> | 2008-01-30 13:33:17 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 13:33:17 +0100 |
commit | d3432896dae72ee97deb850ad7bbc30329d32c0d (patch) | |
tree | 73cc99efc6ca0ef5f8caabd6eed1e2a50196ca5e | |
parent | ca74a6f84e68b44867022f4a4f3ec17c087c864e (diff) | |
download | kernel_samsung_smdk4412-d3432896dae72ee97deb850ad7bbc30329d32c0d.zip kernel_samsung_smdk4412-d3432896dae72ee97deb850ad7bbc30329d32c0d.tar.gz kernel_samsung_smdk4412-d3432896dae72ee97deb850ad7bbc30329d32c0d.tar.bz2 |
x86: don't disable the APIC if it hasn't been mapped yet
When the kernel panics early for some unrelated reason
there would be eventually an early exception inside panic because
clear_local_APIC tried to disable the not yet mapped APIC.
Check for that explicitely.
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | arch/x86/kernel/apic_32.c | 11 | ||||
-rw-r--r-- | arch/x86/kernel/apic_64.c | 9 |
2 files changed, 15 insertions, 5 deletions
diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index d07a603..35a568e 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c @@ -99,6 +99,8 @@ static DEFINE_PER_CPU(struct clock_event_device, lapic_events); /* Local APIC was disabled by the BIOS and enabled by the kernel */ static int enabled_via_apicbase; +static unsigned long apic_phys; + /* * Get the LAPIC version */ @@ -631,9 +633,14 @@ int setup_profiling_timer(unsigned int multiplier) */ void clear_local_APIC(void) { - int maxlvt = lapic_get_maxlvt(); + int maxlvt; u32 v; + /* APIC hasn't been mapped yet */ + if (!apic_phys) + return; + + maxlvt = lapic_get_maxlvt(); /* * Masking an LVT entry can trigger a local APIC error * if the vector is zero. Mask LVTERR first to prevent this. @@ -1120,8 +1127,6 @@ no_apic: */ void __init init_apic_mappings(void) { - unsigned long apic_phys; - /* * If no local APIC can be found then set up a fake all * zeroes page to simulate the local APIC and another diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 85bd3d4..a7a38c9 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -81,6 +81,8 @@ static struct clock_event_device lapic_clockevent = { }; static DEFINE_PER_CPU(struct clock_event_device, lapic_events); +static unsigned long apic_phys; + /* * Get the LAPIC version */ @@ -525,6 +527,11 @@ void clear_local_APIC(void) int maxlvt = lapic_get_maxlvt(); u32 v; + /* APIC hasn't been mapped yet */ + if (!apic_phys) + return; + + maxlvt = lapic_get_maxlvt(); /* * Masking an LVT entry can trigger a local APIC error * if the vector is zero. Mask LVTERR first to prevent this. @@ -859,8 +866,6 @@ static int __init detect_init_APIC(void) */ void __init init_apic_mappings(void) { - unsigned long apic_phys; - /* * If no local APIC can be found then set up a fake all * zeroes page to simulate the local APIC and another |