diff options
Diffstat (limited to 'arch/i386/kernel/smpboot.c')
| -rw-r--r-- | arch/i386/kernel/smpboot.c | 68 | 
1 files changed, 52 insertions, 16 deletions
| diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 5a2bbe0c4ff..01b618e73ec 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -1078,16 +1078,6 @@ 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; @@ -1100,6 +1090,7 @@ 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; @@ -1111,27 +1102,68 @@ 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"); -		disable_smp(); +		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]);  		return;  	} +	verify_local_APIC(); +  	/*  	 * If SMP should be disabled, then really disable it!  	 */ -	if (!max_cpus || (enable_local_apic < 0)) { -		printk(KERN_INFO "SMP mode deactivated.\n"); -		disable_smp(); +	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]);  		return;  	} +	connect_bsp_APIC(); +	setup_local_APIC(); +	map_cpu_to_logical_apicid(); + +  	setup_portio_remap();  	/* @@ -1212,6 +1244,10 @@ 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  	 */ | 
