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; }
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); }
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; }