diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2005-10-30 14:59:41 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-30 17:37:13 -0800 |
commit | f2b36db692b7ff6972320ad9839ae656a3b0ee3e (patch) | |
tree | 110387d2557a156d6b9453ea0c45d392b47796c2 /arch/i386/kernel/smpboot.c | |
parent | 29b70081f7cb094513d5189e82d3478b50777a28 (diff) | |
download | lwn-f2b36db692b7ff6972320ad9839ae656a3b0ee3e.tar.gz lwn-f2b36db692b7ff6972320ad9839ae656a3b0ee3e.zip |
[PATCH] i386: move apic init in init_IRQs
All kinds of ugliness exists because we don't initialize
the apics during init_IRQs.
- We calibrate jiffies in non apic mode even when we are using apics.
- We have to have special code to initialize the apics when non-smp.
- The legacy i8259 must exist and be setup correctly, even
when we won't use it past initialization.
- The kexec on panic code must restore the state of the io_apics.
- init/main.c needs a special case for !smp smp_init on x86
In addition to pure code movement I needed a couple
of non-obvious changes:
- Move setup_boot_APIC_clock into APIC_late_time_init for
simplicity.
- Use cpu_khz to generate a better approximation of loops_per_jiffies
so I can verify the timer interrupt is working.
- Call setup_apic_nmi_watchdog again after cpu_khz is initialized on
the boot cpu.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386/kernel/smpboot.c')
-rw-r--r-- | arch/i386/kernel/smpboot.c | 68 |
1 files changed, 16 insertions, 52 deletions
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 01b618e73ecd..5a2bbe0c4fff 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -1078,6 +1078,16 @@ void *xquad_portio; EXPORT_SYMBOL(xquad_portio); #endif +/* + * Fall back to non SMP mode after errors. + * + */ +static __init void disable_smp(void) +{ + cpu_set(0, cpu_sibling_map[0]); + cpu_set(0, cpu_core_map[0]); +} + static void __init smp_boot_cpus(unsigned int max_cpus) { int apicid, cpu, bit, kicked; @@ -1090,7 +1100,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus) printk("CPU%d: ", 0); print_cpu_info(&cpu_data[0]); - boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); boot_cpu_logical_apicid = logical_smp_processor_id(); x86_cpu_to_apicid[0] = boot_cpu_physical_apicid; @@ -1102,68 +1111,27 @@ static void __init smp_boot_cpus(unsigned int max_cpus) cpus_clear(cpu_core_map[0]); cpu_set(0, cpu_core_map[0]); + map_cpu_to_logical_apicid(); + /* * If we couldn't find an SMP configuration at boot time, * get out of here now! */ if (!smp_found_config && !acpi_lapic) { printk(KERN_NOTICE "SMP motherboard not detected.\n"); - smpboot_clear_io_apic_irqs(); - phys_cpu_present_map = physid_mask_of_physid(0); - if (APIC_init_uniprocessor()) - printk(KERN_NOTICE "Local APIC not detected." - " Using dummy APIC emulation.\n"); - map_cpu_to_logical_apicid(); - cpu_set(0, cpu_sibling_map[0]); - cpu_set(0, cpu_core_map[0]); - return; - } - - /* - * Should not be necessary because the MP table should list the boot - * CPU too, but we do it for the sake of robustness anyway. - * Makes no sense to do this check in clustered apic mode, so skip it - */ - if (!check_phys_apicid_present(boot_cpu_physical_apicid)) { - printk("weird, boot CPU (#%d) not listed by the BIOS.\n", - boot_cpu_physical_apicid); - physid_set(hard_smp_processor_id(), phys_cpu_present_map); - } - - /* - * If we couldn't find a local APIC, then get out of here now! - */ - if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) && !cpu_has_apic) { - printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n", - boot_cpu_physical_apicid); - printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n"); - smpboot_clear_io_apic_irqs(); - phys_cpu_present_map = physid_mask_of_physid(0); - cpu_set(0, cpu_sibling_map[0]); - cpu_set(0, cpu_core_map[0]); + disable_smp(); return; } - verify_local_APIC(); - /* * If SMP should be disabled, then really disable it! */ - if (!max_cpus) { - smp_found_config = 0; - printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n"); - smpboot_clear_io_apic_irqs(); - phys_cpu_present_map = physid_mask_of_physid(0); - cpu_set(0, cpu_sibling_map[0]); - cpu_set(0, cpu_core_map[0]); + if (!max_cpus || (enable_local_apic < 0)) { + printk(KERN_INFO "SMP mode deactivated.\n"); + disable_smp(); return; } - connect_bsp_APIC(); - setup_local_APIC(); - map_cpu_to_logical_apicid(); - - setup_portio_remap(); /* @@ -1244,10 +1212,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus) cpu_set(0, cpu_sibling_map[0]); cpu_set(0, cpu_core_map[0]); - smpboot_setup_io_apic(); - - setup_boot_APIC_clock(); - /* * Synchronize the TSC with the AP */ |