FreeBSD/sys/x86/x86/mp_x86.c
/*
 * AP CPU's call this to initialize themselves.
 */
AP CPU's call this to initialize themselves.
AP CPU ' s call this to initialize themselves .
void
init_secondary_tail(void)
{
	u_int cpuid;
	lapic_xapic_mode();
	pmap_init_pat();
	cpu_setregs();
	initializecpu();
#ifdef __amd64__
	fpuinit();
#else
	npxinit(false);
#endif
	if (cpu_ops.cpu_init)
		cpu_ops.cpu_init();
	cpuid = PCPU_GET(cpuid);
	if (PCPU_GET(apic_id) != lapic_id()) {
		printf("SMP: cpuid = %d\n", cpuid);
		printf("SMP: actual apic_id = %d\n", lapic_id());
		printf("SMP: correct apic_id = %d\n", PCPU_GET(apic_id));
		panic("cpuid mismatch! boom!!");
	}
	KASSERT(PCPU_GET(idlethread) != NULL, ("no idle thread"));
	PCPU_SET(curthread, PCPU_GET(idlethread));
	mca_init();
	mtx_lock_spin(&ap_boot_mtx);
	lapic_setup(1);
	mem_range_AP_init();
	smp_cpus++;
	CTR1(KTR_SMP, "SMP: AP CPU #%d Launched", cpuid);
	printf("SMP: AP CPU #%d Launched!\n", cpuid);
	if (cpu_info[PCPU_GET(apic_id)].cpu_hyperthread)
		CPU_SET(cpuid, &logical_cpus_mask);
	if (bootverbose)
		lapic_dump("AP");
	if (smp_cpus == mp_ncpus) {
		atomic_store_rel_int(&smp_started, 1);
	}
#ifdef __amd64__
	load_cr4(rcr4() | CR4_PGE);
	if (pmap_pcid_enabled)
		load_cr4(rcr4() | CR4_PCIDE);
	load_ds(_udatasel);
	load_es(_udatasel);
	load_fs(_ufssel);
#endif
	mtx_unlock_spin(&ap_boot_mtx);
	while (atomic_load_acq_int(&smp_started) == 0)
		ia32_pause();
#ifndef EARLY_AP_STARTUP
	cpu_initclocks_ap();
#endif
	sched_throw(NULL);
	panic("scheduler returned us to %s", __func__);
}
void init_secondary_tail ( void ) { u_int cpuid ; lapic_xapic_mode ( ) ; pmap_init_pat ( ) ; cpu_setregs ( ) ; initializecpu ( ) ; #ifdef __amd64__ fpuinit ( ) ; #else npxinit ( false ) ; #endif if ( cpu_ops . cpu_init ) cpu_ops . cpu_init ( ) ; cpuid = PCPU_GET ( cpuid ) ; if ( PCPU_GET ( apic_id ) != lapic_id ( ) ) { printf ( " \n " , cpuid ) ; printf ( " \n " , lapic_id ( ) ) ; printf ( " \n " , PCPU_GET ( apic_id ) ) ; panic ( " " ) ; } KASSERT ( PCPU_GET ( idlethread ) != NULL , ( " " ) ) ; PCPU_SET ( curthread , PCPU_GET ( idlethread ) ) ; mca_init ( ) ; mtx_lock_spin ( & ap_boot_mtx ) ; lapic_setup ( 1 ) ; mem_range_AP_init ( ) ; smp_cpus ++ ; CTR1 ( KTR_SMP , " " , cpuid ) ; printf ( " \n " , cpuid ) ; if ( cpu_info [ PCPU_GET ( apic_id ) ] . cpu_hyperthread ) CPU_SET ( cpuid , & logical_cpus_mask ) ; if ( bootverbose ) lapic_dump ( " " ) ; if ( smp_cpus == mp_ncpus ) { atomic_store_rel_int ( & smp_started , 1 ) ; } #ifdef __amd64__ load_cr4 ( rcr4 ( ) | CR4_PGE ) ; if ( pmap_pcid_enabled ) load_cr4 ( rcr4 ( ) | CR4_PCIDE ) ; load_ds ( _udatasel ) ; load_es ( _udatasel ) ; load_fs ( _ufssel ) ; #endif mtx_unlock_spin ( & ap_boot_mtx ) ; while ( atomic_load_acq_int ( & smp_started ) == 0 ) ia32_pause ( ) ; #ifndef EARLY_AP_STARTUP cpu_initclocks_ap ( ) ; #endif sched_throw ( NULL ) ; panic ( " " , __func__ ) ; }
AP CPU's call this to initialize themselves.
AP CPU ' s call this to initialize themselves .
/*
	 * On real hardware, switch to x2apic mode if possible.  Do it
	 * after aps_ready was signalled, to avoid manipulating the
	 * mode while BSP might still want to send some IPI to us
	 * (second startup IPI is ignored on modern hardware etc).
	 */ /* Initialize the PAT MSR. */ /* set up CPU registers and state */ /* set up SSE/NX */ /* set up FPU state on the AP */ /* A quick check from sanity claus */ /* Initialize curthread. */ /* Init local apic for irq's */ /* Set memory range attributes for this CPU to match the BSP */ /* Determine if we are a logical CPU. */ /* enable IPI's, tlb shootdown, freezes etc */ /*
	 * Enable global pages TLB extension
	 * This also implicitly flushes the TLB 
	 */ /* Wait until all the AP's are up. */ /* Start per-CPU event timers. */ /* NOTREACHED */