Exemplo n.º 1
0
int
sys_setcontext(struct lwp *l, const struct sys_setcontext_args *uap,
    register_t *retval)
{
	/* {
		syscallarg(const ucontext_t *) ucp;
	} */
	struct proc *p = l->l_proc;
	ucontext_t uc;
	int error;

	error = copyin(SCARG(uap, ucp), &uc, sizeof (uc));
	if (error)
		return error;
	if ((uc.uc_flags & _UC_CPU) == 0)
		return EINVAL;
	mutex_enter(p->p_lock);
	error = setucontext(l, &uc);
	mutex_exit(p->p_lock);
	if (error)
 		return error;

	return EJUSTRETURN;
}
Exemplo n.º 2
0
int
linux_sys_rt_sigreturn(struct lwp *l, const void *v, register_t *retval)
{
    struct linux_ucontext *luctx;
    struct trapframe *tf = l->l_md.md_regs;
    struct linux_sigcontext *lsigctx;
    struct linux_rt_sigframe frame, *fp;
    ucontext_t uctx;
    mcontext_t *mctx;
    int error;

    fp = (struct linux_rt_sigframe *)(tf->tf_regs[_R_SP]);
    if ((error = copyin(fp, &frame, sizeof(frame))) != 0) {
        mutex_enter(l->l_proc->p_lock);
        sigexit(l, SIGILL);
        return error;
    }

    luctx = &frame.lrs_uc;
    lsigctx = &luctx->luc_mcontext;

    bzero(&uctx, sizeof(uctx));
    mctx = (mcontext_t *)&uctx.uc_mcontext;

    /*
     * Set the flags. Linux always have CPU, stack and signal state,
     * FPU is optional. uc_flags is not used to tell what we have.
     */
    uctx.uc_flags = (_UC_SIGMASK|_UC_CPU|_UC_STACK);
    uctx.uc_link = NULL;

    /*
     * Signal set.
     */
    linux_to_native_sigset(&uctx.uc_sigmask, &luctx->luc_sigmask);

    /*
     * CPU state.
     */
    memcpy(mctx->__gregs, lsigctx->lsc_regs, sizeof(lsigctx->lsc_regs));

    /*
     * And the stack.
     */
    uctx.uc_stack.ss_flags = 0;
    if (luctx->luc_stack.ss_flags & LINUX_SS_ONSTACK)
        uctx.uc_stack.ss_flags |= SS_ONSTACK;

    if (luctx->luc_stack.ss_flags & LINUX_SS_DISABLE)
        uctx.uc_stack.ss_flags |= SS_DISABLE;

    uctx.uc_stack.ss_sp = luctx->luc_stack.ss_sp;
    uctx.uc_stack.ss_size = luctx->luc_stack.ss_size;

    /*
     * And let setucontext deal with that.
     */
    mutex_enter(l->l_proc->p_lock);
    error = setucontext(l, &uctx);
    mutex_exit(l->l_proc->p_lock);
    if (error)
        return error;

    return (EJUSTRETURN);
}
Exemplo n.º 3
0
int
linux_sys_rt_sigreturn(struct lwp *l, const void *v, register_t *retval)
{
	struct linux_ucontext *luctx;
	struct trapframe *tf = l->l_md.md_regs;
	struct linux_sigcontext *lsigctx;
	struct linux__fpstate fpstate;
	struct linux_rt_sigframe frame, *fp;
	ucontext_t uctx;
	mcontext_t *mctx;
	struct fxsave64 *fxarea;
	int error;

	fp = (struct linux_rt_sigframe *)(tf->tf_rsp - 8);
	if ((error = copyin(fp, &frame, sizeof(frame))) != 0) {
		mutex_enter(l->l_proc->p_lock);
		sigexit(l, SIGILL);
		return error;
	}
	luctx = &frame.uc;
	lsigctx = &luctx->luc_mcontext;

	bzero(&uctx, sizeof(uctx));
	mctx = (mcontext_t *)&uctx.uc_mcontext;
	fxarea = (struct fxsave64 *)&mctx->__fpregs;

	/* 
	 * Set the flags. Linux always have CPU, stack and signal state,
	 * FPU is optional. uc_flags is not used to tell what we have.
	 */
	uctx.uc_flags = (_UC_SIGMASK|_UC_CPU|_UC_STACK|_UC_CLRSTACK);
	if (lsigctx->fpstate != NULL)
		uctx.uc_flags |= _UC_FPU;
	uctx.uc_link = NULL;

	/*
	 * Signal set 
	 */
	linux_to_native_sigset(&uctx.uc_sigmask, &luctx->luc_sigmask);

	/*
	 * CPU state
	 */
	mctx->__gregs[_REG_R8] = lsigctx->r8;
	mctx->__gregs[_REG_R9] = lsigctx->r9;
	mctx->__gregs[_REG_R10] = lsigctx->r10;
	mctx->__gregs[_REG_R11] = lsigctx->r11;
	mctx->__gregs[_REG_R12] = lsigctx->r12;
	mctx->__gregs[_REG_R13] = lsigctx->r13;
	mctx->__gregs[_REG_R14] = lsigctx->r14;
	mctx->__gregs[_REG_R15] = lsigctx->r15;
	mctx->__gregs[_REG_RDI] = lsigctx->rdi;
	mctx->__gregs[_REG_RSI] = lsigctx->rsi;
	mctx->__gregs[_REG_RBP] = lsigctx->rbp;
	mctx->__gregs[_REG_RBX] = lsigctx->rbx;
	mctx->__gregs[_REG_RAX] = lsigctx->rax;
	mctx->__gregs[_REG_RDX] = lsigctx->rdx;
	mctx->__gregs[_REG_RCX] = lsigctx->rcx;
	mctx->__gregs[_REG_RIP] = lsigctx->rip;
	mctx->__gregs[_REG_RFLAGS] = lsigctx->eflags;
	mctx->__gregs[_REG_CS] = lsigctx->cs;
	mctx->__gregs[_REG_GS] = lsigctx->gs;
	mctx->__gregs[_REG_FS] = lsigctx->fs;
	mctx->__gregs[_REG_ERR] = lsigctx->err;
	mctx->__gregs[_REG_TRAPNO] = lsigctx->trapno;
	mctx->__gregs[_REG_ES] = tf->tf_es;
	mctx->__gregs[_REG_DS] = tf->tf_ds;
	mctx->__gregs[_REG_RSP] = lsigctx->rsp; /* XXX */
	mctx->__gregs[_REG_SS] = tf->tf_ss;

	/*
	 * FPU state 
	 */
	if (lsigctx->fpstate != NULL) {
		error = copyin(lsigctx->fpstate, &fpstate, sizeof(fpstate));
		if (error != 0) {
			mutex_enter(l->l_proc->p_lock);
			sigexit(l, SIGILL);
			return error;
		}

		fxarea->fx_fcw = fpstate.cwd;
		fxarea->fx_fsw = fpstate.swd;
		fxarea->fx_ftw = fpstate.twd;
		fxarea->fx_fop = fpstate.fop;
		fxarea->fx_rip = fpstate.rip;
		fxarea->fx_rdp = fpstate.rdp;
		fxarea->fx_mxcsr = fpstate.mxcsr;
		fxarea->fx_mxcsr_mask = fpstate.mxcsr_mask;
		memcpy(&fxarea->fx_st, &fpstate.st_space, 
		    sizeof(fxarea->fx_st));
		memcpy(&fxarea->fx_xmm, &fpstate.xmm_space, 
		    sizeof(fxarea->fx_xmm));
	}

	/*
	 * And the stack
	 */
	uctx.uc_stack.ss_flags = 0;
	if (luctx->luc_stack.ss_flags & LINUX_SS_ONSTACK)
		uctx.uc_stack.ss_flags |= SS_ONSTACK;

	if (luctx->luc_stack.ss_flags & LINUX_SS_DISABLE)
		uctx.uc_stack.ss_flags |= SS_DISABLE;

	uctx.uc_stack.ss_sp = luctx->luc_stack.ss_sp;
	uctx.uc_stack.ss_size = luctx->luc_stack.ss_size;

	/*
	 * And let setucontext deal with that.
	 */
	mutex_enter(l->l_proc->p_lock);
	error = setucontext(l, &uctx);
	mutex_exit(l->l_proc->p_lock);
	if (error)
		return error;

	return EJUSTRETURN;
}