FreeBSD/sys/amd64/amd64/machdep.c
/*
 * Send an interrupt to process.
 *
 * Stack is set up to allow sigcode stored
 * at top to call routine, followed by call
 * to sigreturn routine below.  After sigreturn
 * resets the signal mask, the stack, and the
 * frame pointer, it returns to the user
 * specified pc, psl.
 */
Send an interrupt to process.
Stack is set up to allow sigcode stored
at top to call routine, followed by call
to sigreturn routine below.  After sigreturn
resets the signal mask, the stack, and the
frame pointer, it returns to the user
specified pc, psl.
Send an interrupt to process . Stack is set up to allow sigcode stored at top to call routine followed by call 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, ksiginfo_t *ksi, sigset_t *mask)
{
	struct sigframe sf, *sfp;
	struct pcb *pcb;
	struct proc *p;
	struct thread *td;
	struct sigacts *psp;
	char *sp;
	struct trapframe *regs;
	char *xfpusave;
	size_t xfpusave_len;
	int sig;
	int oonstack;
	td = curthread;
	pcb = td->td_pcb;
	p = td->td_proc;
	PROC_LOCK_ASSERT(p, MA_OWNED);
	sig = ksi->ksi_signo;
	psp = p->p_sigacts;
	mtx_assert(&psp->ps_mtx, MA_OWNED);
	regs = td->td_frame;
	oonstack = sigonstack(regs->tf_rsp);
	if (cpu_max_ext_state_size > sizeof(struct savefpu) && use_xsave) {
		xfpusave_len = cpu_max_ext_state_size - sizeof(struct savefpu);
		xfpusave = __builtin_alloca(xfpusave_len);
	} else {
		xfpusave_len = 0;
		xfpusave = NULL;
	}
	bzero(&sf, sizeof(sf));
	sf.sf_uc.uc_sigmask = *mask;
	sf.sf_uc.uc_stack = td->td_sigstk;
	sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
	    ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
	sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
	bcopy(regs, &sf.sf_uc.uc_mcontext.mc_rdi, sizeof(*regs));
	sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); 
	get_fpcontext(td, &sf.sf_uc.uc_mcontext, xfpusave, xfpusave_len);
	fpstate_drop(td);
	sf.sf_uc.uc_mcontext.mc_fsbase = pcb->pcb_fsbase;
	sf.sf_uc.uc_mcontext.mc_gsbase = pcb->pcb_gsbase;
	bzero(sf.sf_uc.uc_mcontext.mc_spare,
	    sizeof(sf.sf_uc.uc_mcontext.mc_spare));
	bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__));
	if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
		sp = (char *)td->td_sigstk.ss_sp + td->td_sigstk.ss_size;
#if defined(COMPAT_43)
		td->td_sigstk.ss_flags |= SS_ONSTACK;
