Exemple #1
0
static void __cpuinit MP_processor_info(struct mpc_config_processor *m)
{
	int cpu;
	cpumask_t tmp_map;
	char *bootup_cpu = "";

	if (!(m->mpc_cpuflag & CPU_ENABLED)) {
		disabled_cpus++;
		return;
	}
	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
		bootup_cpu = " (Bootup-CPU)";
		boot_cpu_id = m->mpc_apicid;
	}

	printk(KERN_INFO "Processor #%d%s\n", m->mpc_apicid, bootup_cpu);

	if (num_processors >= NR_CPUS) {
		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
			" Processor ignored.\n", NR_CPUS);
		return;
	}

	num_processors++;
	cpus_complement(tmp_map, cpu_present_map);
	cpu = first_cpu(tmp_map);

	physid_set(m->mpc_apicid, phys_cpu_present_map);
 	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
 		/*
		 * x86_bios_cpu_apicid is required to have processors listed
 		 * in same order as logical cpu numbers. Hence the first
 		 * entry is BSP, and so on.
 		 */
		cpu = 0;
 	}
	/* are we being called early in kernel startup? */
	if (x86_cpu_to_apicid_early_ptr) {
		u16 *cpu_to_apicid = x86_cpu_to_apicid_early_ptr;
		u16 *bios_cpu_apicid = x86_bios_cpu_apicid_early_ptr;

		cpu_to_apicid[cpu] = m->mpc_apicid;
		bios_cpu_apicid[cpu] = m->mpc_apicid;
	} else {
		per_cpu(x86_cpu_to_apicid, cpu) = m->mpc_apicid;
		per_cpu(x86_bios_cpu_apicid, cpu) = m->mpc_apicid;
	}

	cpu_set(cpu, cpu_possible_map);
	cpu_set(cpu, cpu_present_map);
}
Exemple #2
0
/*
 * This initializes the IO-APIC and APIC hardware if this is
 * a UP kernel.
 */
int __init APIC_init_uniprocessor (void)
{
    if (enable_local_apic < 0)
        clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);

    if (!smp_found_config && !cpu_has_apic) {
        skip_ioapic_setup = 1;
        return -1;
    }

    /*
     * Complain if the BIOS pretends there is one.
     */
    if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
        printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
               boot_cpu_physical_apicid);
        clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
        skip_ioapic_setup = 1;
        return -1;
    }

    verify_local_APIC();

    connect_bsp_APIC();

    /*
     * Hack: In case of kdump, after a crash, kernel might be booting
     * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid
     * might be zero if read from MP tables. Get it from LAPIC.
     */
#ifdef CONFIG_CRASH_DUMP
    boot_cpu_physical_apicid = get_apic_id();
#endif
    physids_clear(phys_cpu_present_map);
    physid_set(boot_cpu_physical_apicid, phys_cpu_present_map);

    setup_local_APIC();

    if (nmi_watchdog == NMI_LOCAL_APIC)
        check_nmi_watchdog();
#ifdef CONFIG_X86_IO_APIC
    if (smp_found_config)
        if (!skip_ioapic_setup && nr_ioapics)
            setup_IO_APIC();
