int netbsd32_cpu_setmcontext( struct lwp *l, /* XXX const netbsd32_*/mcontext_t *mcp, unsigned int flags) { #ifdef NOT_YET /* XXX */ greg32_t *gr = mcp->__gregs; struct trapframe64 *tf = l->l_md.md_tf; /* First ensure consistent stack state (see sendsig). */ write_user_windows(); if (rwindow_save(p)) { mutex_enter(l->l_proc->p_lock); sigexit(p, SIGILL); } if ((flags & _UC_CPU) != 0) { /* * Only the icc bits in the psr are used, so it need not be * verified. pc and npc must be multiples of 4. This is all * that is required; if it holds, just do it. */ if (((gr[_REG_PC] | gr[_REG_nPC]) & 3) != 0 || gr[_REG_PC] == 0 || gr[_REG_nPC] == 0) return (EINVAL); /* Restore general register context. */ /* take only tstate CCR (and ASI) fields */ tf->tf_tstate = (tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(gr[_REG_PSR]); tf->tf_pc = (uint64_t)gr[_REG_PC]; tf->tf_npc = (uint64_t)gr[_REG_nPC]; tf->tf_y = (uint64_t)gr[_REG_Y]; tf->tf_global[1] = (uint64_t)gr[_REG_G1]; tf->tf_global[2] = (uint64_t)gr[_REG_G2]; tf->tf_global[3] = (uint64_t)gr[_REG_G3]; tf->tf_global[4] = (uint64_t)gr[_REG_G4]; tf->tf_global[5] = (uint64_t)gr[_REG_G5]; tf->tf_global[6] = (uint64_t)gr[_REG_G6]; tf->tf_global[7] = (uint64_t)gr[_REG_G7]; tf->tf_out[0] = (uint64_t)gr[_REG_O0]; tf->tf_out[1] = (uint64_t)gr[_REG_O1]; tf->tf_out[2] = (uint64_t)gr[_REG_O2]; tf->tf_out[3] = (uint64_t)gr[_REG_O3]; tf->tf_out[4] = (uint64_t)gr[_REG_O4]; tf->tf_out[5] = (uint64_t)gr[_REG_O5]; tf->tf_out[6] = (uint64_t)gr[_REG_O6]; tf->tf_out[7] = (uint64_t)gr[_REG_O7]; /* %asi restored above; %fprs not yet supported. */ /* XXX mcp->__gwins */ } /* Restore FP register context, if any. */ if ((flags & _UC_FPU) != 0 && mcp->__fpregs.__fpu_en != 0) { struct fpstate *fsp; const netbsd32_fpregset_t *fpr = &mcp->__fpregs; int reload = 0; /* * If we're the current FPU owner, simply reload it from * the supplied context. Otherwise, store it into the * process' FPU save area (which is used to restore from * by lazy FPU context switching); allocate it if necessary. */ /* * XXX Should we really activate the supplied FPU context * XXX immediately or just fault it in later? */ if ((fsp = l->l_md.md_fpstate) == NULL) { fsp = pool_cache_get(fpstate_cache, PR_WAITOK); l->l_md.md_fpstate = fsp; } else { /* Drop the live context on the floor. */ fpusave_lwp(l, false); reload = 1; } /* Note: sizeof fpr->__fpu_fr <= sizeof fsp->fs_regs. */ memcpy(fsp->fs_regs, fpr->__fpu_fr, sizeof (fpr->__fpu_fr)); fsp->fs_fsr = fpr->__fpu_fsr; /* don't care about fcc1-3 */ fsp->fs_qsize = 0; #if 0 /* Need more info! */ mcp->__fpregs.__fpu_q = NULL; /* `Need more info.' */ mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */ #endif /* Reload context again, if necessary. */ if (reload) loadfpstate(fsp); } /* XXX mcp->__xrs */ /* XXX mcp->__asrs */ #endif return (0); }
/* ARGSUSED */ int compat_16_netbsd32___sigreturn14(struct lwp *l, const struct compat_16_netbsd32___sigreturn14_args *uap, register_t *retval) { /* { syscallarg(struct sigcontext *) sigcntxp; } */ struct netbsd32_sigcontext sc, *scp; struct trapframe64 *tf; struct proc *p = l->l_proc; /* First ensure consistent stack state (see sendsig). */ write_user_windows(); if (rwindow_save(l)) { #ifdef DEBUG printf("netbsd32_sigreturn14: rwindow_save(%p) failed, sending SIGILL\n", p); Debugger(); #endif mutex_enter(p->p_lock); sigexit(l, SIGILL); } #ifdef DEBUG if (sigdebug & SDB_FOLLOW) { printf("netbsd32_sigreturn14: %s[%d], sigcntxp %p\n", p->p_comm, p->p_pid, SCARG(uap, sigcntxp)); if (sigdebug & SDB_DDB) Debugger(); } #endif scp = (struct netbsd32_sigcontext *)(u_long)SCARG(uap, sigcntxp); if ((vaddr_t)scp & 3 || (copyin((void *)scp, &sc, sizeof sc) != 0)) { #ifdef DEBUG printf("netbsd32_sigreturn14: copyin failed: scp=%p\n", scp); Debugger(); #endif return (EINVAL); } scp = ≻ tf = l->l_md.md_tf; /* * Only the icc bits in the psr are used, so it need not be * verified. pc and npc must be multiples of 4. This is all * that is required; if it holds, just do it. */ if (((sc.sc_pc | sc.sc_npc) & 3) != 0 || (sc.sc_pc == 0) || (sc.sc_npc == 0)) #ifdef DEBUG { printf("netbsd32_sigreturn14: pc %p or npc %p invalid\n", sc.sc_pc, sc.sc_npc); Debugger(); return (EINVAL); } #else return (EINVAL); #endif /* take only psr ICC field */ tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(sc.sc_psr); tf->tf_pc = (int64_t)sc.sc_pc; tf->tf_npc = (int64_t)sc.sc_npc; tf->tf_global[1] = (int64_t)sc.sc_g1; tf->tf_out[0] = (int64_t)sc.sc_o0; tf->tf_out[6] = (int64_t)sc.sc_sp; #ifdef DEBUG if (sigdebug & SDB_FOLLOW) { printf("netbsd32_sigreturn14: return trapframe pc=%p sp=%p tstate=%llx\n", (vaddr_t)tf->tf_pc, (vaddr_t)tf->tf_out[6], tf->tf_tstate); if (sigdebug & SDB_DDB) Debugger(); } #endif /* Restore signal stack. */ mutex_enter(p->p_lock); if (sc.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, &sc.sc_mask, 0); mutex_exit(p->p_lock); return (EJUSTRETURN); }
void netbsd32_cpu_getmcontext( struct lwp *l, /* netbsd32_mcontext_t XXX */mcontext_t *mcp, unsigned int *flags) { #if 0 /* XXX */ greg32_t *gr = mcp->__gregs; const struct trapframe64 *tf = l->l_md.md_tf; /* First ensure consistent stack state (see sendsig). */ /* XXX? */ write_user_windows(); if (rwindow_save(l)) { mutex_enter(l->l_proc->p_lock); sigexit(l, SIGILL); } /* For now: Erase any random indicators for optional state. */ (void)memset(mcp, 0, sizeof (*mcp)); /* Save general register context. */ gr[_REG_PSR] = TSTATECCR_TO_PSR(tf->tf_tstate); gr[_REG_PC] = tf->tf_pc; gr[_REG_nPC] = tf->tf_npc; gr[_REG_Y] = tf->tf_y; gr[_REG_G1] = tf->tf_global[1]; gr[_REG_G2] = tf->tf_global[2]; gr[_REG_G3] = tf->tf_global[3]; gr[_REG_G4] = tf->tf_global[4]; gr[_REG_G5] = tf->tf_global[5]; gr[_REG_G6] = tf->tf_global[6]; gr[_REG_G7] = tf->tf_global[7]; gr[_REG_O0] = tf->tf_out[0]; gr[_REG_O1] = tf->tf_out[1]; gr[_REG_O2] = tf->tf_out[2]; gr[_REG_O3] = tf->tf_out[3]; gr[_REG_O4] = tf->tf_out[4]; gr[_REG_O5] = tf->tf_out[5]; gr[_REG_O6] = tf->tf_out[6]; gr[_REG_O7] = tf->tf_out[7]; *flags |= (_UC_CPU|_UC_TLSBASE); mcp->__gwins = 0; /* Save FP register context, if any. */ if (l->l_md.md_fpstate != NULL) { struct fpstate *fsp; netbsd32_fpregset_t *fpr = &mcp->__fpregs; /* * If our FP context is currently held in the FPU, take a * private snapshot - lazy FPU context switching can deal * with it later when it becomes necessary. * Otherwise, get it from the process's save area. */ fpusave_lwp(l, true); fsp = l->l_md.md_fpstate; memcpy(&fpr->__fpu_fr, fsp->fs_regs, sizeof (fpr->__fpu_fr)); mcp->__fpregs.__fpu_q = NULL; /* `Need more info.' */ mcp->__fpregs.__fpu_fsr = fs.fs_fsr; mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */ mcp->__fpregs.__fpu_q_entrysize = sizeof (struct netbsd32_fq); mcp->__fpregs.__fpu_en = 1; *flags |= _UC_FPU; } else { mcp->__fpregs.__fpu_en = 0; } mcp->__xrs.__xrs_id = 0; /* Solaris extension? */ #endif }
int cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags) { struct trapframe *tf = l->l_md.md_tf; const __greg32_t *gr = mcp->__gregs; struct proc *p = l->l_proc; int error; /* First ensure consistent stack state (see sendsig). */ write_user_windows(); if (rwindow_save(l)) { mutex_enter(p->p_lock); sigexit(l, SIGILL); } /* Restore register context, if any. */ if ((flags & _UC_CPU) != 0) { error = cpu_mcontext32_validate(l, mcp); if (error) return error; /* Restore general register context. */ /* take only tstate CCR (and ASI) fields */ tf->tf_tstate = (tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(gr[_REG32_PSR]); tf->tf_pc = (uint64_t)gr[_REG32_PC]; tf->tf_npc = (uint64_t)gr[_REG32_nPC]; tf->tf_y = (uint64_t)gr[_REG32_Y]; tf->tf_global[1] = (uint64_t)gr[_REG32_G1]; tf->tf_global[2] = (uint64_t)gr[_REG32_G2]; tf->tf_global[3] = (uint64_t)gr[_REG32_G3]; tf->tf_global[4] = (uint64_t)gr[_REG32_G4]; tf->tf_global[5] = (uint64_t)gr[_REG32_G5]; tf->tf_global[6] = (uint64_t)gr[_REG32_G6]; /* done in lwp_setprivate */ /* tf->tf_global[7] = (uint64_t)gr[_REG32_G7]; */ tf->tf_out[0] = (uint64_t)gr[_REG32_O0]; tf->tf_out[1] = (uint64_t)gr[_REG32_O1]; tf->tf_out[2] = (uint64_t)gr[_REG32_O2]; tf->tf_out[3] = (uint64_t)gr[_REG32_O3]; tf->tf_out[4] = (uint64_t)gr[_REG32_O4]; tf->tf_out[5] = (uint64_t)gr[_REG32_O5]; tf->tf_out[6] = (uint64_t)gr[_REG32_O6]; tf->tf_out[7] = (uint64_t)gr[_REG32_O7]; /* %asi restored above; %fprs not yet supported. */ if (flags & _UC_TLSBASE) lwp_setprivate(l, (void *)(uintptr_t)gr[_REG32_G7]); /* XXX mcp->__gwins */ } /* Restore floating point register context, if any. */ if ((flags & _UC_FPU) != 0) { #ifdef notyet struct fpstate64 *fsp; const __fpregset_t *fpr = &mcp->__fpregs; /* * If we're the current FPU owner, simply reload it from * the supplied context. Otherwise, store it into the * process' FPU save area (which is used to restore from * by lazy FPU context switching); allocate it if necessary. */ if ((fsp = l->l_md.md_fpstate) == NULL) { fsp = pool_cache_get(fpstate_cache, PR_WAITOK); l->l_md.md_fpstate = fsp; } else { /* Drop the live context on the floor. */ fpusave_lwp(l, false); } /* Note: sizeof fpr->__fpu_fr <= sizeof fsp->fs_regs. */ memcpy(fsp->fs_regs, &fpr->__fpu_fr, sizeof (fpr->__fpu_fr)); fsp->fs_fsr = mcp->__fpregs.__fpu_fsr; fsp->fs_qsize = 0; #if 0 /* Need more info! */ mcp->__fpregs.__fpu_q = NULL; /* `Need more info.' */ mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */ #endif #endif } #ifdef _UC_SETSTACK 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); #endif return (0); }
static void netbsd32_sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) { int sig = ksi->ksi_signo; struct lwp *l = curlwp; struct proc *p = l->l_proc; struct sparc32_sigframe *fp; struct trapframe64 *tf; int addr, onstack, error; struct rwindow32 *oldsp, *newsp; register32_t sp; sig_t catcher = SIGACTION(p, sig).sa_handler; struct sparc32_sigframe sf; extern char netbsd32_sigcode[], netbsd32_esigcode[]; #define szsigcode (netbsd32_esigcode - netbsd32_sigcode) tf = l->l_md.md_tf; /* Need to attempt to zero extend this 32-bit pointer */ oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6]; /* Do we need to jump onto the signal stack? */ onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; if (onstack) { fp = (struct sparc32_sigframe *)((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size); l->l_sigstk.ss_flags |= SS_ONSTACK; } else fp = (struct sparc32_sigframe *)oldsp; fp = (struct sparc32_sigframe *)((u_long)(fp - 1) & ~7); #ifdef DEBUG sigpid = p->p_pid; if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { printf("sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n", p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp); if (sigdebug & SDB_DDB) Debugger(); } #endif /* * Now set up the signal frame. We build it in kernel space * and then copy it out. We probably ought to just build it * directly in user space.... */ sf.sf_signo = sig; sf.sf_code = (u_int)ksi->ksi_trap; #if defined(COMPAT_SUNOS) || defined(MODULAR) sf.sf_scp = (u_long)&fp->sf_sc; #endif sf.sf_addr = 0; /* XXX */ /* * Build the signal context to be used by sigreturn. */ sf.sf_sc.sc_onstack = onstack; sf.sf_sc.sc_mask = *mask; sf.sf_sc.sc_sp = (u_long)oldsp; sf.sf_sc.sc_pc = tf->tf_pc; sf.sf_sc.sc_npc = tf->tf_npc; sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */ sf.sf_sc.sc_g1 = tf->tf_global[1]; sf.sf_sc.sc_o0 = tf->tf_out[0]; /* * Put the stack in a consistent state before we whack away * at it. Note that write_user_windows may just dump the * registers into the pcb; we need them in the process's memory. * We also need to make sure that when we start the signal handler, * its %i6 (%fp), which is loaded from the newly allocated stack area, * joins seamlessly with the frame it was in when the signal occurred, * so that the debugger and _longjmp code can back up through it. */ sendsig_reset(l, sig); mutex_exit(p->p_lock); newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32)); write_user_windows(); #ifdef DEBUG if ((sigdebug & SDB_KSTACK)) printf("sendsig: saving sf to %p, setting stack pointer %p to %p\n", fp, &(((struct rwindow32 *)newsp)->rw_in[6]), oldsp); #endif sp = NETBSD32PTR32I(oldsp); error = (rwindow_save(l) || copyout(&sf, fp, sizeof sf) || copyout(&sp, &(((struct rwindow32 *)newsp)->rw_in[6]), sizeof(sp))); mutex_enter(p->p_lock); if (error) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ #ifdef DEBUG mutex_exit(p->p_lock); if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig: window save or copyout error\n"); printf("sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig); if (sigdebug & SDB_DDB) Debugger(); mutex_enter(p->p_lock); #endif sigexit(l, SIGILL); /* NOTREACHED */ } #ifdef DEBUG if (sigdebug & SDB_FOLLOW) { printf("sendsig: %s[%d] sig %d scp %p\n", p->p_comm, p->p_pid, sig, &fp->sf_sc); } #endif /* * Arrange to continue execution at the code copied out in exec(). * It needs the function to call in %g1, and a new stack pointer. */ addr = p->p_psstrp - szsigcode; tf->tf_global[1] = (long)catcher; tf->tf_pc = addr; tf->tf_npc = addr + 4; tf->tf_out[6] = (uint64_t)(u_int)(u_long)newsp; /* Remember that we're now on the signal stack. */ if (onstack) l->l_sigstk.ss_flags |= SS_ONSTACK; #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { mutex_exit(p->p_lock); printf("sendsig: about to return to catcher %p thru %p\n", catcher, addr); if (sigdebug & SDB_DDB) Debugger(); mutex_enter(p->p_lock); } #endif }
void sunos_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) { struct lwp *l = curlwp; struct proc *p = l->l_proc; struct sunos_sigframe *fp; struct trapframe *tf; int addr, onstack, oldsp, newsp, error; int sig = ksi->ksi_signo; u_long code = ksi->ksi_code; sig_t catcher = SIGACTION(p, sig).sa_handler; struct sunos_sigframe sf; tf = l->l_md.md_tf; oldsp = tf->tf_out[6]; /* * Compute new user stack addresses, subtract off * one signal frame, and align. */ onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; if (onstack) fp = (struct sunos_sigframe *) ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size); else fp = (struct sunos_sigframe *)oldsp; fp = (struct sunos_sigframe *)((int)(fp - 1) & ~7); #ifdef DEBUG if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid) printf("sendsig: %s[%d] sig %d newusp %p scp %p\n", p->p_comm, p->p_pid, sig, fp, &fp->sf_sc); #endif /* * Now set up the signal frame. We build it in kernel space * and then copy it out. We probably ought to just build it * directly in user space.... */ sf.sf_signo = sig; sf.sf_code = code; sf.sf_scp = &fp->sf_sc; sf.sf_addr = 0; /* XXX */ /* * Build the signal context to be used by sigreturn. */ sf.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; native_sigset_to_sigset13(mask, &sf.sf_sc.sc_mask); sf.sf_sc.sc_sp = oldsp; sf.sf_sc.sc_pc = tf->tf_pc; sf.sf_sc.sc_npc = tf->tf_npc; sf.sf_sc.sc_psr = tf->tf_psr; sf.sf_sc.sc_g1 = tf->tf_global[1]; sf.sf_sc.sc_o0 = tf->tf_out[0]; /* * Put the stack in a consistent state before we whack away * at it. Note that write_user_windows may just dump the * registers into the pcb; we need them in the process's memory. * We also need to make sure that when we start the signal handler, * its %i6 (%fp), which is loaded from the newly allocated stack area, * joins seamlessly with the frame it was in when the signal occurred, * so that the debugger and _longjmp code can back up through it. */ sendsig_reset(l, sig); mutex_exit(p->p_lock); newsp = (int)fp - sizeof(struct rwindow); write_user_windows(); error = (rwindow_save(l) || copyout((void *)&sf, (void *)fp, sizeof sf) || suword(&((struct rwindow *)newsp)->rw_in[6], oldsp)); mutex_enter(p->p_lock); if (error) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ #ifdef DEBUG if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid) printf("sendsig: window save or copyout error\n"); #endif sigexit(l, SIGILL); /* NOTREACHED */ } #ifdef DEBUG if (sunos_sigdebug & SDB_FOLLOW) printf("sendsig: %s[%d] sig %d scp %p\n", p->p_comm, p->p_pid, sig, &fp->sf_sc); #endif /* * Arrange to continue execution at the code copied out in exec(). * It needs the function to call in %g1, and a new stack pointer. */ addr = (int)catcher; /* user does his own trampolining */ tf->tf_pc = addr; tf->tf_npc = addr + 4; tf->tf_out[6] = newsp; /* Remember that we're now on the signal stack. */ if (onstack) l->l_sigstk.ss_flags |= SS_ONSTACK; #ifdef DEBUG if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid) printf("sendsig: about to return to catcher\n"); #endif }
/* * Send an interrupt to process. * * Stack is set up to allow sigcode stored * in u. to call routine. After the handler is * done svr4 will call setcontext for us * with the user context we just set up, and we * will return to the user pc, psl. */ void svr4_32_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) { int sig = ksi->ksi_signo; register struct lwp *l = curlwp; struct proc *p = l->l_proc; register struct trapframe64 *tf; struct svr4_32_sigframe *fp, frame; int onstack, error; vaddr_t oldsp, newsp, addr; sig_t catcher = SIGACTION(p, sig).sa_handler; sigset_t tmask; tf = (struct trapframe64 *)l->l_md.md_tf; oldsp = tf->tf_out[6]; /* Do we need to jump onto the signal stack? */ onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; /* * Allocate space for the signal handler context. */ if (onstack) fp = (struct svr4_32_sigframe *)((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size); else fp = (struct svr4_32_sigframe *)oldsp; fp = (struct svr4_32_sigframe *) ((long) (fp - 1) & ~7); #ifdef DEBUG sigpid = p->p_pid; if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { printf("svr4_32_sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n", p->p_comm, p->p_pid, sig, fp, &fp->sf_uc, (void *)(u_long)oldsp); #ifdef DDB if (sigdebug & SDB_DDB) Debugger(); #endif } #endif /* * Build the argument list for the signal handler. */ svr4_32_getsiginfo(&frame.sf_si, sig, ksi->ksi_trap, (void *)(u_long)tf->tf_pc); /* Build stack frame for signal trampoline. */ frame.sf_signum = frame.sf_si.si_signo; NETBSD32PTR32(frame.sf_sip, &fp->sf_si); NETBSD32PTR32(frame.sf_ucp, &fp->sf_uc); frame.sf_handler = catcher; DPRINTF(("svr4_32_sendsig signum=%d si = %p uc = %p handler = %p\n", frame.sf_signum, frame.sf_sip, frame.sf_ucp, frame.sf_handler)); /* * Modify the signal context to be used by sigreturn. */ tmask = *mask; sendsig_reset(l, sig); frame.sf_uc.uc_mcontext.greg[SVR4_SPARC_SP] = oldsp; newsp = (u_long)fp - sizeof(struct rwindow32); mutex_exit(p->p_lock); svr4_32_getcontext(l, &frame.sf_uc, &tmask); write_user_windows(); #ifdef DEBUG if ((sigdebug & SDB_KSTACK)) printf("svr4_32_sendsig: saving sf to %p, setting stack pointer %p to %p\n", fp, &(((struct rwindow32 *)newsp)->rw_in[6]), (void *)(u_long)oldsp); #endif error = (rwindow_save(l) || copyout(&frame, fp, sizeof(frame)) != 0 || copyout(&oldsp, &((struct rwindow32 *)newsp)->rw_in[6], sizeof(oldsp))); mutex_enter(p->p_lock); if (error) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ #ifdef DEBUG mutex_exit(p->p_lock); if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("svr4_32_sendsig: window save or copyout error\n"); printf("svr4_32_sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig); #ifdef DDB Debugger(); #endif mutex_enter(p->p_lock); #endif sigexit(l, SIGILL); /* NOTREACHED */ } #ifdef DEBUG if (sigdebug & SDB_FOLLOW) { printf("svr4_32_sendsig: %s[%d] sig %d scp %p\n", p->p_comm, p->p_pid, sig, &fp->sf_uc); } #endif /* * Build context to run handler in. */ addr = (vaddr_t)p->p_sigctx.ps_sigcode; tf->tf_pc = addr; tf->tf_npc = addr + 4; tf->tf_global[1] = (vaddr_t)catcher; tf->tf_out[6] = newsp; /* Remember that we're now on the signal stack. */ if (onstack) l->l_sigstk.ss_flags |= SS_ONSTACK; #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { mutex_exit(p->p_lock); printf("svr4_32_sendsig: about to return to catcher %p thru %p\n", catcher, (void *)(u_long)addr); #ifdef DDB if (sigdebug & SDB_DDB) Debugger(); #endif mutex_enter(p->p_lock); } #endif }
/* * Set to mcontext specified. * Return to previous pc and psl as specified by * context left by sendsig. Check carefully to * make sure that the user has not modified the * psl to gain improper privileges or to cause * a machine fault. * This is almost like sigreturn() and it shows. */ int svr4_32_setmcontext(struct lwp *l, struct svr4_32_mcontext *mc, netbsd32_u_long flags) { register struct trapframe64 *tf; svr4_32_greg_t *r = mc->greg; #ifdef FPU_CONTEXT svr4_32_fregset_t *f = &mc->freg; struct fpstate64 *fps = p->p_md.md_fpstate; #endif #ifdef DEBUG_SVR4 svr4_32_printmcontext("setmcontext", uc); #endif write_user_windows(); if (rwindow_save(l)) { #ifdef DEBUG printf("svr4_32_setcontext: rwindow_save(%p) failed, sending SIGILL\n", l); #ifdef DDB Debugger(); #endif #endif mutex_enter(l->l_proc->p_lock); sigexit(l, SIGILL); } #ifdef DEBUG if (sigdebug & SDB_FOLLOW) printf("svr4_32_setmcontext: %s[%d], svr4_32_mcontext %p\n", l->l_proc->p_comm, l->l_proc->p_pid, mc); #endif if (flags & SVR4_UC_CPU) { /* Restore register context. */ tf = (struct trapframe64 *)l->l_md.md_tf; /* * Only the icc bits in the psr are used, so it need not be * verified. pc and npc must be multiples of 4. This is all * that is required; if it holds, just do it. */ if (((r[SVR4_SPARC_PC] | r[SVR4_SPARC_nPC]) & 3) != 0) { printf("pc or npc are not multiples of 4!\n"); return EINVAL; } /* take only psr ICC field */ tf->tf_tstate = (tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(r[SVR4_SPARC_PSR]); tf->tf_pc = r[SVR4_SPARC_PC]; tf->tf_npc = r[SVR4_SPARC_nPC]; tf->tf_y = r[SVR4_SPARC_Y]; /* Restore everything */ tf->tf_global[1] = r[SVR4_SPARC_G1]; tf->tf_global[2] = r[SVR4_SPARC_G2]; tf->tf_global[3] = r[SVR4_SPARC_G3]; tf->tf_global[4] = r[SVR4_SPARC_G4]; tf->tf_global[5] = r[SVR4_SPARC_G5]; tf->tf_global[6] = r[SVR4_SPARC_G6]; tf->tf_global[7] = r[SVR4_SPARC_G7]; tf->tf_out[0] = r[SVR4_SPARC_O0]; tf->tf_out[1] = r[SVR4_SPARC_O1]; tf->tf_out[2] = r[SVR4_SPARC_O2]; tf->tf_out[3] = r[SVR4_SPARC_O3]; tf->tf_out[4] = r[SVR4_SPARC_O4]; tf->tf_out[5] = r[SVR4_SPARC_O5]; tf->tf_out[6] = r[SVR4_SPARC_O6]; tf->tf_out[7] = r[SVR4_SPARC_O7]; } #ifdef FPU_CONTEXT if (flags & SVR4_UC_FPU) { /* * Set the floating point registers */ int error; size_t sz = f->fp_nqel * f->fp_nqsize; if (sz > sizeof(fps->fs_queue)) { #ifdef DIAGNOSTIC printf("setmcontext: fp_queue too large\n"); #endif return EINVAL; } /* Note: touches only pre-v9 floating point registers. */ memcpy(fps->fs_regs, f->fpu_regs, sizeof(f->fpu_regs)); fps->fs_qsize = f->fp_nqel; fps->fs_fsr = f->fp_fsr; if (f->fp_q != 0) { if ((error = copyin((void *)(u_long)f->fp_q, fps->fs_queue, f->fp_nqel * f->fp_nqsize)) != 0) { #ifdef DIAGNOSTIC printf("setmcontext: fp_queue copy failed\n"); #endif return error; } } } #endif return 0; }
void * svr4_32_getmcontext(struct lwp *l, struct svr4_32_mcontext *mc, netbsd32_u_long *flags) { struct trapframe64 *tf = (struct trapframe64 *)l->l_md.md_tf; svr4_32_greg_t *r = mc->greg; #ifdef FPU_CONTEXT svr4_32_fregset_t *f = &mc->freg; struct fpstate *fps = l->l_md.md_fpstate; #endif write_user_windows(); if (rwindow_save(l)) { #ifdef DEBUG printf("svr4_32_getcontext: rwindow_save(%p) failed, sending SIGILL\n", l); #ifdef DDB Debugger(); #endif #endif mutex_enter(l->l_proc->p_lock); sigexit(l, SIGILL); } /* * Get the general purpose registers */ r[SVR4_SPARC_PSR] = TSTATECCR_TO_PSR(tf->tf_tstate); r[SVR4_SPARC_PC] = tf->tf_pc; r[SVR4_SPARC_nPC] = tf->tf_npc; r[SVR4_SPARC_Y] = tf->tf_y; r[SVR4_SPARC_G1] = tf->tf_global[1]; r[SVR4_SPARC_G2] = tf->tf_global[2]; r[SVR4_SPARC_G3] = tf->tf_global[3]; r[SVR4_SPARC_G4] = tf->tf_global[4]; r[SVR4_SPARC_G5] = tf->tf_global[5]; r[SVR4_SPARC_G6] = tf->tf_global[6]; r[SVR4_SPARC_G7] = tf->tf_global[7]; r[SVR4_SPARC_O0] = tf->tf_out[0]; r[SVR4_SPARC_O1] = tf->tf_out[1]; r[SVR4_SPARC_O2] = tf->tf_out[2]; r[SVR4_SPARC_O3] = tf->tf_out[3]; r[SVR4_SPARC_O4] = tf->tf_out[4]; r[SVR4_SPARC_O5] = tf->tf_out[5]; r[SVR4_SPARC_O6] = tf->tf_out[6]; r[SVR4_SPARC_O7] = tf->tf_out[7]; *flags |= SVR4_UC_CPU; #ifdef FPU_CONTEXT /* * Get the floating point registers */ /* Note: copies only pre-v9 floating point registers. */ memcpy(f->fpu_regs, fps->fs_regs, sizeof(f->fpu_regs)); f->fp_nqsize = sizeof(struct fp_qentry); f->fp_nqel = fps->fs_qsize; f->fp_fsr = fps->fs_fsr; if (f->fp_q != NULL) { size_t sz = f->fp_nqel * f->fp_nqsize; if (sz > sizeof(fps->fs_queue)) { #ifdef DIAGNOSTIC printf("getcontext: fp_queue too large\n"); #endif return; } if (copyout(fps->fs_queue, (void *)(u_long)f->fp_q, sz) != 0) { #ifdef DIAGNOSTIC printf("getcontext: copy of fp_queue failed %d\n", error); #endif return; } } f->fp_busy = 0; /* XXX: How do we determine that? */ *flags |= SVR4_UC_FPU; #endif #ifdef DEBUG_SVR4 svr4_32_printmcontext("getmcontext", mc); #endif return (void *)(u_long)tf->tf_out[6]; }
void sunos32_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) { int sig = ksi->ksi_signo; struct lwp *l = curlwp; /* XXX */ struct proc *p = l->l_proc; struct sunos32_sigframe *fp; struct trapframe64 *tf; struct rwindow32 *oldsp, *newsp; struct sunos32_sigframe sf; struct sunos32_sigcontext *scp; uint32_t addr, oldsp32; int onstack, error; sig_t catcher = SIGACTION(p, sig).sa_handler; tf = l->l_md.md_tf; /* Need to attempt to zero extend this 32-bit pointer */ oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6]; oldsp32 = (uint32_t)(u_long)oldsp; /* * Compute new user stack addresses, subtract off * one signal frame, and align. */ onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; if (onstack) fp = (struct sunos32_sigframe *) ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size); else fp = (struct sunos32_sigframe *)oldsp; fp = (struct sunos32_sigframe *)((u_long)(fp - 1) & ~7); #ifdef DEBUG sigpid = p->p_pid; if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { mutex_exit(p->p_lock); printf("sunos32_sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n", p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp); #ifdef DDB if (sigdebug & SDB_DDB) Debugger(); #endif mutex_enter(p->p_lock); } #endif /* * Now set up the signal frame. We build it in kernel space * and then copy it out. We probably ought to just build it * directly in user space.... */ sf.sf_signo = sig; sf.sf_code = (uint32_t)ksi->ksi_trap; scp = &fp->sf_sc; if ((u_long)scp >= 0x100000000) printf("sunos32_sendsig: sf_scp overflow %p > 0x100000000\n", scp); sf.sf_scp = (uint32_t)(u_long)scp; sf.sf_addr = 0; /* XXX */ /* * Build the signal context to be used by sigreturn. */ sf.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; native_sigset_to_sigset13(mask, &sf.sf_sc.sc_mask); sf.sf_sc.sc_sp = (u_int)(u_long)oldsp; sf.sf_sc.sc_pc = tf->tf_pc; sf.sf_sc.sc_npc = tf->tf_npc; sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */ sf.sf_sc.sc_g1 = tf->tf_global[1]; sf.sf_sc.sc_o0 = tf->tf_out[0]; /* * Put the stack in a consistent state before we whack away * at it. Note that write_user_windows may just dump the * registers into the pcb; we need them in the process's memory. * We also need to make sure that when we start the signal handler, * its %i6 (%fp), which is loaded from the newly allocated stack area, * joins seamlessly with the frame it was in when the signal occurred, * so that the debugger and _longjmp code can back up through it. */ sendsig_reset(l, sig); mutex_exit(p->p_lock); newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32)); write_user_windows(); #ifdef DEBUG if ((sigdebug & SDB_KSTACK)) printf("sunos32_sendsig: saving sf to %p, setting stack pointer %p to %p\n", fp, &(((struct rwindow32 *)newsp)->rw_in[6]), oldsp); #endif error = (rwindow_save(l) || copyout((void *)&sf, (void *)fp, sizeof sf) || copyout((void *)&oldsp32, &(((struct rwindow32 *)newsp)->rw_in[6]), sizeof oldsp32)); mutex_enter(p->p_lock); if (error) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ #ifdef DEBUG mutex_exit(p->p_lock); if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sunos32_sendsig: window save or copyout error\n"); printf("sunos32_sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig); #ifdef DDB if (sigdebug & SDB_DDB) Debugger(); #endif mutex_enter(p->p_lock); #endif sigexit(l, SIGILL); /* NOTREACHED */ } #ifdef DEBUG if ((sigdebug & SDB_FOLLOW)) { printf("sunos32_sendsig: %s[%d] sig %d scp %p\n", p->p_comm, p->p_pid, sig, &fp->sf_sc); } #endif /* * Arrange to continue execution at the code copied out in exec(). * It needs the function to call in %g1, and a new stack pointer. */ addr = (uint32_t)(u_long)catcher; /* user does his own trampolining */ tf->tf_pc = addr; tf->tf_npc = addr + 4; tf->tf_out[6] = (uint64_t)(u_int)(u_long)newsp; #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { mutex_exit(p->p_lock); printf("sunos32_sendsig: about to return to catcher %p thru %p\n", catcher, (void *)(u_long)addr); #ifdef DDB if (sigdebug & SDB_DDB) Debugger(); #endif mutex_enter(p->p_lock); } #endif }