void setup_linux_rt_sigframe(struct trapframe *tf, const ksiginfo_t *ksi, const sigset_t *mask) { struct lwp *l = curlwp; struct proc *p = l->l_proc; struct linux_rt_sigframe *sfp, sigframe; int onstack, error; int fsize, rndfsize; int sig = ksi->ksi_signo; extern char linux_rt_sigcode[], linux_rt_esigcode[]; /* 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. */ fsize = sizeof(struct linux_rt_sigframe); rndfsize = ((fsize + 15) / 16) * 16; if (onstack) sfp = (struct linux_rt_sigframe *) ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size); else sfp = (struct linux_rt_sigframe *)(alpha_pal_rdusp()); sfp = (struct linux_rt_sigframe *)((char *)sfp - rndfsize); #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && (p->p_pid == sigpid)) printf("linux_sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid, sig, &onstack, sfp); #endif /* DEBUG */ /* * Build the signal context to be used by sigreturn. */ memset(&sigframe.uc, 0, sizeof(struct linux_ucontext)); sigframe.uc.uc_mcontext.sc_onstack = onstack; /* Setup potentially partial signal mask in sc_mask. */ /* But get all of it in uc_sigmask */ native_to_linux_old_sigset(&sigframe.uc.uc_mcontext.sc_mask, mask); native_to_linux_sigset(&sigframe.uc.uc_sigmask, mask); sigframe.uc.uc_mcontext.sc_pc = tf->tf_regs[FRAME_PC]; sigframe.uc.uc_mcontext.sc_ps = ALPHA_PSL_USERMODE; frametoreg(tf, (struct reg *)sigframe.uc.uc_mcontext.sc_regs); sigframe.uc.uc_mcontext.sc_regs[R_SP] = alpha_pal_rdusp(); fpu_load(); alpha_pal_wrfen(1); sigframe.uc.uc_mcontext.sc_fpcr = alpha_read_fpcr(); sigframe.uc.uc_mcontext.sc_fp_control = alpha_read_fp_c(l); alpha_pal_wrfen(0); sigframe.uc.uc_mcontext.sc_traparg_a0 = tf->tf_regs[FRAME_A0]; sigframe.uc.uc_mcontext.sc_traparg_a1 = tf->tf_regs[FRAME_A1]; sigframe.uc.uc_mcontext.sc_traparg_a2 = tf->tf_regs[FRAME_A2]; native_to_linux_siginfo(&sigframe.info, &ksi->ksi_info); sendsig_reset(l, sig); mutex_exit(p->p_lock); error = copyout((void *)&sigframe, (void *)sfp, fsize); mutex_enter(p->p_lock); if (error != 0) { #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig(%d): copyout failed on sig %d\n", p->p_pid, sig); #endif /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ sigexit(l, SIGILL); /* NOTREACHED */ } /* Pass pointers to siginfo and ucontext in the regs */ tf->tf_regs[FRAME_A1] = (unsigned long)&sfp->info; tf->tf_regs[FRAME_A2] = (unsigned long)&sfp->uc; /* Address of trampoline code. End up at this PC after mi_switch */ tf->tf_regs[FRAME_PC] = (u_int64_t)(p->p_psstrp - (linux_rt_esigcode - linux_rt_sigcode)); /* Adjust the stack */ alpha_pal_wrusp((unsigned long)sfp); /* Remember that we're now on the signal stack. */ if (onstack) l->l_sigstk.ss_flags |= SS_ONSTACK; }
void sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) { struct lwp *l = curlwp; struct proc *p = l->l_proc; struct sigacts *ps = p->p_sigacts; int onstack, sig = ksi->ksi_signo; struct sigframe_sigcontext *fp, frame; struct trapframe *tf; sig_t catcher = SIGACTION(p, sig).sa_handler; tf = l->l_md.md_tf; fp = getframe(l, sig, &onstack), frame; fp--; #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig_sigcontext(%d): sig %d ssp %p usp %p\n", p->p_pid, sig, &onstack, fp); #endif /* Build stack frame for signal trampoline. */ frame.sf_sc.sc_pc = tf->tf_regs[FRAME_PC]; frame.sf_sc.sc_ps = tf->tf_regs[FRAME_PS]; /* Save register context. */ frametoreg(tf, (struct reg *)frame.sf_sc.sc_regs); frame.sf_sc.sc_regs[R_ZERO] = 0xACEDBADE; /* magic number */ frame.sf_sc.sc_regs[R_SP] = alpha_pal_rdusp(); /* save the floating-point state, if necessary, then copy it. */ if (l->l_addr->u_pcb.pcb_fpcpu != NULL) fpusave_proc(l, 1); frame.sf_sc.sc_ownedfp = l->l_md.md_flags & MDP_FPUSED; memcpy((struct fpreg *)frame.sf_sc.sc_fpregs, &l->l_addr->u_pcb.pcb_fp, sizeof(struct fpreg)); frame.sf_sc.sc_fp_control = alpha_read_fp_c(l); memset(frame.sf_sc.sc_reserved, 0, sizeof frame.sf_sc.sc_reserved); memset(frame.sf_sc.sc_xxx, 0, sizeof frame.sf_sc.sc_xxx); /* XXX */ /* Save signal stack. */ frame.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK; /* Save signal mask. */ frame.sf_sc.sc_mask = *mask; #ifdef COMPAT_13 /* * XXX We always have to save an old style signal mask because * XXX we might be delivering a signal to a process which will * XXX escape from the signal in a non-standard way and invoke * XXX sigreturn() directly. */ { /* Note: it's a long in the stack frame. */ sigset13_t mask13; native_sigset_to_sigset13(mask, &mask13); frame.sf_sc.__sc_mask13 = mask13; } #endif #ifdef COMPAT_OSF1 /* * XXX Create an OSF/1-style sigcontext and associated goo. */ #endif if (copyout(&frame, (caddr_t)fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ #ifdef DEBUG if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig_sigcontext(%d): copyout failed on sig %d\n", p->p_pid, sig); #endif sigexit(l, SIGILL); /* NOTREACHED */ } #ifdef DEBUG if (sigdebug & SDB_FOLLOW) printf("sendsig_sigcontext(%d): sig %d usp %p code %x\n", p->p_pid, sig, fp, ksi->ksi_code); #endif /* * Set up the registers to directly invoke the signal handler. The * signal trampoline is then used to return from the signal. Note * the trampoline version numbers are coordinated with machine- * dependent code in libc. */ switch (ps->sa_sigdesc[sig].sd_vers) { case 0: /* legacy on-stack sigtramp */ buildcontext(l,(void *)catcher, (void *)p->p_sigctx.ps_sigcode, (void *)fp); break; case 1: buildcontext(l,(void *)catcher, (void *)ps->sa_sigdesc[sig].sd_tramp, (void *)fp); break; default: /* Don't know what trampoline version; kill it. */ sigexit(l, SIGILL); } /* sigcontext specific trap frame */ tf->tf_regs[FRAME_A0] = sig; /* tf->tf_regs[FRAME_A1] = ksi->ksi_code; */ tf->tf_regs[FRAME_A1] = KSI_TRAPCODE(ksi); tf->tf_regs[FRAME_A2] = (u_int64_t)&fp->sf_sc; /* Remember that we're now on the signal stack. */ if (onstack) p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; #ifdef DEBUG if (sigdebug & SDB_FOLLOW) printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid, tf->tf_regs[FRAME_PC], tf->tf_regs[FRAME_A3]); if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) printf("sendsig(%d): sig %d returns\n", p->p_pid, sig); #endif }