/* * Determine mass storage and memory configuration for a machine. * We get the PROM's root device and make sure we understand it, then * attach it as `mainbus0'. We also set up to handle the PROM `sync' * command. */ void cpu_configure(void) { if (CPU_ISSUN4V) mdesc_init(); bool userconf = (boothowto & RB_USERCONF) != 0; /* fetch boot device settings */ get_bootpath_from_prom(); if (((boothowto & RB_USERCONF) != 0) && !userconf) /* * Old bootloaders do not pass boothowto, and MI code * has already handled userconfig before we get here * and finally fetch the right options. So if we missed * it, just do it here. */ userconf_prompt(); /* block clock interrupts and anything below */ splclock(); /* Enable device interrupts */ setpstate(getpstate()|PSTATE_IE); if (config_rootfound("mainbus", NULL) == NULL) panic("mainbus not configured"); /* Enable device interrupts */ setpstate(getpstate()|PSTATE_IE); (void)spl0(); }
/* * 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); } }
/* * Determine mass storage and memory configuration for a machine. * We get the PROM's root device and make sure we understand it, then * attach it as `mainbus0'. We also set up to handle the PROM `sync' * command. */ void cpu_configure(void) { /* fetch boot device settings */ get_bootpath_from_prom(); /* block clock interrupts and anything below */ splclock(); /* Enable device interrupts */ setpstate(getpstate()|PSTATE_IE); if (config_rootfound("mainbus", NULL) == NULL) panic("mainbus not configured"); /* Enable device interrupts */ setpstate(getpstate()|PSTATE_IE); (void)spl0(); }
/* * 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); } }
/* * Write necessary machine dependent information to cpr state file, * eg. sun4u mmu ctx secondary for the current running process (cpr) ... */ int i_cpr_write_machdep(vnode_t *vp) { extern uint_t getpstate(), getwstate(); extern uint_t i_cpr_tstack_size; const char ustr[] = ": unix-tte 2drop false ;"; uintptr_t tinfo; label_t *ltp; cmd_t cmach; char *fmt; int rc; /* * ustr[] is used as temporary forth words during * slave startup sequence, see sfmmu_mp_startup() */ cmach.md_magic = (uint_t)CPR_MACHDEP_MAGIC; cmach.md_size = sizeof (m_info) + sizeof (ustr); if (rc = cpr_write(vp, (caddr_t)&cmach, sizeof (cmach))) { cpr_err(CE_WARN, "Failed to write descriptor."); return (rc); } /* * m_info is now cleared in i_cpr_dump_setup() */ m_info.ksb = (uint32_t)STACK_BIAS; m_info.kpstate = (uint16_t)getpstate(); m_info.kwstate = (uint16_t)getwstate(); CPR_DEBUG(CPR_DEBUG1, "stack bias 0x%x, pstate 0x%x, wstate 0x%x\n", m_info.ksb, m_info.kpstate, m_info.kwstate); ltp = &ttolwp(curthread)->lwp_qsav; m_info.qsav_pc = (cpr_ext)ltp->val[0]; m_info.qsav_sp = (cpr_ext)ltp->val[1]; /* * Set secondary context to INVALID_CONTEXT to force the HAT * to re-setup the MMU registers and locked TTEs it needs for * TLB miss handling. */ m_info.mmu_ctx_sec = INVALID_CONTEXT; m_info.mmu_ctx_pri = KCONTEXT; tinfo = (uintptr_t)curthread; m_info.thrp = (cpr_ptr)tinfo; tinfo = (uintptr_t)i_cpr_resume_setup; m_info.func = (cpr_ptr)tinfo; /* * i_cpr_data_page is comprised of a 4K stack area and a few * trailing data symbols; the page is shared by the prom and * kernel during resume. the stack size is recorded here * and used by cprboot to set %sp */ tinfo = (uintptr_t)&i_cpr_data_page; m_info.tmp_stack = (cpr_ptr)tinfo; m_info.tmp_stacksize = i_cpr_tstack_size; m_info.test_mode = cpr_test_mode; i_cpr_save_cpu_info(); if (rc = cpr_write(vp, (caddr_t)&m_info, sizeof (m_info))) { cpr_err(CE_WARN, "Failed to write machdep info."); return (rc); } fmt = "error writing %s forth info"; if (rc = cpr_write(vp, (caddr_t)ustr, sizeof (ustr))) cpr_err(CE_WARN, fmt, "unix-tte"); return (rc); }
void cpu_lwp_fork(register struct lwp *l1, register struct lwp *l2, void *stack, size_t stacksize, void (*func)(void *), void *arg) { struct pcb *opcb = lwp_getpcb(l1); struct pcb *npcb = lwp_getpcb(l2); struct trapframe *tf2; struct rwindow *rp; /* * Save all user registers to l1's stack or, in the case of * user registers and invalid stack pointers, to opcb. * We then copy the whole pcb to l2; when switch() selects l2 * to run, it will run at the `lwp_trampoline' stub, rather * than returning at the copying code below. * * If process l1 has an FPU state, we must copy it. If it is * the FPU user, we must save the FPU state first. */ #ifdef NOTDEF_DEBUG printf("cpu_lwp_fork()\n"); #endif if (l1 == curlwp) { write_user_windows(); /* * We're in the kernel, so we don't really care about * %ccr or %asi. We do want to duplicate %pstate and %cwp. */ opcb->pcb_pstate = getpstate(); opcb->pcb_cwp = getcwp(); } #ifdef DIAGNOSTIC else if (l1 != &lwp0) panic("cpu_lwp_fork: curlwp"); #endif #ifdef DEBUG /* prevent us from having NULL lastcall */ opcb->lastcall = cpu_forkname; #else opcb->lastcall = NULL; #endif memcpy(npcb, opcb, sizeof(struct pcb)); if (l1->l_md.md_fpstate) { fpusave_lwp(l1, true); l2->l_md.md_fpstate = pool_cache_get(fpstate_cache, PR_WAITOK); memcpy(l2->l_md.md_fpstate, l1->l_md.md_fpstate, sizeof(struct fpstate64)); } else l2->l_md.md_fpstate = NULL; /* * Setup (kernel) stack frame that will by-pass the child * out of the kernel. (The trap frame invariably resides at * the tippity-top of the u. area.) */ tf2 = l2->l_md.md_tf = (struct trapframe *) ((long)npcb + USPACE - sizeof(*tf2)); /* Copy parent's trapframe */ *tf2 = *(struct trapframe *)((long)opcb + USPACE - sizeof(*tf2)); /* * If specified, give the child a different stack. */ if (stack != NULL) tf2->tf_out[6] = (uint64_t)(u_long)stack + stacksize; /* * Set return values in child mode and clear condition code, * in case we end up running a signal handler before returning * to userland. */ tf2->tf_out[0] = 0; tf2->tf_out[1] = 1; tf2->tf_tstate &= ~TSTATE_CCR; /* Construct kernel frame to return to in cpu_switch() */ rp = (struct rwindow *)((u_long)npcb + TOPFRAMEOFF); *rp = *(struct rwindow *)((u_long)opcb + TOPFRAMEOFF); rp->rw_local[0] = (long)func; /* Function to call */ rp->rw_local[1] = (long)arg; /* and its argument */ rp->rw_local[2] = (long)l2; /* new lwp */ npcb->pcb_pc = (long)lwp_trampoline - 8; npcb->pcb_sp = (long)rp - STACK_OFFSET; }