sig_machdep.c revision 1.12
11.12Slukem/* $NetBSD: sig_machdep.c,v 1.12 2003/07/15 02:54:48 lukem Exp $ */ 21.1Skleink 31.1Skleink/* 41.1Skleink * Copyright (C) 1995, 1996 Wolfgang Solfrank. 51.1Skleink * Copyright (C) 1995, 1996 TooLs GmbH. 61.1Skleink * All rights reserved. 71.1Skleink * 81.1Skleink * Redistribution and use in source and binary forms, with or without 91.1Skleink * modification, are permitted provided that the following conditions 101.1Skleink * are met: 111.1Skleink * 1. Redistributions of source code must retain the above copyright 121.1Skleink * notice, this list of conditions and the following disclaimer. 131.1Skleink * 2. Redistributions in binary form must reproduce the above copyright 141.1Skleink * notice, this list of conditions and the following disclaimer in the 151.1Skleink * documentation and/or other materials provided with the distribution. 161.1Skleink * 3. All advertising materials mentioning features or use of this software 171.1Skleink * must display the following acknowledgement: 181.1Skleink * This product includes software developed by TooLs GmbH. 191.1Skleink * 4. The name of TooLs GmbH may not be used to endorse or promote products 201.1Skleink * derived from this software without specific prior written permission. 211.1Skleink * 221.1Skleink * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 231.1Skleink * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 241.1Skleink * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 251.1Skleink * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 261.1Skleink * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 271.1Skleink * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 281.1Skleink * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 291.1Skleink * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 301.1Skleink * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 311.1Skleink * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 321.1Skleink */ 331.12Slukem 341.12Slukem#include <sys/cdefs.h> 351.12Slukem__KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.12 2003/07/15 02:54:48 lukem Exp $"); 361.2Stsubai 371.2Stsubai#include "opt_compat_netbsd.h" 381.8Sthorpej#include "opt_ppcarch.h" 391.1Skleink 401.1Skleink#include <sys/param.h> 411.1Skleink#include <sys/mount.h> 421.1Skleink#include <sys/proc.h> 431.8Sthorpej#include <sys/sa.h> 441.8Sthorpej#include <sys/savar.h> 451.1Skleink#include <sys/syscallargs.h> 461.1Skleink#include <sys/systm.h> 471.8Sthorpej#include <sys/ucontext.h> 481.1Skleink#include <sys/user.h> 491.1Skleink 501.8Sthorpej#include <machine/fpu.h> 511.8Sthorpej 521.1Skleink/* 531.1Skleink * Send a signal to process. 541.1Skleink */ 551.1Skleinkvoid 561.7Sthorpejsendsig(sig, mask, code) 571.1Skleink int sig; 581.1Skleink sigset_t *mask; 591.1Skleink u_long code; 601.1Skleink{ 611.8Sthorpej struct lwp *l = curlwp; 621.8Sthorpej struct proc *p = l->l_proc; 631.7Sthorpej struct sigacts *ps = p->p_sigacts; 641.11Smatt struct sigframe *fp, frame; 651.1Skleink struct trapframe *tf; 661.11Smatt struct utrapframe *utf = &frame.sf_sc.sc_frame; 671.1Skleink int onstack; 681.7Sthorpej sig_t catcher = SIGACTION(p, sig).sa_handler; 691.1Skleink 701.8Sthorpej tf = trapframe(l); 711.1Skleink 721.1Skleink /* Do we need to jump onto the signal stack? */ 731.1Skleink onstack = 741.4Sjdolecek (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 751.4Sjdolecek (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 761.1Skleink 771.1Skleink /* Allocate space for the signal handler context. */ 781.1Skleink if (onstack) 791.4Sjdolecek fp = (struct sigframe *)((caddr_t)p->p_sigctx.ps_sigstk.ss_sp + 801.4Sjdolecek p->p_sigctx.ps_sigstk.ss_size); 811.1Skleink else 821.1Skleink fp = (struct sigframe *)tf->fixreg[1]; 831.9Smatt fp = (struct sigframe *)((uintptr_t)(fp - 1) & ~0xf); 841.1Skleink 851.1Skleink /* Save register context. */ 861.11Smatt memcpy(utf->fixreg, tf->fixreg, sizeof(utf->fixreg)); 871.11Smatt utf->lr = tf->lr; 881.11Smatt utf->cr = tf->cr; 891.11Smatt utf->xer = tf->xer; 901.11Smatt utf->ctr = tf->ctr; 911.11Smatt utf->srr0 = tf->srr0; 921.11Smatt utf->srr1 = tf->srr1; 931.11Smatt#ifdef PPC_OEA 941.11Smatt utf->vrsave = tf->tf_xtra[TF_VRSAVE]; 951.11Smatt utf->mq = tf->tf_xtra[TF_MQ]; 961.11Smatt#endif 971.1Skleink 981.1Skleink /* Save signal stack. */ 991.4Sjdolecek frame.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK; 1001.1Skleink 1011.1Skleink /* Save signal mask. */ 1021.1Skleink frame.sf_sc.sc_mask = *mask; 1031.1Skleink 1041.1Skleink#ifdef COMPAT_13 1051.1Skleink /* 1061.1Skleink * XXX We always have to save an old style signal mask because 1071.1Skleink * XXX we might be delivering a signal to a process which will 1081.1Skleink * XXX escape from the signal in a non-standard way and invoke 1091.1Skleink * XXX sigreturn() directly. 1101.1Skleink */ 1111.1Skleink native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13); 1121.1Skleink#endif 1131.1Skleink 1141.1Skleink if (copyout(&frame, fp, sizeof frame) != 0) { 1151.1Skleink /* 1161.1Skleink * Process has trashed its stack; give it an illegal 1171.1Skleink * instructoin to halt it in its tracks. 1181.1Skleink */ 1191.8Sthorpej sigexit(l, SIGILL); 1201.1Skleink /* NOTREACHED */ 1211.1Skleink } 1221.1Skleink 1231.1Skleink /* 1241.7Sthorpej * Build context to run handler in. Note the trampoline version 1251.7Sthorpej * numbers are coordinated with machine-dependent code in libc. 1261.1Skleink */ 1271.7Sthorpej switch (ps->sa_sigdesc[sig].sd_vers) { 1281.7Sthorpej#if 1 /* COMPAT_16 */ 1291.7Sthorpej case 0: /* legacy on-stack sigtramp */ 1301.9Smatt tf->fixreg[1] = (register_t)fp; 1311.9Smatt tf->lr = (register_t)catcher; 1321.9Smatt tf->fixreg[3] = (register_t)sig; 1331.9Smatt tf->fixreg[4] = (register_t)code; 1341.9Smatt tf->fixreg[5] = (register_t)&fp->sf_sc; 1351.9Smatt tf->srr0 = (register_t)p->p_sigctx.ps_sigcode; 1361.7Sthorpej break; 1371.7Sthorpej#endif /* COMPAT_16 */ 1381.7Sthorpej 1391.7Sthorpej case 1: 1401.9Smatt tf->fixreg[1] = (register_t)fp; 1411.9Smatt tf->lr = (register_t)catcher; 1421.9Smatt tf->fixreg[3] = (register_t)sig; 1431.9Smatt tf->fixreg[4] = (register_t)code; 1441.9Smatt tf->fixreg[5] = (register_t)&fp->sf_sc; 1451.9Smatt tf->srr0 = (register_t)ps->sa_sigdesc[sig].sd_tramp; 1461.7Sthorpej break; 1471.7Sthorpej 1481.7Sthorpej default: 1491.7Sthorpej /* Don't know what trampoline version; kill it. */ 1501.8Sthorpej sigexit(l, SIGILL); 1511.7Sthorpej } 1521.1Skleink 1531.1Skleink /* Remember that we're now on the signal stack. */ 1541.1Skleink if (onstack) 1551.4Sjdolecek p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 1561.1Skleink} 1571.1Skleink 1581.1Skleink/* 1591.1Skleink * System call to cleanup state after a signal handler returns. 1601.1Skleink */ 1611.1Skleinkint 1621.8Sthorpejsys___sigreturn14(l, v, retval) 1631.8Sthorpej struct lwp *l; 1641.1Skleink void *v; 1651.1Skleink register_t *retval; 1661.1Skleink{ 1671.1Skleink struct sys___sigreturn14_args /* { 1681.1Skleink syscallarg(struct sigcontext *) sigcntxp; 1691.1Skleink } */ *uap = v; 1701.8Sthorpej struct proc *p = l->l_proc; 1711.1Skleink struct sigcontext sc; 1721.1Skleink struct trapframe *tf; 1731.11Smatt struct utrapframe * const utf = &sc.sc_frame; 1741.1Skleink int error; 1751.1Skleink 1761.1Skleink /* 1771.1Skleink * The trampoline hands us the context. 1781.1Skleink * It is unsafe to keep track of it ourselves, in the event that a 1791.1Skleink * program jumps out of a signal hander. 1801.1Skleink */ 1811.1Skleink if ((error = copyin(SCARG(uap, sigcntxp), &sc, sizeof sc)) != 0) 1821.1Skleink return (error); 1831.1Skleink 1841.1Skleink /* Restore the register context. */ 1851.8Sthorpej tf = trapframe(l); 1861.1Skleink if ((sc.sc_frame.srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) 1871.1Skleink return (EINVAL); 1881.11Smatt 1891.11Smatt /* Restore register context. */ 1901.11Smatt memcpy(tf->fixreg, utf->fixreg, sizeof(tf->fixreg)); 1911.11Smatt tf->lr = utf->lr; 1921.11Smatt tf->cr = utf->cr; 1931.11Smatt tf->xer = utf->xer; 1941.11Smatt tf->ctr = utf->ctr; 1951.11Smatt tf->srr0 = utf->srr0; 1961.11Smatt tf->srr1 = utf->srr1; 1971.11Smatt#ifdef PPC_OEA 1981.11Smatt tf->tf_xtra[TF_VRSAVE] = utf->vrsave; 1991.11Smatt tf->tf_xtra[TF_MQ] = utf->mq; 2001.11Smatt#endif 2011.1Skleink 2021.1Skleink /* Restore signal stack. */ 2031.1Skleink if (sc.sc_onstack & SS_ONSTACK) 2041.4Sjdolecek p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 2051.1Skleink else 2061.4Sjdolecek p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; 2071.1Skleink 2081.1Skleink /* Restore signal mask. */ 2091.1Skleink (void) sigprocmask1(p, SIG_SETMASK, &sc.sc_mask, 0); 2101.1Skleink 2111.1Skleink return (EJUSTRETURN); 2121.8Sthorpej} 2131.8Sthorpej 2141.8Sthorpejvoid 2151.8Sthorpejcpu_getmcontext(l, mcp, flagp) 2161.8Sthorpej struct lwp *l; 2171.8Sthorpej mcontext_t *mcp; 2181.8Sthorpej unsigned int *flagp; 2191.8Sthorpej{ 2201.8Sthorpej const struct trapframe *tf = trapframe(l); 2211.10Smatt __greg_t *gr = mcp->__gregs; 2221.8Sthorpej#ifdef PPC_HAVE_FPU 2231.8Sthorpej struct pcb *pcb = &l->l_addr->u_pcb; 2241.8Sthorpej#endif 2251.8Sthorpej 2261.8Sthorpej /* Save GPR context. */ 2271.10Smatt (void)memcpy(gr, &tf->fixreg, 32 * sizeof (gr[0])); /* GR0-31 */ 2281.10Smatt gr[_REG_CR] = tf->cr; 2291.10Smatt gr[_REG_LR] = tf->lr; 2301.10Smatt gr[_REG_PC] = tf->srr0; 2311.10Smatt gr[_REG_MSR] = tf->srr1; 2321.10Smatt gr[_REG_CTR] = tf->ctr; 2331.10Smatt gr[_REG_XER] = tf->xer; 2341.11Smatt#ifdef PPC_OEA 2351.11Smatt gr[_REG_MQ] = tf->tf_xtra[TF_MQ]; 2361.11Smatt#else 2371.11Smatt gr[_REG_MQ] = 0; 2381.11Smatt#endif 2391.8Sthorpej *flagp |= _UC_CPU; 2401.8Sthorpej 2411.8Sthorpej#ifdef PPC_HAVE_FPU 2421.8Sthorpej /* Save FPR context, if any. */ 2431.8Sthorpej if ((pcb->pcb_flags & PCB_FPU) != 0) { 2441.8Sthorpej /* If we're the FPU owner, dump its context to the PCB first. */ 2451.8Sthorpej if (pcb->pcb_fpcpu) 2461.8Sthorpej save_fpu_lwp(l); 2471.8Sthorpej (void)memcpy(mcp->__fpregs.__fpu_regs, pcb->pcb_fpu.fpr, 2481.8Sthorpej sizeof (mcp->__fpregs.__fpu_regs)); 2491.8Sthorpej mcp->__fpregs.__fpu_fpscr = 2501.8Sthorpej ((int *)&pcb->pcb_fpu.fpscr)[_QUAD_LOWWORD]; 2511.8Sthorpej mcp->__fpregs.__fpu_valid = 1; 2521.8Sthorpej *flagp |= _UC_FPU; 2531.8Sthorpej } else 2541.8Sthorpej#endif 2551.8Sthorpej mcp->__fpregs.__fpu_valid = 0; 2561.8Sthorpej 2571.8Sthorpej /* No AltiVec support, for now. */ 2581.8Sthorpej memset(&mcp->__vrf, 0, sizeof (mcp->__vrf)); 2591.8Sthorpej} 2601.8Sthorpej 2611.8Sthorpejint 2621.8Sthorpejcpu_setmcontext(l, mcp, flags) 2631.8Sthorpej struct lwp *l; 2641.8Sthorpej const mcontext_t *mcp; 2651.8Sthorpej unsigned int flags; 2661.8Sthorpej{ 2671.8Sthorpej struct trapframe *tf = trapframe(l); 2681.10Smatt __greg_t *gr = mcp->__gregs; 2691.8Sthorpej#ifdef PPC_HAVE_FPU 2701.8Sthorpej struct pcb *pcb = &l->l_addr->u_pcb; 2711.8Sthorpej#endif 2721.8Sthorpej 2731.8Sthorpej /* Restore GPR context, if any. */ 2741.8Sthorpej if (flags & _UC_CPU) { 2751.10Smatt if ((gr[_REG_MSR] & PSL_USERSTATIC) != 2761.8Sthorpej (tf->srr1 & PSL_USERSTATIC)) 2771.8Sthorpej return (EINVAL); 2781.8Sthorpej 2791.10Smatt (void)memcpy(&tf->fixreg, gr, 32 * sizeof (gr[0])); 2801.10Smatt tf->cr = gr[_REG_CR]; 2811.10Smatt tf->lr = gr[_REG_LR]; 2821.10Smatt tf->srr0 = gr[_REG_PC]; 2831.10Smatt tf->srr1 = gr[_REG_MSR]; 2841.10Smatt tf->ctr = gr[_REG_CTR]; 2851.10Smatt tf->xer = gr[_REG_XER]; 2861.11Smatt#ifdef PPC_OEA 2871.11Smatt tf->tf_xtra[TF_MQ] = gr[_REG_MQ]; 2881.11Smatt#endif 2891.8Sthorpej } 2901.8Sthorpej 2911.8Sthorpej#ifdef PPC_HAVE_FPU 2921.8Sthorpej /* Restore FPR context, if any. */ 2931.8Sthorpej if ((flags & _UC_FPU) && mcp->__fpregs.__fpu_valid != 0) { 2941.8Sthorpej /* XXX we don't need to save the state, just to drop it */ 2951.8Sthorpej save_fpu_lwp(l); 2961.8Sthorpej (void)memcpy(&pcb->pcb_fpu.fpr, &mcp->__fpregs.__fpu_regs, 2971.8Sthorpej sizeof (pcb->pcb_fpu.fpr)); 2981.8Sthorpej pcb->pcb_fpu.fpscr = *(double *)&mcp->__fpregs.__fpu_fpscr; 2991.8Sthorpej } 3001.8Sthorpej#endif 3011.8Sthorpej 3021.8Sthorpej return (0); 3031.1Skleink} 304