#endif
    setup_boot_APIC_clock();

    return 0;
}
Exemple #3
0
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
void __devinit smp_prepare_boot_cpu(void)
{
	bsp_phys_id = hard_smp_processor_id();
	physid_set(bsp_phys_id, phys_cpu_present_map);
	cpu_set(0, cpu_online_map);	/* BSP's cpu_id == 0 */
	cpu_set(0, cpu_callout_map);
	cpu_set(0, cpu_callin_map);

	/*
	 * Initialize the logical to physical CPU number mapping
	 */
	init_cpu_to_physid();
	map_cpu_to_physid(0, bsp_phys_id);
	current_thread_info()->cpu = 0;
}
Exemple #4
0
static void __init MP_processor_info (struct mpc_config_processor *m)
{
	int ver;

	if (!(m->mpc_cpuflag & CPU_ENABLED))
		return;

	printk(KERN_INFO "Processor #%d %d:%d APIC version %d\n",
		m->mpc_apicid,
	       (m->mpc_cpufeature & CPU_FAMILY_MASK)>>8,
	       (m->mpc_cpufeature & CPU_MODEL_MASK)>>4,
		m->mpc_apicver);

	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
		Dprintk("    Bootup CPU\n");
		boot_cpu_id = m->mpc_apicid;
	}
	if (num_processors >= NR_CPUS) {
		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
			" Processor ignored.\n", NR_CPUS);
		return;
	}
	if (num_processors >= maxcpus) {
		printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
			" Processor ignored.\n", maxcpus);
		return;
	}

	num_processors++;

	if (m->mpc_apicid > MAX_APICS) {
		printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n",
			m->mpc_apicid, MAX_APICS);
		return;
	}
	ver = m->mpc_apicver;

	physid_set(m->mpc_apicid, phys_cpu_present_map);
	/*
	 * Validate version
	 */
	if (ver == 0x0) {
		printk(KERN_ERR "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
		ver = 0x10;
	}
	apic_version[m->mpc_apicid] = ver;
	bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
}
Exemple #5
0
void __cpuinit generic_processor_info(int apicid, int version)
{
    int cpu;
    cpumask_t tmp_map;

    if (num_processors >= NR_CPUS) {
        printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
               " Processor ignored.\n", NR_CPUS);
        return;
    }

    num_processors++;
    cpus_complement(tmp_map, cpu_present_map);
    cpu = first_cpu(tmp_map);

    physid_set(apicid, phys_cpu_present_map);
    if (apicid == boot_cpu_physical_apicid) {
        /*
         * x86_bios_cpu_apicid is required to have processors listed
         * in same order as logical cpu numbers. Hence the first
         * entry is BSP, and so on.
         */
        cpu = 0;
    }
    if (apicid > max_physical_apicid)
        max_physical_apicid = apicid;

    /* are we being called early in kernel startup? */
    if (early_per_cpu_ptr(x86_cpu_to_apicid)) {
        u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid);
        u16 *bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);

        cpu_to_apicid[cpu] = apicid;
        bios_cpu_apicid[cpu] = apicid;
    } else {
        per_cpu(x86_cpu_to_apicid, cpu) = apicid;
        per_cpu(x86_bios_cpu_apicid, cpu) = apicid;
    }

    cpu_set(cpu, cpu_possible_map);
    cpu_set(cpu, cpu_present_map);
}
Exemple #6
0
/*==========================================================================*
 * Name:         smp_prepare_cpus (old smp_boot_cpus)
 *
 * Description:  This routine boot up APs.
 *
 * Born on Date: 2002.02.05
 *
 * Arguments:    NONE
 *
 * Returns:      void (cannot fail)
 *
 * Modification log:
 * Date       Who Description
 * ---------- --- --------------------------------------------------------
 * 2003-06-24 hy  modify for linux-2.5.69
 *
 *==========================================================================*/
