/* * Send an interrupt to process. */ void sendsig(sig_t catcher, int sig, int mask, unsigned long code, int type, union sigval val) { struct proc *p = curproc; struct trapframe *tf; struct sigacts *psp = p->p_sigacts; struct sigframe *fp; int oonstack, fsize; struct sigframe sf; vaddr_t addr; tf = p->p_md.md_tf; oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; /* * Allocate and validate space for the signal handler * context. Note that if the stack is in data space, the * call to grow() is a nop, and the copyout() * will fail if the process has not already allocated * the space with a `brk'. */ fsize = sizeof(struct sigframe); if ((psp->ps_flags & SAS_ALTSTACK) && (psp->ps_sigstk.ss_flags & SS_ONSTACK) == 0 && (psp->ps_sigonstack & sigmask(sig))) { fp = (struct sigframe *)(psp->ps_sigstk.ss_sp + psp->ps_sigstk.ss_size - fsize); psp->ps_sigstk.ss_flags |= SS_ONSTACK; } else fp = (struct sigframe *)(tf->tf_r[31] - fsize); /* make sure the frame is aligned on a 8 byte boundary */ if (((vaddr_t)fp & 0x07) != 0) fp = (struct sigframe *)((vaddr_t)fp & ~0x07); if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize)) (void)uvm_grow(p, (unsigned)fp); #ifdef DEBUG if ((sigdebug & SDB_FOLLOW) || ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n", p->p_pid, sig, &oonstack, fp, &fp->sf_sc); #endif /* * Build the signal context to be used by sigreturn. */ sf.sf_scp = &fp->sf_sc; sf.sf_sc.sc_onstack = oonstack; sf.sf_sc.sc_mask = mask; if (psp->ps_siginfo & sigmask(sig)) { initsiginfo(&sf.sf_si, sig, code, type, val); } /* * Copy the whole user context into signal context that we * are building. */ bcopy((const void *)&tf->tf_regs, (void *)&sf.sf_sc.sc_regs, sizeof(sf.sf_sc.sc_regs)); if (copyout((caddr_t)&sf, (caddr_t)fp, sizeof sf)) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ sigexit(p, SIGILL); /* NOTREACHED */ } /* * Set up registers for the signal handler invocation. */ tf->tf_r[1] = p->p_sigcode; /* return to sigcode */ tf->tf_r[2] = sig; /* first arg is signo */ tf->tf_r[3] = (vaddr_t)&fp->sf_si; /* second arg is siginfo */ addr = (vaddr_t)catcher; /* and resume in the handler */ #ifdef M88100 if (CPU_IS88100) { tf->tf_snip = (addr & NIP_ADDR) | NIP_V; tf->tf_sfip = (tf->tf_snip + 4) | FIP_V; } #endif #ifdef M88110 if (CPU_IS88110) { tf->tf_exip = (addr & XIP_ADDR); } #endif tf->tf_r[31] = (vaddr_t)fp; #ifdef DEBUG if ((sigdebug & SDB_FOLLOW) || ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) printf("sendsig(%d): sig %d returns\n", p->p_pid, sig); #endif }
/* * Send an interrupt to process. */ void sendsig(sig_t catcher, int sig, int mask, u_long code, int type, union sigval val) { struct proc *p = curproc; struct sigframe *fp, frame; struct trapframe *tf = p->p_md.md_regs; struct sigacts *psp = p->p_sigacts; siginfo_t *sip; int onstack; onstack = p->p_sigstk.ss_flags & SS_ONSTACK; if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && onstack == 0 && (psp->ps_sigonstack & sigmask(sig))) { fp = (struct sigframe *)((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size); p->p_sigstk.ss_flags |= SS_ONSTACK; } else fp = (void *)p->p_md.md_regs->tf_r15; --fp; bzero(&frame, sizeof(frame)); if (psp->ps_siginfo & sigmask(sig)) { initsiginfo(&frame.sf_si, sig, code, type, val); sip = &fp->sf_si; } else sip = NULL; /* Save register context. */ frame.sf_uc.sc_reg.r_spc = tf->tf_spc; frame.sf_uc.sc_reg.r_ssr = tf->tf_ssr; frame.sf_uc.sc_reg.r_pr = tf->tf_pr; frame.sf_uc.sc_reg.r_mach = tf->tf_mach; frame.sf_uc.sc_reg.r_macl = tf->tf_macl; frame.sf_uc.sc_reg.r_r15 = tf->tf_r15; frame.sf_uc.sc_reg.r_r14 = tf->tf_r14; frame.sf_uc.sc_reg.r_r13 = tf->tf_r13; frame.sf_uc.sc_reg.r_r12 = tf->tf_r12; frame.sf_uc.sc_reg.r_r11 = tf->tf_r11; frame.sf_uc.sc_reg.r_r10 = tf->tf_r10; frame.sf_uc.sc_reg.r_r9 = tf->tf_r9; frame.sf_uc.sc_reg.r_r8 = tf->tf_r8; frame.sf_uc.sc_reg.r_r7 = tf->tf_r7; frame.sf_uc.sc_reg.r_r6 = tf->tf_r6; frame.sf_uc.sc_reg.r_r5 = tf->tf_r5; frame.sf_uc.sc_reg.r_r4 = tf->tf_r4; frame.sf_uc.sc_reg.r_r3 = tf->tf_r3; frame.sf_uc.sc_reg.r_r2 = tf->tf_r2; frame.sf_uc.sc_reg.r_r1 = tf->tf_r1; frame.sf_uc.sc_reg.r_r0 = tf->tf_r0; #ifdef SH4 if (CPU_IS_SH4) fpu_save(&frame.sf_uc.sc_fpreg); #endif frame.sf_uc.sc_onstack = onstack; frame.sf_uc.sc_expevt = tf->tf_expevt; /* frame.sf_uc.sc_err = 0; */ frame.sf_uc.sc_mask = mask; if (copyout(&frame, fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ sigexit(p, SIGILL); /* NOTREACHED */ } tf->tf_r4 = sig; /* "signum" argument for handler */ tf->tf_r5 = (int)sip; /* "sip" argument for handler */ tf->tf_r6 = (int)&fp->sf_uc; /* "ucp" argument for handler */ tf->tf_spc = (int)catcher; tf->tf_r15 = (int)fp; tf->tf_pr = (int)p->p_sigcode; }
/* * Send an interrupt to process. * * Stack is set up to allow sigcode stored * in u. to call routine, followed by kcall * to sigreturn routine below. After sigreturn * resets the signal mask, the stack, and the * frame pointer, it returns to the user * specified pc, psl. */ void sendsig(sig_t catcher, int sig, int mask, u_long code, int type, union sigval val) { struct proc *p = curproc; struct trapframe *tf = p->p_md.md_regs; struct sigacts * psp = p->p_sigacts; struct sigcontext ksc; siginfo_t ksi; register_t sp, scp, sip; u_long sss; #ifdef DEBUG if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) printf("sendsig: %s[%d] sig %d catcher %p\n", p->p_comm, p->p_pid, sig, catcher); #endif bcopy(tf, &ksc, sizeof(*tf)); ksc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; ksc.sc_mask = mask; ksc.sc_fpstate = NULL; /* Allocate space for the signal handler context. */ if ((psp->ps_flags & SAS_ALTSTACK) && !ksc.sc_onstack && (psp->ps_sigonstack & sigmask(sig))) { sp = (register_t)psp->ps_sigstk.ss_sp + psp->ps_sigstk.ss_size; psp->ps_sigstk.ss_flags |= SS_ONSTACK; } else sp = tf->tf_rsp - 128; sp &= ~15ULL; /* just in case */ sss = (sizeof(ksc) + 15) & ~15; if (p->p_md.md_flags & MDP_USEDFPU) { fpusave_proc(p, 1); sp -= sizeof(struct fxsave64); ksc.sc_fpstate = (struct fxsave64 *)sp; if (copyout(&p->p_addr->u_pcb.pcb_savefpu.fp_fxsave, (void *)sp, sizeof(struct fxsave64))) sigexit(p, SIGILL); } sip = 0; if (psp->ps_siginfo & sigmask(sig)) { sip = sp - ((sizeof(ksi) + 15) & ~15); sss += (sizeof(ksi) + 15) & ~15; initsiginfo(&ksi, sig, code, type, val); if (copyout(&ksi, (void *)sip, sizeof(ksi))) sigexit(p, SIGILL); } scp = sp - sss; if (copyout(&ksc, (void *)scp, sizeof(ksc))) sigexit(p, SIGILL); /* * Build context to run handler in. */ tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL); tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL); tf->tf_fs = LSEL(LUDATA_SEL, SEL_UPL); tf->tf_gs = LSEL(LUDATA_SEL, SEL_UPL); tf->tf_rax = (u_int64_t)catcher; tf->tf_rdi = sig; tf->tf_rsi = sip; tf->tf_rdx = scp; tf->tf_rip = (u_int64_t)p->p_sigcode; tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL); tf->tf_rflags &= ~(PSL_T|PSL_VM|PSL_AC); tf->tf_rsp = scp; tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL); #ifdef DEBUG if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) printf("sendsig(%d): pc 0x%x, catcher 0x%x\n", p->p_pid, tf->tf_rip, tf->tf_rax); #endif }
/* * Send an interrupt to process. * * Stack is set up to allow sigcode stored * in u. to call routine, followed by kcall * to sigreturn routine below. After sigreturn * resets the signal mask, the stack, and the * frame pointer, it returns to the user specified pc. */ void sendsig(sig_t catcher, int sig, int returnmask, u_long code, int type, union sigval val) { struct proc *p = curproc; struct trapframe *tf; struct sigframe *fp, frame; struct sigacts *psp = p->p_sigacts; int oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; int onstack = 0; tf = process_frame(p); /* Do we need to jump onto the signal stack? */ /* Allocate space for the signal handler context. */ if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack && (psp->ps_sigonstack & sigmask(sig))) { onstack = 1; fp = (struct sigframe *)((caddr_t)psp->ps_sigstk.ss_sp + psp->ps_sigstk.ss_size); } else fp = (struct sigframe *)tf->tf_usr_sp; /* make room on the stack */ fp--; /* make the stack aligned */ fp = (void *)STACKALIGN(fp); /* Build stack frame for signal trampoline. */ frame.sf_signum = sig; frame.sf_sip = NULL; frame.sf_scp = &fp->sf_sc; frame.sf_handler = catcher; /* Save register context. */ frame.sf_sc.sc_r0 = tf->tf_r0; frame.sf_sc.sc_r1 = tf->tf_r1; frame.sf_sc.sc_r2 = tf->tf_r2; frame.sf_sc.sc_r3 = tf->tf_r3; frame.sf_sc.sc_r4 = tf->tf_r4; frame.sf_sc.sc_r5 = tf->tf_r5; frame.sf_sc.sc_r6 = tf->tf_r6; frame.sf_sc.sc_r7 = tf->tf_r7; frame.sf_sc.sc_r8 = tf->tf_r8; frame.sf_sc.sc_r9 = tf->tf_r9; frame.sf_sc.sc_r10 = tf->tf_r10; frame.sf_sc.sc_r11 = tf->tf_r11; frame.sf_sc.sc_r12 = tf->tf_r12; frame.sf_sc.sc_usr_sp = tf->tf_usr_sp; frame.sf_sc.sc_usr_lr = tf->tf_usr_lr; frame.sf_sc.sc_svc_lr = tf->tf_svc_lr; frame.sf_sc.sc_pc = tf->tf_pc; frame.sf_sc.sc_spsr = tf->tf_spsr; /* Save signal stack. */ frame.sf_sc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; /* Save signal mask. */ frame.sf_sc.sc_mask = returnmask; if (psp->ps_siginfo & sigmask(sig)) { frame.sf_sip = &fp->sf_si; initsiginfo(&frame.sf_si, sig, code, type, val); } if (copyout(&frame, fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ sigexit(p, SIGILL); /* NOTREACHED */ } /* * Build context to run handler in. We invoke the handler * directly, only returning via the trampoline. Note the * trampoline version numbers are coordinated with machine- * dependent code in libc. */ /* * this was all in the switch below, seemed daft to duplicate it, if * we do a new trampoline version it might change then */ tf->tf_r0 = sig; tf->tf_r1 = (int)frame.sf_sip; tf->tf_r2 = (int)frame.sf_scp; tf->tf_pc = (int)frame.sf_handler; tf->tf_usr_sp = (int)fp; tf->tf_usr_lr = (int)p->p_sigcode; /* XXX This should not be needed. */ cpu_icache_sync_all(); /* Remember that we're now on the signal stack. */ if (onstack) psp->ps_sigstk.ss_flags |= SS_ONSTACK; }