linux
Kernel panic due to double enable_IR_x2apic() call on non-SMP boards
If a single-core CPU boots an SMP kernel it will call enable_IR_x2apic() first from native_smp_prepare_cpus(), and later from APIC_init_uniprocessor(). This is not an idempotent operation and such a double call causes a kernel panic.
Bug fixed by commit 472a474c663
Type | DoubleOpOnResource |
Config | "X86 && SMP" (2nd degree) |
Fix-in | mapping |
Location | arch/x86/kernel/ |
#define NULL (void*)0 __attribute__ ((noinline)) int nondet() { return 0; } #ifdef CONFIG_SMP int smp_found_config; /* found an SMP configuration at boot time ? */ #endif void enable_IR_x2apic(void) { static char c; static char *ptr = &c; *ptr = 'a'; if (ptr) ptr = NULL; } int APIC_init_uniprocessor(void) { enable_IR_x2apic(); // (6) ERROR: enable_IR_x2apic() is not idempotent } #ifdef CONFIG_SMP int smp_sanity_check() { if (!smp_found_config) APIC_init_uniprocessor(); // (5) return 0; } void native_smp_prepare_cpus() { enable_IR_x2apic(); // (3) first call smp_sanity_check(); // (4) } #endif int main(void) { #ifdef CONFIG_SMP smp_found_config = nondet(); // (1) native_smp_prepare_cpus(); // (2) #endif return 0; }
diff --git a/simple/472a474.c b/simple/472a474.c --- a/simple/472a474.c +++ b/simple/472a474.c @@ -19,7 +19,9 @@ int APIC_init_uniprocessor(void) { +#ifndef CONFIG_SMP enable_IR_x2apic(); // (6) ERROR: enable_IR_x2apic() is not idempotent +#endif } #ifdef CONFIG_SMP
#include <stdbool.h> #include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { #ifdef CONFIG_SMP int smp_found_config; smp_found_config = false; // native_smp_prepare_cpus(); static int called = 0; called++; if (called > 1) do { fprintf(stderr, "panic!\n"); exit(1); } while(0); if (!smp_found_config) { called = 0; called++; if (called > 1) do { fprintf(stderr, "panic!\n"); exit(1); } while(0); } #endif return 0; }
. call arch/x86/kernel/smpboot.c:1071:native_smp_prepare_cpus() . 1095: enable_IR_x2apic(); . 1098: if (smp_sanity_check(max_cpus) < 0) .. call arch/x86/kernel/smpboot.c:954:smp_sanity_check() .. 997: if (!smp_found_config && !acpi_lapic) { // do not find SMP configuration, i.e. non-SMP CPU .. 1001: if (APIC_init_uniprocessor()) ... call arch/x86/kernel/apic/apic.c:1616:APIC_init_uniprocessor() ... ERROR 1643: enable_IR_x2apic();