sig_machdep.c revision 1.34
11.34She/* $NetBSD: sig_machdep.c,v 1.34 2008/11/21 20:22:30 he 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.34She__KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.34 2008/11/21 20:22:30 he Exp $"); 361.2Stsubai 371.8Sthorpej#include "opt_ppcarch.h" 381.22Smatt#include "opt_altivec.h" 391.1Skleink 401.1Skleink#include <sys/param.h> 411.1Skleink#include <sys/mount.h> 421.1Skleink#include <sys/proc.h> 431.1Skleink#include <sys/syscallargs.h> 441.1Skleink#include <sys/systm.h> 451.8Sthorpej#include <sys/ucontext.h> 461.1Skleink#include <sys/user.h> 471.1Skleink 481.22Smatt#include <powerpc/fpu.h> 491.22Smatt#include <powerpc/altivec.h> 501.8Sthorpej 511.1Skleink/* 521.1Skleink * Send a signal to process. 531.1Skleink */ 541.1Skleinkvoid 551.34Shesendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) 561.1Skleink{ 571.13Smatt struct lwp * const l = curlwp; 581.13Smatt struct proc * const p = l->l_proc; 591.13Smatt struct trapframe * const tf = trapframe(l); 601.27Sad struct sigaltstack *ss = &l->l_sigstk; 611.13Smatt const struct sigact_sigdesc *sd = 621.13Smatt &p->p_sigacts->sa_sigdesc[ksi->ksi_signo]; 631.13Smatt ucontext_t uc; 641.13Smatt vaddr_t sp, sip, ucp; 651.27Sad int onstack, error; 661.1Skleink 671.1Skleink /* Do we need to jump onto the signal stack? */ 681.13Smatt onstack = (ss->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 691.13Smatt (sd->sd_sigact.sa_flags & SA_ONSTACK) != 0; 701.1Skleink 711.13Smatt /* Find top of stack. */ 721.13Smatt sp = (onstack ? (vaddr_t)ss->ss_sp + ss->ss_size : tf->fixreg[1]); 731.13Smatt sp &= ~(CALLFRAMELEN-1); 741.13Smatt 751.13Smatt /* Allocate space for the ucontext. */ 761.13Smatt sp -= sizeof(ucontext_t); 771.13Smatt ucp = sp; 781.13Smatt 791.13Smatt /* Allocate space for the siginfo. */ 801.13Smatt sp -= sizeof(siginfo_t); 811.13Smatt sip = sp; 821.13Smatt 831.13Smatt sp &= ~(CALLFRAMELEN-1); 841.1Skleink 851.1Skleink /* Save register context. */ 861.13Smatt uc.uc_flags = _UC_SIGMASK; 871.13Smatt uc.uc_sigmask = *mask; 881.30Spooka uc.uc_link = l->l_ctxlink; 891.13Smatt memset(&uc.uc_stack, 0, sizeof(uc.uc_stack)); 901.27Sad sendsig_reset(l, ksi->ksi_signo); 911.32Sad mutex_exit(p->p_lock); 921.13Smatt cpu_getmcontext(l, &uc.uc_mcontext, &uc.uc_flags); 931.1Skleink 941.1Skleink /* 951.13Smatt * Copy the siginfo and ucontext onto the user's stack. 961.1Skleink */ 971.29Schristos error = (copyout(&ksi->ksi_info, (void *)sip, sizeof(ksi->ksi_info)) != 0 || 981.29Schristos copyout(&uc, (void *)ucp, sizeof(uc)) != 0); 991.32Sad mutex_enter(p->p_lock); 1001.27Sad 1011.27Sad if (error) { 1021.1Skleink /* 1031.1Skleink * Process has trashed its stack; give it an illegal 1041.14Smatt * instruction to halt it in its tracks. 1051.1Skleink */ 1061.8Sthorpej sigexit(l, SIGILL); 1071.1Skleink /* NOTREACHED */ 1081.1Skleink } 1091.1Skleink 1101.1Skleink /* 1111.7Sthorpej * Build context to run handler in. Note the trampoline version 1121.7Sthorpej * numbers are coordinated with machine-dependent code in libc. 1131.1Skleink */ 1141.13Smatt switch (sd->sd_vers) { 1151.13Smatt case 2: /* siginfo sigtramp */ 1161.14Smatt tf->fixreg[1] = (register_t)sp - CALLFRAMELEN; 1171.17Smatt tf->fixreg[3] = (register_t)ksi->ksi_signo; 1181.14Smatt tf->fixreg[4] = (register_t)sip; 1191.14Smatt tf->fixreg[5] = (register_t)ucp; 1201.14Smatt /* Preserve ucp across call to signal function */ 1211.14Smatt tf->fixreg[30] = (register_t)ucp; 1221.14Smatt tf->lr = (register_t)sd->sd_tramp; 1231.14Smatt tf->srr0 = (register_t)sd->sd_sigact.sa_handler; 1241.7Sthorpej break; 1251.7Sthorpej 1261.7Sthorpej default: 1271.14Smatt goto nosupport; 1281.7Sthorpej } 1291.1Skleink 1301.1Skleink /* Remember that we're now on the signal stack. */ 1311.1Skleink if (onstack) 1321.13Smatt ss->ss_flags |= SS_ONSTACK; 1331.14Smatt return; 1341.14Smatt 1351.14Smatt nosupport: 1361.14Smatt /* Don't know what trampoline version; kill it. */ 1371.14Smatt printf("sendsig_siginfo(sig %d): bad version %d\n", 1381.17Smatt ksi->ksi_signo, sd->sd_vers); 1391.14Smatt sigexit(l, SIGILL); 1401.14Smatt /* NOTREACHED */ 1411.8Sthorpej} 1421.8Sthorpej 1431.8Sthorpejvoid 1441.13Smattcpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flagp) 1451.8Sthorpej{ 1461.8Sthorpej const struct trapframe *tf = trapframe(l); 1471.10Smatt __greg_t *gr = mcp->__gregs; 1481.22Smatt#if defined(PPC_HAVE_FPU) || defined(ALTIVEC) 1491.8Sthorpej struct pcb *pcb = &l->l_addr->u_pcb; 1501.8Sthorpej#endif 1511.8Sthorpej 1521.8Sthorpej /* Save GPR context. */ 1531.10Smatt (void)memcpy(gr, &tf->fixreg, 32 * sizeof (gr[0])); /* GR0-31 */ 1541.10Smatt gr[_REG_CR] = tf->cr; 1551.10Smatt gr[_REG_LR] = tf->lr; 1561.10Smatt gr[_REG_PC] = tf->srr0; 1571.22Smatt gr[_REG_MSR] = tf->srr1 & PSL_USERSRR1; 1581.21Smatt#ifdef PPC_HAVE_FPU 1591.21Smatt gr[_REG_MSR] |= pcb->pcb_flags & (PCB_FE0|PCB_FE1); 1601.21Smatt#endif 1611.22Smatt#ifdef ALTIVEC 1621.22Smatt gr[_REG_MSR] |= pcb->pcb_flags & PCB_ALTIVEC ? PSL_VEC : 0; 1631.22Smatt#endif 1641.10Smatt gr[_REG_CTR] = tf->ctr; 1651.10Smatt gr[_REG_XER] = tf->xer; 1661.11Smatt#ifdef PPC_OEA 1671.11Smatt gr[_REG_MQ] = tf->tf_xtra[TF_MQ]; 1681.11Smatt#else 1691.11Smatt gr[_REG_MQ] = 0; 1701.11Smatt#endif 1711.8Sthorpej *flagp |= _UC_CPU; 1721.8Sthorpej 1731.8Sthorpej#ifdef PPC_HAVE_FPU 1741.8Sthorpej /* Save FPR context, if any. */ 1751.8Sthorpej if ((pcb->pcb_flags & PCB_FPU) != 0) { 1761.8Sthorpej /* If we're the FPU owner, dump its context to the PCB first. */ 1771.8Sthorpej if (pcb->pcb_fpcpu) 1781.23Smatt save_fpu_lwp(l, FPU_SAVE); 1791.23Smatt (void)memcpy(mcp->__fpregs.__fpu_regs, pcb->pcb_fpu.fpreg, 1801.8Sthorpej sizeof (mcp->__fpregs.__fpu_regs)); 1811.8Sthorpej mcp->__fpregs.__fpu_fpscr = 1821.8Sthorpej ((int *)&pcb->pcb_fpu.fpscr)[_QUAD_LOWWORD]; 1831.8Sthorpej mcp->__fpregs.__fpu_valid = 1; 1841.8Sthorpej *flagp |= _UC_FPU; 1851.8Sthorpej } else 1861.8Sthorpej#endif 1871.13Smatt memset(&mcp->__fpregs, 0, sizeof(mcp->__fpregs)); 1881.8Sthorpej 1891.22Smatt#ifdef ALTIVEC 1901.22Smatt /* Save AltiVec context, if any. */ 1911.22Smatt if ((pcb->pcb_flags & PCB_ALTIVEC) != 0) { 1921.22Smatt /* 1931.22Smatt * If we're the AltiVec owner, dump its context 1941.22Smatt * to the PCB first. 1951.22Smatt */ 1961.22Smatt if (pcb->pcb_veccpu) 1971.23Smatt save_vec_lwp(l, ALTIVEC_SAVE); 1981.22Smatt (void)memcpy(mcp->__vrf.__vrs, pcb->pcb_vr.vreg, 1991.22Smatt sizeof (mcp->__vrf.__vrs)); 2001.22Smatt mcp->__vrf.__vscr = pcb->pcb_vr.vscr; 2011.22Smatt mcp->__vrf.__vrsave = pcb->pcb_vr.vrsave; 2021.22Smatt *flagp |= _UC_POWERPC_VEC; 2031.22Smatt } else 2041.22Smatt#endif 2051.22Smatt memset(&mcp->__vrf, 0, sizeof (mcp->__vrf)); 2061.8Sthorpej} 2071.8Sthorpej 2081.8Sthorpejint 2091.13Smattcpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) 2101.8Sthorpej{ 2111.8Sthorpej struct trapframe *tf = trapframe(l); 2121.26She const __greg_t *gr = mcp->__gregs; 2131.8Sthorpej#ifdef PPC_HAVE_FPU 2141.8Sthorpej struct pcb *pcb = &l->l_addr->u_pcb; 2151.8Sthorpej#endif 2161.8Sthorpej 2171.8Sthorpej /* Restore GPR context, if any. */ 2181.8Sthorpej if (flags & _UC_CPU) { 2191.21Smatt#ifdef PPC_HAVE_FPU 2201.21Smatt /* 2211.21Smatt * Always save the FP exception mode in the PCB. 2221.21Smatt */ 2231.21Smatt pcb->pcb_flags &= ~(PCB_FE0|PCB_FE1); 2241.21Smatt pcb->pcb_flags |= gr[_REG_MSR] & (PCB_FE0|PCB_FE1); 2251.21Smatt#endif 2261.21Smatt 2271.10Smatt (void)memcpy(&tf->fixreg, gr, 32 * sizeof (gr[0])); 2281.10Smatt tf->cr = gr[_REG_CR]; 2291.10Smatt tf->lr = gr[_REG_LR]; 2301.10Smatt tf->srr0 = gr[_REG_PC]; 2311.26She /* 2321.26She * Accept all user-settable bits without complaint; 2331.26She * userland should not need to know the machine-specific 2341.26She * MSR value. 2351.26She */ 2361.26She tf->srr1 = (gr[_REG_MSR] & PSL_USERMOD) | PSL_USERSET; 2371.10Smatt tf->ctr = gr[_REG_CTR]; 2381.10Smatt tf->xer = gr[_REG_XER]; 2391.11Smatt#ifdef PPC_OEA 2401.11Smatt tf->tf_xtra[TF_MQ] = gr[_REG_MQ]; 2411.11Smatt#endif 2421.8Sthorpej } 2431.8Sthorpej 2441.22Smatt#ifdef PPC_HAVE_FPU /* Restore FPR context, if any. */ 2451.8Sthorpej if ((flags & _UC_FPU) && mcp->__fpregs.__fpu_valid != 0) { 2461.23Smatt /* we don't need to save the state, just drop it */ 2471.23Smatt save_fpu_lwp(l, FPU_DISCARD); 2481.23Smatt (void)memcpy(&pcb->pcb_fpu.fpreg, &mcp->__fpregs.__fpu_regs, 2491.23Smatt sizeof (pcb->pcb_fpu.fpreg)); 2501.20Smatt ((int *)&pcb->pcb_fpu.fpscr)[_QUAD_LOWWORD] = 2511.20Smatt mcp->__fpregs.__fpu_fpscr; 2521.8Sthorpej } 2531.8Sthorpej#endif 2541.8Sthorpej 2551.22Smatt#ifdef ALTIVEC 2561.22Smatt /* Restore AltiVec context, if any. */ 2571.22Smatt if (flags & _UC_POWERPC_VEC) { 2581.23Smatt /* we don't need to save the state, just drop it */ 2591.23Smatt save_vec_lwp(l, ALTIVEC_DISCARD); 2601.22Smatt (void)memcpy(pcb->pcb_vr.vreg, &mcp->__vrf.__vrs, 2611.22Smatt sizeof (pcb->pcb_vr.vreg)); 2621.22Smatt pcb->pcb_vr.vscr = mcp->__vrf.__vscr; 2631.22Smatt pcb->pcb_vr.vrsave = mcp->__vrf.__vrsave; 2641.22Smatt } 2651.22Smatt#endif 2661.22Smatt 2671.8Sthorpej return (0); 2681.1Skleink} 269