Example #1
0
/*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;
}
Example #2
0
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;
}
Example #3
0
/*
 * 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);
	}
}