void __init smp_prepare_cpus(unsigned int max_cpus)
{
	int phys_id;
	unsigned long nr_cpu;

	nr_cpu = inl(M32R_FPGA_NUM_OF_CPUS_PORTL);
	if (nr_cpu > NR_CPUS) {
		printk(KERN_INFO "NUM_OF_CPUS reg. value [%ld] > NR_CPU [%d]",
			nr_cpu, NR_CPUS);
		goto smp_done;
	}
	for (phys_id = 0 ; phys_id < nr_cpu ; phys_id++)
		physid_set(phys_id, phys_cpu_present_map);
#ifndef CONFIG_HOTPLUG_CPU
	cpu_present_map = cpu_possible_map;
#endif

	show_mp_info(nr_cpu);

	init_ipi_lock();

	/*
	 * Setup boot CPU information
	 */
	smp_store_cpu_info(0); /* Final full version of the data */

	/*
	 * If SMP should be disabled, then really disable it!
	 */
	if (!max_cpus) {
		printk(KERN_INFO "SMP mode deactivated by commandline.\n");
		goto smp_done;
	}

	/*
	 * Now scan the CPU present map and fire up the other CPUs.
	 */
	Dprintk("CPU present map : %lx\n", physids_coerce(phys_cpu_present_map));

	for (phys_id = 0 ; phys_id < NR_CPUS ; phys_id++) {
		/*
		 * Don't even attempt to start the boot CPU!
		 */
		if (phys_id == bsp_phys_id)
			continue;

		if (!physid_isset(phys_id, phys_cpu_present_map))
			continue;

		if ((max_cpus >= 0) && (max_cpus <= cpucount + 1))
			continue;

		do_boot_cpu(phys_id);

		/*
		 * Make sure we unmap all failed CPUs
		 */
		if (physid_to_cpu(phys_id) == -1) {
			physid_clear(phys_id, phys_cpu_present_map);
			printk("phys CPU#%d not responding - " \
				"cannot use it.\n", phys_id);
		}
	}

smp_done:
	Dprintk("Boot done.\n");
}
static void __init MP_processor_info (struct mpc_config_processor *m)
{
	int cpu;
	unsigned char ver;
	static int found_bsp=0;

	if (!(m->mpc_cpuflag & CPU_ENABLED)) {
		disabled_cpus++;
		return;
	}

	printk(KERN_INFO "Processor #%d %d:%d APIC version %d\n",
		m->mpc_apicid,
	       (m->mpc_cpufeature & CPU_FAMILY_MASK)>>8,
	       (m->mpc_cpufeature & CPU_MODEL_MASK)>>4,
		m->mpc_apicver);

	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
		Dprintk("    Bootup CPU\n");
		boot_cpu_id = m->mpc_apicid;
	}
	if (num_processors >= NR_CPUS) {
		printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
			" Processor ignored.\n", NR_CPUS);
		return;
	}

	cpu = num_processors++;
	
#if MAX_APICS < 255	
	if ((int)m->mpc_apicid > MAX_APICS) {
		printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n",
			m->mpc_apicid, MAX_APICS);
		return;
	}
