int compat_16_netbsd32___sigreturn14(struct lwp *l, const struct compat_16_netbsd32___sigreturn14_args *uap, register_t *retval) { /* { syscallarg(netbsd32_sigcontextp_t) sigcntxp; } */ struct netbsd32_sigcontext *scp, context; struct proc *p = l->l_proc; struct trapframe *tf; int error; /* * The trampoline code hands us the context. * It is unsafe to keep track of it ourselves, in the event that a * program jumps out of a signal handler. */ scp = NETBSD32PTR64(SCARG(uap, sigcntxp)); if (copyin(scp, &context, sizeof(*scp)) != 0) return (EFAULT); /* * Check for security violations. */ error = check_sigcontext32(l, &context); if (error != 0) return error; /* Restore register context. */ tf = l->l_md.md_regs; tf->tf_ds = context.sc_ds; tf->tf_es = context.sc_es; cpu_fsgs_reload(l, context.sc_fs, context.sc_gs); tf->tf_rflags = context.sc_eflags; tf->tf_rdi = context.sc_edi; tf->tf_rsi = context.sc_esi; tf->tf_rbp = context.sc_ebp; tf->tf_rbx = context.sc_ebx; tf->tf_rdx = context.sc_edx; tf->tf_rcx = context.sc_ecx; tf->tf_rax = context.sc_eax; tf->tf_rip = context.sc_eip; tf->tf_cs = context.sc_cs; tf->tf_rsp = context.sc_esp; tf->tf_ss = context.sc_ss; mutex_enter(p->p_lock); /* Restore signal stack. */ if (context.sc_onstack & SS_ONSTACK) l->l_sigstk.ss_flags |= SS_ONSTACK; else l->l_sigstk.ss_flags &= ~SS_ONSTACK; /* Restore signal mask. */ (void) sigprocmask1(l, SIG_SETMASK, &context.sc_mask, 0); mutex_exit(p->p_lock); return (EJUSTRETURN); }
void linux32_setregs(struct lwp *l, struct exec_package *pack, u_long stack) { struct pcb *pcb = lwp_getpcb(l); struct trapframe *tf; struct proc *p = l->l_proc; /* If we were using the FPU, forget about it. */ if (pcb->pcb_fpcpu != NULL) fpusave_lwp(l, 0); #if defined(USER_LDT) && 0 pmap_ldt_cleanup(p); #endif netbsd32_adjust_limits(p); l->l_md.md_flags &= ~MDL_USEDFPU; l->l_md.md_flags |= MDL_COMPAT32; /* Forces iret not sysret */ pcb->pcb_flags = PCB_COMPAT32; pcb->pcb_savefpu.fp_fxsave.fx_fcw = __Linux_NPXCW__; pcb->pcb_savefpu.fp_fxsave.fx_mxcsr = __INITIAL_MXCSR__; pcb->pcb_savefpu.fp_fxsave.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__; p->p_flag |= PK_32; tf = l->l_md.md_regs; tf->tf_rax = 0; tf->tf_rbx = (u_int32_t)p->p_psstrp; tf->tf_rcx = pack->ep_entry & 0xffffffff; tf->tf_rdx = 0; tf->tf_rsi = 0; tf->tf_rdi = 0; tf->tf_rbp = 0; tf->tf_rsp = stack & 0xffffffff; tf->tf_r8 = 0; tf->tf_r9 = 0; tf->tf_r10 = 0; tf->tf_r11 = 0; tf->tf_r12 = 0; tf->tf_r13 = 0; tf->tf_r14 = 0; tf->tf_r15 = 0; tf->tf_rip = pack->ep_entry & 0xffffffff; tf->tf_rflags = PSL_USERSET; tf->tf_cs = GSEL(GUCODE32_SEL, SEL_UPL); tf->tf_ss = GSEL(GUDATA32_SEL, SEL_UPL); tf->tf_ds = GSEL(GUDATA32_SEL, SEL_UPL); tf->tf_es = GSEL(GUDATA32_SEL, SEL_UPL); cpu_fsgs_zero(l); cpu_fsgs_reload(l, GSEL(GUDATA32_SEL, SEL_UPL), GSEL(GUDATA32_SEL, SEL_UPL)); }
void netbsd32_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) { struct pcb *pcb; struct trapframe *tf; struct proc *p = l->l_proc; pcb = lwp_getpcb(l); /* If we were using the FPU, forget about it. */ if (pcb->pcb_fpcpu != NULL) { fpusave_lwp(l, false); } #if defined(USER_LDT) && 0 pmap_ldt_cleanup(p); #endif netbsd32_adjust_limits(p); l->l_md.md_flags &= ~MDL_USEDFPU; l->l_md.md_flags |= MDL_COMPAT32; /* Force iret not sysret */ pcb->pcb_flags = PCB_COMPAT32; if (pack->ep_osversion >= 699002600) pcb->pcb_savefpu.fp_fxsave.fx_fcw = __NetBSD_NPXCW__; else pcb->pcb_savefpu.fp_fxsave.fx_fcw = __NetBSD_COMPAT_NPXCW__; pcb->pcb_savefpu.fp_fxsave.fx_mxcsr = __INITIAL_MXCSR__; pcb->pcb_savefpu.fp_fxsave.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__; p->p_flag |= PK_32; tf = l->l_md.md_regs; tf->tf_ds = LSEL(LUDATA32_SEL, SEL_UPL); tf->tf_es = LSEL(LUDATA32_SEL, SEL_UPL); cpu_fsgs_zero(l); cpu_fsgs_reload(l, tf->tf_ds, tf->tf_es); tf->tf_rdi = 0; tf->tf_rsi = 0; tf->tf_rbp = 0; tf->tf_rbx = (uint32_t)p->p_psstrp; tf->tf_rdx = 0; tf->tf_rcx = 0; tf->tf_rax = 0; tf->tf_rip = pack->ep_entry; tf->tf_cs = LSEL(LUCODE32_SEL, SEL_UPL); tf->tf_rflags = PSL_USERSET; tf->tf_rsp = stack; tf->tf_ss = LSEL(LUDATA32_SEL, SEL_UPL); }
void linux32_setregs(struct lwp *l, struct exec_package *pack, u_long stack) { struct pcb *pcb = lwp_getpcb(l); struct trapframe *tf; struct proc *p = l->l_proc; #if defined(USER_LDT) && 0 pmap_ldt_cleanup(l); #endif netbsd32_adjust_limits(p); fpu_save_area_clear(l, __Linux_NPXCW__); l->l_md.md_flags |= MDL_COMPAT32; /* Forces iret not sysret */ pcb->pcb_flags = PCB_COMPAT32; p->p_flag |= PK_32; tf = l->l_md.md_regs; tf->tf_rax = 0; tf->tf_rbx = (u_int32_t)p->p_psstrp; tf->tf_rcx = pack->ep_entry & 0xffffffff; tf->tf_rdx = 0; tf->tf_rsi = 0; tf->tf_rdi = 0; tf->tf_rbp = 0; tf->tf_rsp = stack & 0xffffffff; tf->tf_r8 = 0; tf->tf_r9 = 0; tf->tf_r10 = 0; tf->tf_r11 = 0; tf->tf_r12 = 0; tf->tf_r13 = 0; tf->tf_r14 = 0; tf->tf_r15 = 0; tf->tf_rip = pack->ep_entry & 0xffffffff; tf->tf_rflags = PSL_USERSET; tf->tf_cs = GSEL(GUCODE32_SEL, SEL_UPL); tf->tf_ss = GSEL(GUDATA32_SEL, SEL_UPL); tf->tf_ds = GSEL(GUDATA32_SEL, SEL_UPL); tf->tf_es = GSEL(GUDATA32_SEL, SEL_UPL); cpu_fsgs_zero(l); cpu_fsgs_reload(l, GSEL(GUDATA32_SEL, SEL_UPL), GSEL(GUDATA32_SEL, SEL_UPL)); }
static int linux32_restore_sigcontext(struct lwp *l, struct linux32_sigcontext *scp, register_t *retval) { struct trapframe *tf; struct proc *p = l->l_proc; struct sigaltstack *sas = &l->l_sigstk; struct pcb *pcb; sigset_t mask; ssize_t ss_gap; register_t fssel, gssel; /* Restore register context. */ tf = l->l_md.md_regs; pcb = lwp_getpcb(l); DPRINTF(("sigreturn enter rsp=0x%lx rip=0x%lx\n", tf->tf_rsp, tf->tf_rip)); /* * Check for security violations. */ if (((scp->sc_eflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0 || !USERMODE(scp->sc_cs, scp->sc_eflags)) return EINVAL; if (scp->sc_fs != 0 && !VALID_USER_DSEL32(scp->sc_fs) && !(VALID_USER_FSEL32(scp->sc_fs) && pcb->pcb_fs != 0)) return EINVAL; if (scp->sc_gs != 0 && !VALID_USER_DSEL32(scp->sc_gs) && !(VALID_USER_GSEL32(scp->sc_gs) && pcb->pcb_gs != 0)) return EINVAL; if (scp->sc_es != 0 && !VALID_USER_DSEL32(scp->sc_es)) return EINVAL; if (!VALID_USER_DSEL32(scp->sc_ds) || !VALID_USER_DSEL32(scp->sc_ss)) return EINVAL; if (scp->sc_eip >= VM_MAXUSER_ADDRESS32) return EINVAL; gssel = (register_t)scp->sc_gs & 0xffff; fssel = (register_t)scp->sc_fs & 0xffff; cpu_fsgs_reload(l, fssel, gssel); tf->tf_es = (register_t)scp->sc_es & 0xffff; tf->tf_ds = (register_t)scp->sc_ds & 0xffff; tf->tf_rflags &= ~PSL_USER; tf->tf_rflags |= ((register_t)scp->sc_eflags & PSL_USER); tf->tf_rdi = (register_t)scp->sc_edi & 0xffffffff; tf->tf_rsi = (register_t)scp->sc_esi & 0xffffffff; tf->tf_rbp = (register_t)scp->sc_ebp & 0xffffffff; tf->tf_rbx = (register_t)scp->sc_ebx & 0xffffffff; tf->tf_rdx = (register_t)scp->sc_edx & 0xffffffff; tf->tf_rcx = (register_t)scp->sc_ecx & 0xffffffff; tf->tf_rax = (register_t)scp->sc_eax & 0xffffffff; tf->tf_rip = (register_t)scp->sc_eip & 0xffffffff; tf->tf_cs = (register_t)scp->sc_cs & 0xffff; tf->tf_rsp = (register_t)scp->sc_esp_at_signal & 0xffffffff; tf->tf_ss = (register_t)scp->sc_ss & 0xffff; mutex_enter(p->p_lock); /* Restore signal stack. */ ss_gap = (ssize_t) ((char *)NETBSD32IPTR64(scp->sc_esp_at_signal) - (char *)sas->ss_sp); if (ss_gap >= 0 && ss_gap < sas->ss_size) sas->ss_flags |= SS_ONSTACK; else sas->ss_flags &= ~SS_ONSTACK; /* Restore signal mask. */ linux32_old_to_native_sigset(&mask, &scp->sc_mask); (void) sigprocmask1(l, SIG_SETMASK, &mask, 0); mutex_exit(p->p_lock); DPRINTF(("linux32_sigreturn: rip = 0x%lx, rsp = 0x%lx, flags = 0x%lx\n", tf->tf_rip, tf->tf_rsp, tf->tf_rflags)); return EJUSTRETURN; }
int cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags) { struct trapframe *tf = l->l_md.md_regs; const __greg32_t *gr = mcp->__gregs; struct proc *p = l->l_proc; int error; /* Restore register context, if any. */ if ((flags & _UC_CPU) != 0) { /* * Check for security violations. */ error = cpu_mcontext32_validate(l, mcp); if (error != 0) return error; cpu_fsgs_reload(l, gr[_REG32_FS], gr[_REG32_GS]); tf->tf_es = gr[_REG32_ES]; tf->tf_ds = gr[_REG32_DS]; /* Only change the user-alterable part of eflags */ tf->tf_rflags &= ~PSL_USER; tf->tf_rflags |= (gr[_REG32_EFL] & PSL_USER); tf->tf_rdi = gr[_REG32_EDI]; tf->tf_rsi = gr[_REG32_ESI]; tf->tf_rbp = gr[_REG32_EBP]; tf->tf_rbx = gr[_REG32_EBX]; tf->tf_rdx = gr[_REG32_EDX]; tf->tf_rcx = gr[_REG32_ECX]; tf->tf_rax = gr[_REG32_EAX]; tf->tf_rip = gr[_REG32_EIP]; tf->tf_cs = gr[_REG32_CS]; tf->tf_rsp = gr[_REG32_UESP]; tf->tf_ss = gr[_REG32_SS]; } if ((flags & _UC_TLSBASE) != 0) lwp_setprivate(l, (void *)(uintptr_t)mcp->_mc_tlsbase); /* Restore floating point register context, if any. */ if ((flags & _UC_FPU) != 0) { struct pcb *pcb = lwp_getpcb(l); /* * If we were using the FPU, forget that we were. */ if (pcb->pcb_fpcpu != NULL) { fpusave_lwp(l, false); } memcpy(&pcb->pcb_savefpu.fp_fxsave, &mcp->__fpregs, sizeof (pcb->pcb_savefpu.fp_fxsave)); /* If not set already. */ l->l_md.md_flags |= MDL_USEDFPU; } mutex_enter(p->p_lock); if (flags & _UC_SETSTACK) l->l_sigstk.ss_flags |= SS_ONSTACK; if (flags & _UC_CLRSTACK) l->l_sigstk.ss_flags &= ~SS_ONSTACK; mutex_exit(p->p_lock); return (0); }