/* * Start secondary processors in motion. */ void cpu_boot_secondary_processors() { int i, pstate; struct cpu_info *ci; sparc64_ipi_init(); for (ci = cpus; ci != NULL; ci = ci->ci_next) { if (ci->ci_cpuid == CPU_UPAID) continue; cpu_pmap_prepare(ci, false); cpu_args->cb_node = ci->ci_node; cpu_args->cb_cpuinfo = ci->ci_paddr; membar_sync(); /* Disable interrupts and start another CPU. */ pstate = getpstate(); setpstate(PSTATE_KERN); prom_startcpu(ci->ci_node, (void *)cpu_spinup_trampoline, 0); for (i = 0; i < 2000; i++) { membar_sync(); if (CPUSET_HAS(cpus_active, ci->ci_index)) break; delay(10000); } setpstate(pstate); if (!CPUSET_HAS(cpus_active, ci->ci_index)) printf("cpu%d: startup failed\n", ci->ci_cpuid); } }
/* * Internal cpu startup sequencer * The sequence is as follows: * * MASTER SLAVE * ------- ---------- * assume the kernel data is initialized * clear the proxy bit * start the slave cpu * wait for the slave cpu to set the proxy * * the slave runs slave_startup and then sets the proxy * the slave waits for the master to add slave to the ready set * * the master finishes the initialization and * adds the slave to the ready set * * the slave exits the startup thread and is running */ void start_cpu(int cpuid, void(*flag_func)(int)) { extern void cpu_startup(int); int timout; ASSERT(MUTEX_HELD(&cpu_lock)); /* * Before we begin the dance, tell DTrace that we're about to start * a CPU. */ if (dtrace_cpustart_init != NULL) (*dtrace_cpustart_init)(); /* start the slave cpu */ CPUSET_DEL(proxy_ready_set, cpuid); if (prom_test("SUNW,start-cpu-by-cpuid") == 0) { (void) prom_startcpu_bycpuid(cpuid, (caddr_t)&cpu_startup, cpuid); } else { /* "by-cpuid" interface didn't exist. Do it the old way */ pnode_t nodeid = cpunodes[cpuid].nodeid; ASSERT(nodeid != (pnode_t)0); (void) prom_startcpu(nodeid, (caddr_t)&cpu_startup, cpuid); } /* wait for the slave cpu to check in. */ for (timout = CPU_WAKEUP_GRACE_MSEC; timout; timout--) { if (CPU_IN_SET(proxy_ready_set, cpuid)) break; DELAY(1000); } if (timout == 0) { panic("cpu%d failed to start (2)", cpuid); } /* * The slave has started; we can tell DTrace that it's safe again. */ if (dtrace_cpustart_fini != NULL) (*dtrace_cpustart_fini)(); /* run the master side of stick synchronization for the slave cpu */ sticksync_master(); /* * deal with the cpu flags in a phase-specific manner * for various reasons, this needs to run after the slave * is checked in but before the slave is released. */ (*flag_func)(cpuid); /* release the slave */ CPUSET_ADD(cpu_ready_set, cpuid); }
/* * Start secondary processors in motion. */ void cpu_boot_secondary_processors(void) { int i, pstate; struct cpu_info *ci; sync_tick = 0; sparc64_ipi_init(); if (boothowto & RB_MD1) { cpus[0].ci_next = NULL; sparc_ncpus = ncpu = ncpuonline = 1; return; } for (ci = cpus; ci != NULL; ci = ci->ci_next) { if (ci->ci_cpuid == CPU_UPAID) continue; cpu_pmap_prepare(ci, false); cpu_args->cb_node = ci->ci_node; cpu_args->cb_cpuinfo = ci->ci_paddr; membar_Sync(); /* Disable interrupts and start another CPU. */ pstate = getpstate(); setpstate(PSTATE_KERN); prom_startcpu(ci->ci_node, (void *)cpu_spinup_trampoline, 0); for (i = 0; i < 2000; i++) { membar_Sync(); if (CPUSET_HAS(cpus_active, ci->ci_index)) break; delay(10000); } /* synchronize %tick ( to some degree at least ) */ delay(1000); sync_tick = 1; membar_Sync(); settick(0); if (ci->ci_system_clockrate[0] != 0) setstick(0); setpstate(pstate); if (!CPUSET_HAS(cpus_active, ci->ci_index)) printf("cpu%d: startup failed\n", ci->ci_cpuid); } }