#endif
	ver = m->mpc_apicver;

	physid_set(m->mpc_apicid, phys_cpu_present_map);
	/*
	 * Validate version
	 */
	if (ver == 0x0) {
		printk(KERN_ERR "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
		ver = 0x10;
	}
	apic_version[m->mpc_apicid] = ver;
 	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
 		/*
 		 * bios_cpu_apicid is required to have processors listed
 		 * in same order as logical cpu numbers. Hence the first
 		 * entry is BSP, and so on.
 		 */
		cpu = 0;

 		bios_cpu_apicid[0] = m->mpc_apicid;
 		x86_cpu_to_apicid[0] = m->mpc_apicid;
 		found_bsp = 1;
 	} else
		cpu = num_processors - found_bsp;
	bios_cpu_apicid[cpu] = m->mpc_apicid;
	x86_cpu_to_apicid[cpu] = m->mpc_apicid;

	cpu_set(cpu, cpu_possible_map);
	cpu_set(cpu, cpu_present_map);
}
Exemple #8
0
static void __init smp_boot_cpus(unsigned int max_cpus)
{
	int apicid, cpu, bit, kicked;
	unsigned long bogosum = 0;

	/*
	 * Setup boot CPU information
	 */
	smp_store_cpu_info(0); /* Final full version of the data */
	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;

	current_thread_info()->cpu = 0;
	smp_tune_scheduling();
	cpus_clear(cpu_sibling_map[0]);
	cpu_set(0, cpu_sibling_map[0]);

	/*
	 * 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();
		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);
		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);
		return;
	}

	connect_bsp_APIC();
	setup_local_APIC();
	map_cpu_to_logical_apicid();


	setup_portio_remap();

	/*
	 * Scan the CPU present map and fire up the other CPUs via do_boot_cpu
	 *
	 * In clustered apic mode, phys_cpu_present_map is a constructed thus:
	 * bits 0-3 are quad0, 4-7 are quad1, etc. A perverse twist on the 
	 * clustered apic ID.
	 */
	Dprintk("CPU present map: %lx\n", physids_coerce(phys_cpu_present_map));

	kicked = 1;
	for (bit = 0; kicked < NR_CPUS && bit < MAX_APICS; bit++) {
		apicid = cpu_present_to_apicid(bit);
		/*
		 * Don't even attempt to start the boot CPU!
		 */
		if ((apicid == boot_cpu_apicid) || (apicid == BAD_APICID))
			continue;

		if (!check_apicid_present(bit))
			continue;
		if (max_cpus <= cpucount+1)
			continue;

		if (do_boot_cpu(apicid))
			printk("CPU #%d not responding - cannot use it.\n",
								apicid);
		else
			++kicked;
	}

	/*
	 * Cleanup possible dangling ends...
	 */
	smpboot_restore_warm_reset_vector();

	/*
	 * Allow the user to impress friends.
	 */
	Dprintk("Before bogomips.\n");
	for (cpu = 0; cpu < NR_CPUS; cpu++)
		if (cpu_isset(cpu, cpu_callout_map))
			bogosum += cpu_data[cpu].loops_per_jiffy;
	printk(KERN_INFO
		"Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
		cpucount+1,
		bogosum/(500000/HZ),
		(bogosum/(5000/HZ))%100);
	
	Dprintk("Before bogocount - setting activated=1.\n");

	if (smp_b_stepping)
		printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n");

	/*
	 * Don't taint if we are running SMP kernel on a single non-MP
	 * approved Athlon
	 */
	if (tainted & TAINT_UNSAFE_SMP) {
		if (cpucount)
			printk (KERN_INFO "WARNING: This combination of AMD processors is not suitable for SMP.\n");
		else
			tainted &= ~TAINT_UNSAFE_SMP;
	}

	Dprintk("Boot done.\n");

	/*
	 * construct cpu_sibling_map[], so that we can tell sibling CPUs
	 * efficiently.
	 */
	for (cpu = 0; cpu < NR_CPUS; cpu++)
		cpus_clear(cpu_sibling_map[cpu]);

	for (cpu = 0; cpu < NR_CPUS; cpu++) {
		int siblings = 0;
		int i;
		if (!cpu_isset(cpu, cpu_callout_map))
			continue;

		if (smp_num_siblings > 1) {
			for (i = 0; i < NR_CPUS; i++) {
				if (!cpu_isset(i, cpu_callout_map))
					continue;
				if (phys_proc_id[cpu] == phys_proc_id[i]) {
					siblings++;
					cpu_set(i, cpu_sibling_map[cpu]);
				}
			}
		} else {
			siblings++;
			cpu_set(cpu, cpu_sibling_map[cpu]);
		}

		if (siblings != smp_num_siblings)
			printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings);
	}

	if (nmi_watchdog == NMI_LOCAL_APIC)
		check_nmi_watchdog();

	smpboot_setup_io_apic();

	setup_boot_APIC_clock();

	/*
	 * Synchronize the TSC with the AP
	 */
	if (cpu_has_tsc && cpucount && cpu_khz)
		synchronize_tsc_bp();
}
Exemple #9
0
void __cpuinit generic_processor_info(int apicid, int version)
{
    int cpu;


    if (version == 0x0) {
        pr_warning("BIOS bug, APIC version is 0 for CPU#%d! "
                   "fixing up to 0x10. (tell your hw vendor)\n",
                   version);
        version = 0x10;
    }
    apic_version[apicid] = version;

    if (num_processors >= nr_cpu_ids) {
        int max = nr_cpu_ids;
        int thiscpu = max + disabled_cpus;

        pr_warning(
            "ACPI: NR_CPUS/possible_cpus limit of %i reached."
            "  Processor %d/0x%x ignored.\n", max, thiscpu, apicid);

        disabled_cpus++;
        return;
    }

    num_processors++;
    cpu = cpumask_next_zero(-1, cpu_present_mask);

    if (version != apic_version[boot_cpu_physical_apicid])
        WARN_ONCE(1,
                  "ACPI: apic version mismatch, bootcpu: %x cpu %d: %x\n",
                  apic_version[boot_cpu_physical_apicid], cpu, version);

    physid_set(apicid, phys_cpu_present_map);
    if (apicid == boot_cpu_physical_apicid) {

        cpu = 0;
    }
    if (apicid > max_physical_apicid)
        max_physical_apicid = apicid;

#ifdef CONFIG_X86_32
    switch (boot_cpu_data.x86_vendor) {
    case X86_VENDOR_INTEL:
        if (num_processors > 8)
            def_to_bigsmp = 1;
        break;
    case X86_VENDOR_AMD:
        if (max_physical_apicid >= 8)
            def_to_bigsmp = 1;
    }
#endif

#if defined(CONFIG_SMP) || defined(CONFIG_X86_64)
    early_per_cpu(x86_cpu_to_apicid, cpu) = apicid;
    early_per_cpu(x86_bios_cpu_apicid, cpu) = apicid;
#endif

    set_cpu_possible(cpu, true);
    set_cpu_present(cpu, true);
}
Exemple #10
0
/**
 * Parses an MP table CPU entry.
 */
