sig_machdep.c revision 1.13
11.13Smatt/* $NetBSD: sig_machdep.c,v 1.13 2003/09/25 18:42:18 matt 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.13Smatt__KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.13 2003/09/25 18:42:18 matt 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.13Smattsendsig(ksiginfo_t *ksi, sigset_t *mask) 571.1Skleink{ 581.13Smatt struct lwp * const l = curlwp; 591.13Smatt struct proc * const p = l->l_proc; 601.13Smatt struct trapframe * const tf = trapframe(l); 611.13Smatt struct sigaltstack *ss = &p->p_sigctx.ps_sigstk; 621.13Smatt const struct sigact_sigdesc *sd = 631.13Smatt &p->p_sigacts->sa_sigdesc[ksi->ksi_signo]; 641.13Smatt ucontext_t uc; 651.13Smatt vaddr_t sp, sip, ucp; 661.1Skleink int onstack; 671.1Skleink 681.13Smatt#ifdef COMPAT_16 691.13Smatt if (sd->sd_vers < 2) { 701.13Smatt sendsig_sigcontext(ksi->ksi_signo, mask, ksi->ksi_trap); 711.13Smatt return; 721.13Smatt } 731.13Smatt#endif 741.1Skleink 751.1Skleink /* Do we need to jump onto the signal stack? */ 761.13Smatt onstack = (ss->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 771.13Smatt (sd->sd_sigact.sa_flags & SA_ONSTACK) != 0; 781.1Skleink 791.13Smatt /* Find top of stack. */ 801.13Smatt sp = (onstack ? (vaddr_t)ss->ss_sp + ss->ss_size : tf->fixreg[1]); 811.13Smatt sp &= ~(CALLFRAMELEN-1); 821.13Smatt 831.13Smatt /* Allocate space for the ucontext. */ 841.13Smatt sp -= sizeof(ucontext_t); 851.13Smatt ucp = sp; 861.13Smatt 871.13Smatt /* Allocate space for the siginfo. */ 881.13Smatt sp -= sizeof(siginfo_t); 891.13Smatt sip = sp; 901.13Smatt 911.13Smatt sp &= ~(CALLFRAMELEN-1); 921.1Skleink 931.1Skleink /* Save register context. */ 941.13Smatt uc.uc_flags = _UC_SIGMASK; 951.13Smatt uc.uc_sigmask = *mask; 961.13Smatt uc.uc_link = NULL; 971.13Smatt memset(&uc.uc_stack, 0, sizeof(uc.uc_stack)); 981.13Smatt cpu_getmcontext(l, &uc.uc_mcontext, &uc.uc_flags); 991.1Skleink 1001.1Skleink /* 1011.13Smatt * Copy the siginfo and ucontext onto the user's stack. 1021.1Skleink */ 1031.13Smatt if (copyout(ksi, (caddr_t)sip, sizeof(ksi)) != 0 || 1041.13Smatt copyout(&uc, (caddr_t)ucp, sizeof(uc)) != 0) { 1051.1Skleink /* 1061.1Skleink * Process has trashed its stack; give it an illegal 1071.1Skleink * instructoin to halt it in its tracks. 1081.1Skleink */ 1091.8Sthorpej sigexit(l, SIGILL); 1101.1Skleink /* NOTREACHED */ 1111.1Skleink } 1121.1Skleink 1131.1Skleink /* 1141.7Sthorpej * Build context to run handler in. Note the trampoline version 1151.7Sthorpej * numbers are coordinated with machine-dependent code in libc. 1161.1Skleink */ 1171.13Smatt switch (sd->sd_vers) { 1181.13Smatt case 2: /* siginfo sigtramp */ 1191.13Smatt tf->fixreg[1] = (register_t)sp; 1201.13Smatt tf->lr = (register_t)sd->sd_sigact.sa_handler; 1211.13Smatt tf->fixreg[3] = (register_t)ksi->_signo; 1221.13Smatt tf->fixreg[4] = (register_t)sip; 1231.13Smatt tf->fixreg[5] = (register_t)ucp; 1241.13Smatt tf->srr0 = (register_t)sd->sd_tramp; 1251.7Sthorpej break; 1261.7Sthorpej 1271.7Sthorpej default: 1281.7Sthorpej /* Don't know what trampoline version; kill it. */ 1291.13Smatt printf("sendsig_siginfo(sig %d): bad version %d\n", 1301.13Smatt ksi->_signo, sd->sd_vers); 1311.8Sthorpej sigexit(l, SIGILL); 1321.7Sthorpej } 1331.1Skleink 1341.1Skleink /* Remember that we're now on the signal stack. */ 1351.1Skleink if (onstack) 1361.13Smatt ss->ss_flags |= SS_ONSTACK; 1371.8Sthorpej} 1381.8Sthorpej 1391.8Sthorpejvoid 1401.13Smattcpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flagp) 1411.8Sthorpej{ 1421.8Sthorpej const struct trapframe *tf = trapframe(l); 1431.10Smatt __greg_t *gr = mcp->__gregs; 1441.8Sthorpej#ifdef PPC_HAVE_FPU 1451.8Sthorpej struct pcb *pcb = &l->l_addr->u_pcb; 1461.8Sthorpej#endif 1471.8Sthorpej 1481.8Sthorpej /* Save GPR context. */ 1491.10Smatt (void)memcpy(gr, &tf->fixreg, 32 * sizeof (gr[0])); /* GR0-31 */ 1501.10Smatt gr[_REG_CR] = tf->cr; 1511.10Smatt gr[_REG_LR] = tf->lr; 1521.10Smatt gr[_REG_PC] = tf->srr0; 1531.10Smatt gr[_REG_MSR] = tf->srr1; 1541.10Smatt gr[_REG_CTR] = tf->ctr; 1551.10Smatt gr[_REG_XER] = tf->xer; 1561.11Smatt#ifdef PPC_OEA 1571.11Smatt gr[_REG_MQ] = tf->tf_xtra[TF_MQ]; 1581.11Smatt#else 1591.11Smatt gr[_REG_MQ] = 0; 1601.11Smatt#endif 1611.8Sthorpej *flagp |= _UC_CPU; 1621.8Sthorpej 1631.8Sthorpej#ifdef PPC_HAVE_FPU 1641.8Sthorpej /* Save FPR context, if any. */ 1651.8Sthorpej if ((pcb->pcb_flags & PCB_FPU) != 0) { 1661.8Sthorpej /* If we're the FPU owner, dump its context to the PCB first. */ 1671.8Sthorpej if (pcb->pcb_fpcpu) 1681.8Sthorpej save_fpu_lwp(l); 1691.8Sthorpej (void)memcpy(mcp->__fpregs.__fpu_regs, pcb->pcb_fpu.fpr, 1701.8Sthorpej sizeof (mcp->__fpregs.__fpu_regs)); 1711.8Sthorpej mcp->__fpregs.__fpu_fpscr = 1721.8Sthorpej ((int *)&pcb->pcb_fpu.fpscr)[_QUAD_LOWWORD]; 1731.8Sthorpej mcp->__fpregs.__fpu_valid = 1; 1741.8Sthorpej *flagp |= _UC_FPU; 1751.8Sthorpej } else 1761.8Sthorpej#endif 1771.13Smatt memset(&mcp->__fpregs, 0, sizeof(mcp->__fpregs)); 1781.8Sthorpej 1791.8Sthorpej /* No AltiVec support, for now. */ 1801.8Sthorpej memset(&mcp->__vrf, 0, sizeof (mcp->__vrf)); 1811.8Sthorpej} 1821.8Sthorpej 1831.8Sthorpejint 1841.13Smattcpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) 1851.8Sthorpej{ 1861.8Sthorpej struct trapframe *tf = trapframe(l); 1871.10Smatt __greg_t *gr = mcp->__gregs; 1881.8Sthorpej#ifdef PPC_HAVE_FPU 1891.8Sthorpej struct pcb *pcb = &l->l_addr->u_pcb; 1901.8Sthorpej#endif 1911.8Sthorpej 1921.8Sthorpej /* Restore GPR context, if any. */ 1931.8Sthorpej if (flags & _UC_CPU) { 1941.10Smatt if ((gr[_REG_MSR] & PSL_USERSTATIC) != 1951.8Sthorpej (tf->srr1 & PSL_USERSTATIC)) 1961.8Sthorpej return (EINVAL); 1971.8Sthorpej 1981.10Smatt (void)memcpy(&tf->fixreg, gr, 32 * sizeof (gr[0])); 1991.10Smatt tf->cr = gr[_REG_CR]; 2001.10Smatt tf->lr = gr[_REG_LR]; 2011.10Smatt tf->srr0 = gr[_REG_PC]; 2021.10Smatt tf->srr1 = gr[_REG_MSR]; 2031.10Smatt tf->ctr = gr[_REG_CTR]; 2041.10Smatt tf->xer = gr[_REG_XER]; 2051.11Smatt#ifdef PPC_OEA 2061.11Smatt tf->tf_xtra[TF_MQ] = gr[_REG_MQ]; 2071.11Smatt#endif 2081.8Sthorpej } 2091.8Sthorpej 2101.8Sthorpej#ifdef PPC_HAVE_FPU 2111.8Sthorpej /* Restore FPR context, if any. */ 2121.8Sthorpej if ((flags & _UC_FPU) && mcp->__fpregs.__fpu_valid != 0) { 2131.8Sthorpej /* XXX we don't need to save the state, just to drop it */ 2141.8Sthorpej save_fpu_lwp(l); 2151.8Sthorpej (void)memcpy(&pcb->pcb_fpu.fpr, &mcp->__fpregs.__fpu_regs, 2161.8Sthorpej sizeof (pcb->pcb_fpu.fpr)); 2171.8Sthorpej pcb->pcb_fpu.fpscr = *(double *)&mcp->__fpregs.__fpu_fpscr; 2181.8Sthorpej } 2191.8Sthorpej#endif 2201.8Sthorpej 2211.8Sthorpej return (0); 2221.1Skleink} 223