/*ARGSUSED1*/ void xregrestore(klwp_t *lwp, int shared) { /* * If locals+ins were modified by /proc copy them out. * Also copy to the shared window, if necessary. */ if (lwp->lwp_pcb.pcb_xregstat == XREGMODIFIED) { struct machpcb *mpcb = lwptompcb(lwp); caddr_t sp = (caddr_t)lwptoregs(lwp)->r_sp; size_t rwinsize; caddr_t rwp; int is64; if (lwp_getdatamodel(lwp) == DATAMODEL_LP64) { rwinsize = sizeof (struct rwindow); rwp = sp + STACK_BIAS; is64 = 1; } else { rwinsize = sizeof (struct rwindow32); sp = (caddr_t)(uintptr_t)(caddr32_t)(uintptr_t)sp; rwp = sp; is64 = 0; } if (is64) (void) copyout_nowatch(&lwp->lwp_pcb.pcb_xregs, rwp, rwinsize); else { struct rwindow32 rwindow32; int watched; watched = watch_disable_addr(rwp, rwinsize, S_WRITE); rwindow_nto32(&lwp->lwp_pcb.pcb_xregs, &rwindow32); (void) copyout(&rwindow32, rwp, rwinsize); if (watched) watch_enable_addr(rwp, rwinsize, S_WRITE); } /* also copy to the user return window */ mpcb->mpcb_rsp[0] = sp; mpcb->mpcb_rsp[1] = NULL; bcopy(&lwp->lwp_pcb.pcb_xregs, &mpcb->mpcb_rwin[0], sizeof (lwp->lwp_pcb.pcb_xregs)); } lwp->lwp_pcb.pcb_xregstat = XREGNONE; }
void lwp_stk_fini(klwp_t *lwp) { struct machpcb *mpcb = lwptompcb(lwp); /* * there might be windows still in the wbuf due to unmapped * stack, misaligned stack pointer, etc. We just free it. */ mpcb->mpcb_wbcnt = 0; if (mpcb->mpcb_wstate == WSTATE_USER32) kmem_cache_free(wbuf32_cache, mpcb->mpcb_wbuf); else kmem_cache_free(wbuf64_cache, mpcb->mpcb_wbuf); mpcb->mpcb_wbuf = NULL; mpcb->mpcb_wbuf_pa = -1; }
/* * Copy regs from parent to child. */ void lwp_forkregs(klwp_t *lwp, klwp_t *clwp) { kthread_t *t, *pt = lwptot(lwp); struct machpcb *mpcb = lwptompcb(clwp); struct machpcb *pmpcb = lwptompcb(lwp); kfpu_t *fp, *pfp = lwptofpu(lwp); caddr_t wbuf; uint_t wstate; t = mpcb->mpcb_thread; /* * remember child's fp and wbuf since they will get erased during * the bcopy. */ fp = mpcb->mpcb_fpu; wbuf = mpcb->mpcb_wbuf; wstate = mpcb->mpcb_wstate; /* * Don't copy mpcb_frame since we hand-crafted it * in thread_load(). */ bcopy(lwp->lwp_regs, clwp->lwp_regs, sizeof (struct machpcb) - REGOFF); mpcb->mpcb_thread = t; mpcb->mpcb_fpu = fp; fp->fpu_q = mpcb->mpcb_fpu_q; /* * It is theoretically possibly for the lwp's wstate to * be different from its value assigned in lwp_stk_init, * since lwp_stk_init assumed the data model of the process. * Here, we took on the data model of the cloned lwp. */ if (mpcb->mpcb_wstate != wstate) { if (wstate == WSTATE_USER32) { kmem_cache_free(wbuf32_cache, wbuf); wbuf = kmem_cache_alloc(wbuf64_cache, KM_SLEEP); wstate = WSTATE_USER64; } else { kmem_cache_free(wbuf64_cache, wbuf); wbuf = kmem_cache_alloc(wbuf32_cache, KM_SLEEP); wstate = WSTATE_USER32; } } mpcb->mpcb_pa = va_to_pa(mpcb); mpcb->mpcb_wbuf = wbuf; mpcb->mpcb_wbuf_pa = va_to_pa(wbuf); ASSERT(mpcb->mpcb_wstate == wstate); if (mpcb->mpcb_wbcnt != 0) { bcopy(pmpcb->mpcb_wbuf, mpcb->mpcb_wbuf, mpcb->mpcb_wbcnt * ((mpcb->mpcb_wstate == WSTATE_USER32) ? sizeof (struct rwindow32) : sizeof (struct rwindow64))); } if (pt == curthread) pfp->fpu_fprs = _fp_read_fprs(); if ((pfp->fpu_en) || (pfp->fpu_fprs & FPRS_FEF)) { if (pt == curthread && fpu_exists) { save_gsr(clwp->lwp_fpu); } else { uint64_t gsr; gsr = get_gsr(lwp->lwp_fpu); set_gsr(gsr, clwp->lwp_fpu); } fp_fork(lwp, clwp); } }