static void __init
MP_processor_info(struct mpc_config_processor *m)
{
    int cpu;
    int is_bp;
    unsigned char ver;
    cpumask_t tmp_map;

    if (!(m->mpc_cpuflag & CPU_ENABLED)) {
        printk(KERN_WARNING "A disabled CPU was encountered\n");
        return;
    }

    /* Count the new CPU */
    if (++num_cpus > NR_CPUS)
        panic("NR_CPUS limit of %i reached.\n", NR_CPUS);

    /*
     * Determine if this is the bootstrap processor...
     * the one responsible for booting the other CPUs.
     */
    is_bp = (m->mpc_cpuflag & CPU_BOOTPROCESSOR);

    /*
     * Assign a logical CPU ID.
     * The bootstrap CPU is always assigned logical ID 0.
     * All other CPUs are assigned the lowest ID available.
     */
    if (is_bp) {
        cpu = 0;
    } else {
        cpus_complement(tmp_map, cpu_present_map);
        cpu = first_cpu(tmp_map);
    }

    /* Validate APIC version, fixing up if necessary. */
    ver = m->mpc_apicver;
    if (ver == 0x0) {
        printk(KERN_ERR "BIOS bug, APIC version is 0 for PhysCPU#%d! "
               "fixing up to 0x10. (tell your hw vendor)\n",
               m->mpc_apicid);
        ver = 0x10;
    }

    /* Remember the APIC's version */
    apic_version[m->mpc_apicid] = ver;

    /* Add the CPU to the map of physical CPU IDs present. */
    physid_set(m->mpc_apicid, phys_cpu_present_map);

    /* Remember the physical CPU ID of the bootstrap CPU. */
    if (is_bp)
        boot_phys_cpu_id = m->mpc_apicid;

    /* Add the CPU to the map of logical CPU IDs present. */
    cpu_set(cpu, cpu_present_map);

    /* Store ID information. */
    cpu_info[cpu].logical_id   = cpu;
    cpu_info[cpu].physical_id  = m->mpc_apicid;
    cpu_info[cpu].arch.apic_id = m->mpc_apicid;

    printk(KERN_DEBUG
           "Physical CPU #%d -> Logical CPU #%d, %d:%d APIC version %d%s\n",
           m->mpc_apicid,
           cpu,
           (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
           (m->mpc_cpufeature & CPU_MODEL_MASK)  >> 4,
           ver,
           is_bp ? " (Bootstrap CPU)" : "");
}
Exemple #11
0
static void __init smp_boot_cpus(unsigned int max_cpus)
{
	unsigned apicid, cpu, bit, kicked;

	nmi_watchdog_default();

	/*
	 * Setup boot CPU information
	 */
	smp_store_cpu_info(0); /* Final full version of the data */
	printk(KERN_INFO "CPU%d: ", 0);
	print_cpu_info(&cpu_data[0]);

	current_thread_info()->cpu = 0;
	smp_tune_scheduling();

	if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) {
		printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
		       hard_smp_processor_id());
		physid_set(hard_smp_processor_id(), phys_cpu_present_map);
	}

	/*
	 * If we couldn't find an SMP configuration at boot time,
	 * get out of here now!
	 */
	if (!smp_found_config) {
		printk(KERN_NOTICE "SMP motherboard not detected.\n");
		io_apic_irqs = 0;
		cpu_online_map = cpumask_of_cpu(0);
		cpu_set(0, cpu_sibling_map[0]);
		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");
		goto smp_done;
	}

	/*
	 * Should not be necessary because the MP table should list the boot
	 * CPU too, but we do it for the sake of robustness anyway.
	 */
	if (!physid_isset(boot_cpu_id, phys_cpu_present_map)) {
		printk(KERN_NOTICE "weird, boot CPU (#%d) not listed by the BIOS.\n",
								 boot_cpu_id);
		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_id]) && !cpu_has_apic) {
		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
			boot_cpu_id);
		printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
		io_apic_irqs = 0;
		cpu_online_map = cpumask_of_cpu(0);
		cpu_set(0, cpu_sibling_map[0]);
		phys_cpu_present_map = physid_mask_of_physid(0);
		disable_apic = 1;
		goto smp_done;
	}

	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");
		io_apic_irqs = 0;
		cpu_online_map = cpumask_of_cpu(0);
		cpu_set(0, cpu_sibling_map[0]);
		phys_cpu_present_map = physid_mask_of_physid(0);
		disable_apic = 1;
		goto smp_done;
	}

	connect_bsp_APIC();
	setup_local_APIC();

	if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_id)
		BUG();

	x86_cpu_to_apicid[0] = boot_cpu_id;

	/*
	 * Now scan the CPU present map and fire up the other CPUs.
	 */
	Dprintk("CPU present map: %lx\n", physids_coerce(phys_cpu_present_map));

	kicked = 1;
	for (bit = 0; kicked < NR_CPUS && bit < MAX_APICS; bit++) {
		apicid = cpu_present_to_apicid(bit);
		/*
		 * Don't even attempt to start the boot CPU!
		 */
		if (apicid == boot_cpu_id || (apicid == BAD_APICID))
			continue;

		if (!physid_isset(apicid, phys_cpu_present_map))
			continue;
		if ((max_cpus >= 0) && (max_cpus <= cpucount+1))
			continue;

		do_boot_cpu(apicid);
		++kicked;
	}

	/*
	 * Cleanup possible dangling ends...
	 */
	{
		/*
		 * Install writable page 0 entry to set BIOS data area.
		 */
		local_flush_tlb();

		/*
		 * Paranoid:  Set warm reset code and vector here back
		 * to default values.
		 */
		CMOS_WRITE(0, 0xf);

		*((volatile int *) phys_to_virt(0x467)) = 0;
	}

	/*
	 * Allow the user to impress friends.
	 */

	Dprintk("Before bogomips.\n");
	if (!cpucount) {
		printk(KERN_INFO "Only one processor found.\n");
	} else {
		unsigned long bogosum = 0;
		for (cpu = 0; cpu < NR_CPUS; cpu++)
			if (cpu_isset(cpu, cpu_callout_map))
				bogosum += cpu_data[cpu].loops_per_jiffy;
		printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
			cpucount+1,
			bogosum/(500000/HZ),
			(bogosum/(5000/HZ))%100);
		Dprintk("Before bogocount - setting activated=1.\n");
	}

	/*
	 * Construct cpu_sibling_map[], so that we can tell the
	 * sibling CPU efficiently.
	 */
	for (cpu = 0; cpu < NR_CPUS; cpu++)
		cpus_clear(cpu_sibling_map[cpu]);

	for (cpu = 0; cpu < NR_CPUS; cpu++) {
		int siblings = 0;
		int i;
		if (!cpu_isset(cpu, cpu_callout_map))
			continue;

		if (smp_num_siblings > 1) {
			for (i = 0; i < NR_CPUS; i++) {
				if (!cpu_isset(i, cpu_callout_map))
					continue;
				if (phys_proc_id[cpu] == phys_proc_id[i]) {
					siblings++;
					cpu_set(i, cpu_sibling_map[cpu]);
				}
			}
		} else { 
			siblings++;
			cpu_set(cpu, cpu_sibling_map[cpu]);
		}

		if (siblings != smp_num_siblings) {
			printk(KERN_WARNING 
	       "WARNING: %d siblings found for CPU%d, should be %d\n", 
			       siblings, cpu, smp_num_siblings);
			smp_num_siblings = siblings;
		}       
	}

	Dprintk("Boot done.\n");

	/*
	 * Here we can be sure that there is an IO-APIC in the system. Let's
	 * go and set it up:
	 */
	if (!skip_ioapic_setup && nr_ioapics)
		setup_IO_APIC();
	else
		nr_ioapics = 0;

	setup_boot_APIC_clock();

	/*
	 * Synchronize the TSC with the AP
	 */
	if (cpu_has_tsc && cpucount)
		synchronize_tsc_bp();

 smp_done:
	time_init_smp();
}