#endif
	} else
		sp = (char *)regs->tf_rsp - 128;
	if (xfpusave != NULL) {
		sp -= xfpusave_len;
		sp = (char *)((unsigned long)sp & ~0x3Ful);
		sf.sf_uc.uc_mcontext.mc_xfpustate = (register_t)sp;
	}
	sp -= sizeof(struct sigframe);
	sfp = (struct sigframe *)((unsigned long)sp & ~0xFul);
	regs->tf_rdi = sig;			
	regs->tf_rdx = (register_t)&sfp->sf_uc;	
	bzero(&sf.sf_si, sizeof(sf.sf_si));
	if (SIGISMEMBER(psp->ps_siginfo, sig)) {
		regs->tf_rsi = (register_t)&sfp->sf_si;	
		sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
		sf.sf_si = ksi->ksi_info;
		sf.sf_si.si_signo = sig; 
		regs->tf_rcx = (register_t)ksi->ksi_addr; 
	} else {
		regs->tf_rsi = ksi->ksi_code;	
		regs->tf_rcx = (register_t)ksi->ksi_addr; 
		sf.sf_ahu.sf_handler = catcher;
	}
	mtx_unlock(&psp->ps_mtx);
	PROC_UNLOCK(p);
	if (copyout(&sf, sfp, sizeof(*sfp)) != 0 ||
	    (xfpusave != NULL && copyout(xfpusave,
	    (void *)sf.sf_uc.uc_mcontext.mc_xfpustate, xfpusave_len)
	    != 0)) {
#ifdef DEBUG
		printf("process %ld has trashed its stack\n", (long)p->p_pid);
#endif
		PROC_LOCK(p);
		sigexit(td, SIGILL);
	}
	regs->tf_rsp = (long)sfp;
	regs->tf_rip = p->p_sysent->sv_sigcode_base;
	regs->tf_rflags &= ~(PSL_T | PSL_D);
	regs->tf_cs = _ucodesel;
	regs->tf_ds = _udatasel;
	regs->tf_ss = _udatasel;
	regs->tf_es = _udatasel;
	regs->tf_fs = _ufssel;
	regs->tf_gs = _ugssel;
	regs->tf_flags = TF_HASSEGS;
	set_pcb_flags(pcb, PCB_FULL_IRET);
	PROC_LOCK(p);
	mtx_lock(&psp->ps_mtx);
}
void sendsig ( sig_t catcher , ksiginfo_t * ksi , sigset_t * mask ) { struct sigframe sf , * sfp ; struct pcb * pcb ; struct proc * p ; struct thread * td ; struct sigacts * psp ; char * sp ; struct trapframe * regs ; char * xfpusave ; size_t xfpusave_len ; int sig ; int oonstack ; td = curthread ; pcb = td -> td_pcb ; p = td -> td_proc ; PROC_LOCK_ASSERT ( p , MA_OWNED ) ; sig = ksi -> ksi_signo ; psp = p -> p_sigacts ; mtx_assert ( & psp -> ps_mtx , MA_OWNED ) ; regs = td -> td_frame ; oonstack = sigonstack ( regs -> tf_rsp ) ; if ( cpu_max_ext_state_size > sizeof ( struct savefpu ) && use_xsave ) { xfpusave_len = cpu_max_ext_state_size - sizeof ( struct savefpu ) ; xfpusave = __builtin_alloca ( xfpusave_len ) ; } else { xfpusave_len = 0 ; xfpusave = NULL ; } bzero ( & sf , sizeof ( sf ) ) ; sf . sf_uc . uc_sigmask = * mask ; sf . sf_uc . uc_stack = td -> td_sigstk ; sf . sf_uc . uc_stack . ss_flags = ( td -> td_pflags & TDP_ALTSTACK ) ? ( ( oonstack ) ? SS_ONSTACK : 0 ) : SS_DISABLE ; sf . sf_uc . uc_mcontext . mc_onstack = ( oonstack ) ? 1 : 0 ; bcopy ( regs , & sf . sf_uc . uc_mcontext . mc_rdi , sizeof ( * regs ) ) ; sf . sf_uc . uc_mcontext . mc_len = sizeof ( sf . sf_uc . uc_mcontext ) ; get_fpcontext ( td , & sf . sf_uc . uc_mcontext , xfpusave , xfpusave_len ) ; fpstate_drop ( td ) ; sf . sf_uc . uc_mcontext . mc_fsbase = pcb -> pcb_fsbase ; sf . sf_uc . uc_mcontext . mc_gsbase = pcb -> pcb_gsbase ; bzero ( sf . sf_uc . uc_mcontext . mc_spare , sizeof ( sf . sf_uc . uc_mcontext . mc_spare ) ) ; bzero ( sf . sf_uc . __spare__ , sizeof ( sf . sf_uc . __spare__ ) ) ; if ( ( td -> td_pflags & TDP_ALTSTACK ) != 0 && ! oonstack && SIGISMEMBER ( psp -> ps_sigonstack , sig ) ) { sp = ( char * ) td -> td_sigstk . ss_sp + td -> td_sigstk . ss_size ; #if defined ( COMPAT_43 ) td -> td_sigstk . ss_flags |= SS_ONSTACK ; #endif } else sp = ( char * ) regs -> tf_rsp - 128 ; if ( xfpusave != NULL ) { sp -= xfpusave_len ; sp = ( char * ) ( ( unsigned long ) sp & ~ 0x3Ful ) ; sf . sf_uc . uc_mcontext . mc_xfpustate = ( register_t ) sp ; } sp -= sizeof ( struct sigframe ) ; sfp = ( struct sigframe * ) ( ( unsigned long ) sp & ~ 0xFul ) ; regs -> tf_rdi = sig ; regs -> tf_rdx = ( register_t ) & sfp -> sf_uc ; bzero ( & sf . sf_si , sizeof ( sf . sf_si ) ) ; if ( SIGISMEMBER ( psp -> ps_siginfo , sig ) ) { regs -> tf_rsi = ( register_t ) & sfp -> sf_si ; sf . sf_ahu . sf_action = ( __siginfohandler_t * ) catcher ; sf . sf_si = ksi -> ksi_info ; sf . sf_si . si_signo = sig ; regs -> tf_rcx = ( register_t ) ksi -> ksi_addr ; } else { regs -> tf_rsi = ksi -> ksi_code ; regs -> tf_rcx = ( register_t ) ksi -> ksi_addr ; sf . sf_ahu . sf_handler = catcher ; } mtx_unlock ( & psp -> ps_mtx ) ; PROC_UNLOCK ( p ) ; if ( copyout ( & sf , sfp , sizeof ( * sfp ) ) != 0 || ( xfpusave != NULL && copyout ( xfpusave , ( void * ) sf . sf_uc . uc_mcontext . mc_xfpustate , xfpusave_len ) != 0 ) ) { #ifdef DEBUG printf ( " \n " , ( long ) p -> p_pid ) ; #endif PROC_LOCK ( p ) ; sigexit ( td , SIGILL ) ; } regs -> tf_rsp = ( long ) sfp ; regs -> tf_rip = p -> p_sysent -> sv_sigcode_base ; regs -> tf_rflags &= ~ ( PSL_T | PSL_D ) ; regs -> tf_cs = _ucodesel ; regs -> tf_ds = _udatasel ; regs -> tf_ss = _udatasel ; regs -> tf_es = _udatasel ; regs -> tf_fs = _ufssel ; regs -> tf_gs = _ugssel ; regs -> tf_flags = TF_HASSEGS ; set_pcb_flags ( pcb , PCB_FULL_IRET ) ; PROC_LOCK ( p ) ; mtx_lock ( & psp -> ps_mtx ) ; }
Send an interrupt to process.
Send an interrupt to process .
/* Save user context. */ /* magic */ /* Allocate space for the signal handler context. */ /* Align to 16 bytes. */ /* Build the argument list for the signal handler. */ /* arg 1 in %rdi */ /* arg 3 in %rdx */ /* Signal handler installed with SA_SIGINFO. */ /* arg 2 in %rsi */ /* Fill in POSIX parts */ /* maybe a translated signal */ /* arg 4 in %rcx */ /* Old FreeBSD-style arguments. */ /* arg 2 in %rsi */ /* arg 4 in %rcx */ /*
	 * Copy the sigframe out to the user's stack.
	 */