sig_machdep.c revision 1.51
11.51Srin/* $NetBSD: sig_machdep.c,v 1.51 2020/06/22 05:34:57 rin 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.51Srin__KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.51 2020/06/22 05:34:57 rin 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.44Schs#include <sys/cpu.h> 471.1Skleink 481.36Srmind#include <uvm/uvm_extern.h> 491.36Srmind 501.22Smatt#include <powerpc/fpu.h> 511.22Smatt#include <powerpc/altivec.h> 521.37Srmind#include <powerpc/pcb.h> 531.41Smatt#include <powerpc/psl.h> 541.8Sthorpej 551.1Skleink/* 561.1Skleink * Send a signal to process. 571.1Skleink */ 581.1Skleinkvoid 591.34Shesendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) 601.1Skleink{ 611.13Smatt struct lwp * const l = curlwp; 621.13Smatt struct proc * const p = l->l_proc; 631.39Smatt struct trapframe * const tf = l->l_md.md_utf; 641.39Smatt struct sigaltstack * const ss = &l->l_sigstk; 651.39Smatt const struct sigact_sigdesc * const sd = 661.13Smatt &p->p_sigacts->sa_sigdesc[ksi->ksi_signo]; 671.39Smatt /* save handler before sendsig_reset trashes it! */ 681.39Smatt const void * const handler = sd->sd_sigact.sa_handler; 691.13Smatt ucontext_t uc; 701.13Smatt vaddr_t sp, sip, ucp; 711.27Sad int onstack, error; 721.1Skleink 731.1Skleink /* Do we need to jump onto the signal stack? */ 741.13Smatt onstack = (ss->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 751.13Smatt (sd->sd_sigact.sa_flags & SA_ONSTACK) != 0; 761.1Skleink 771.13Smatt /* Find top of stack. */ 781.38Smatt sp = (onstack ? (vaddr_t)ss->ss_sp + ss->ss_size : tf->tf_fixreg[1]); 791.13Smatt sp &= ~(CALLFRAMELEN-1); 801.13Smatt 811.13Smatt /* Allocate space for the ucontext. */ 821.13Smatt sp -= sizeof(ucontext_t); 831.13Smatt ucp = sp; 841.13Smatt 851.13Smatt /* Allocate space for the siginfo. */ 861.13Smatt sp -= sizeof(siginfo_t); 871.13Smatt sip = sp; 881.13Smatt 891.13Smatt sp &= ~(CALLFRAMELEN-1); 901.1Skleink 911.1Skleink /* Save register context. */ 921.46Smaxv memset(&uc, 0, sizeof(uc)); 931.13Smatt uc.uc_flags = _UC_SIGMASK; 941.49Srin uc.uc_flags |= (ss->ss_flags & SS_ONSTACK) ? 951.49Srin _UC_SETSTACK : _UC_CLRSTACK; 961.13Smatt uc.uc_sigmask = *mask; 971.30Spooka uc.uc_link = l->l_ctxlink; 981.27Sad sendsig_reset(l, ksi->ksi_signo); 991.32Sad mutex_exit(p->p_lock); 1001.13Smatt cpu_getmcontext(l, &uc.uc_mcontext, &uc.uc_flags); 1011.1Skleink 1021.1Skleink /* 1031.13Smatt * Copy the siginfo and ucontext onto the user's stack. 1041.1Skleink */ 1051.29Schristos error = (copyout(&ksi->ksi_info, (void *)sip, sizeof(ksi->ksi_info)) != 0 || 1061.29Schristos copyout(&uc, (void *)ucp, sizeof(uc)) != 0); 1071.32Sad mutex_enter(p->p_lock); 1081.27Sad 1091.27Sad if (error) { 1101.1Skleink /* 1111.1Skleink * Process has trashed its stack; give it an illegal 1121.14Smatt * instruction to halt it in its tracks. 1131.1Skleink */ 1141.8Sthorpej sigexit(l, SIGILL); 1151.1Skleink /* NOTREACHED */ 1161.1Skleink } 1171.1Skleink 1181.1Skleink /* 1191.7Sthorpej * Build context to run handler in. Note the trampoline version 1201.7Sthorpej * numbers are coordinated with machine-dependent code in libc. 1211.1Skleink */ 1221.13Smatt switch (sd->sd_vers) { 1231.13Smatt case 2: /* siginfo sigtramp */ 1241.38Smatt tf->tf_fixreg[1] = (register_t)sp - CALLFRAMELEN; 1251.38Smatt tf->tf_fixreg[3] = (register_t)ksi->ksi_signo; 1261.38Smatt tf->tf_fixreg[4] = (register_t)sip; 1271.38Smatt tf->tf_fixreg[5] = (register_t)ucp; 1281.14Smatt /* Preserve ucp across call to signal function */ 1291.38Smatt tf->tf_fixreg[30] = (register_t)ucp; 1301.38Smatt tf->tf_lr = (register_t)sd->sd_tramp; 1311.39Smatt tf->tf_srr0 = (register_t)handler; 1321.7Sthorpej break; 1331.7Sthorpej 1341.7Sthorpej default: 1351.14Smatt goto nosupport; 1361.7Sthorpej } 1371.1Skleink 1381.1Skleink /* Remember that we're now on the signal stack. */ 1391.1Skleink if (onstack) 1401.13Smatt ss->ss_flags |= SS_ONSTACK; 1411.14Smatt return; 1421.14Smatt 1431.14Smatt nosupport: 1441.14Smatt /* Don't know what trampoline version; kill it. */ 1451.14Smatt printf("sendsig_siginfo(sig %d): bad version %d\n", 1461.17Smatt ksi->ksi_signo, sd->sd_vers); 1471.14Smatt sigexit(l, SIGILL); 1481.14Smatt /* NOTREACHED */ 1491.8Sthorpej} 1501.8Sthorpej 1511.8Sthorpejvoid 1521.13Smattcpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flagp) 1531.8Sthorpej{ 1541.40Smatt const struct trapframe * const tf = l->l_md.md_utf; 1551.38Smatt __greg_t * const gr = mcp->__gregs; 1561.38Smatt#if defined(PPC_HAVE_FPU) 1571.38Smatt struct pcb * const pcb = lwp_getpcb(l); 1581.8Sthorpej#endif 1591.8Sthorpej 1601.8Sthorpej /* Save GPR context. */ 1611.38Smatt (void)memcpy(gr, &tf->tf_fixreg, 32 * sizeof (gr[0])); /* GR0-31 */ 1621.38Smatt gr[_REG_CR] = tf->tf_cr; 1631.38Smatt gr[_REG_LR] = tf->tf_lr; 1641.38Smatt gr[_REG_PC] = tf->tf_srr0; 1651.38Smatt gr[_REG_MSR] = tf->tf_srr1 & PSL_USERSRR1; 1661.21Smatt#ifdef PPC_HAVE_FPU 1671.21Smatt gr[_REG_MSR] |= pcb->pcb_flags & (PCB_FE0|PCB_FE1); 1681.21Smatt#endif 1691.38Smatt gr[_REG_CTR] = tf->tf_ctr; 1701.38Smatt gr[_REG_XER] = tf->tf_xer; 1711.11Smatt#ifdef PPC_OEA 1721.38Smatt gr[_REG_MQ] = tf->tf_mq; 1731.11Smatt#else 1741.11Smatt gr[_REG_MQ] = 0; 1751.11Smatt#endif 1761.38Smatt 1771.8Sthorpej *flagp |= _UC_CPU; 1781.44Schs *flagp |= _UC_TLSBASE; 1791.8Sthorpej 1801.8Sthorpej#ifdef PPC_HAVE_FPU 1811.38Smatt /* Save FPU context, if any. */ 1821.38Smatt if (!fpu_save_to_mcontext(l, mcp, flagp)) 1831.8Sthorpej#endif 1841.13Smatt memset(&mcp->__fpregs, 0, sizeof(mcp->__fpregs)); 1851.8Sthorpej 1861.38Smatt#if defined(ALTIVEC) || defined(PPC_HAVE_SPE) 1871.38Smatt /* Save vector context, if any. */ 1881.38Smatt if (!vec_save_to_mcontext(l, mcp, flagp)) 1891.22Smatt#endif 1901.22Smatt memset(&mcp->__vrf, 0, sizeof (mcp->__vrf)); 1911.8Sthorpej} 1921.8Sthorpej 1931.8Sthorpejint 1941.42Smartincpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp) 1951.42Smartin{ 1961.42Smartin return 0; 1971.42Smartin} 1981.42Smartin 1991.42Smartinint 2001.13Smattcpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) 2011.8Sthorpej{ 2021.40Smatt struct trapframe * const tf = l->l_md.md_utf; 2031.38Smatt const __greg_t * const gr = mcp->__gregs; 2041.49Srin struct proc * const p = l->l_proc; 2051.42Smartin int error; 2061.8Sthorpej 2071.8Sthorpej /* Restore GPR context, if any. */ 2081.8Sthorpej if (flags & _UC_CPU) { 2091.42Smartin error = cpu_mcontext_validate(l, mcp); 2101.42Smartin if (error) 2111.42Smartin return error; 2121.42Smartin 2131.21Smatt#ifdef PPC_HAVE_FPU 2141.21Smatt /* 2151.21Smatt * Always save the FP exception mode in the PCB. 2161.21Smatt */ 2171.38Smatt struct pcb * const pcb = lwp_getpcb(l); 2181.21Smatt pcb->pcb_flags &= ~(PCB_FE0|PCB_FE1); 2191.21Smatt pcb->pcb_flags |= gr[_REG_MSR] & (PCB_FE0|PCB_FE1); 2201.21Smatt#endif 2211.21Smatt 2221.45Schs /* 2231.45Schs * R2 is the TLS register so avoid updating it here. 2241.45Schs */ 2251.45Schs 2261.45Schs __greg_t save_r2 = tf->tf_fixreg[_REG_R2]; 2271.38Smatt (void)memcpy(&tf->tf_fixreg, gr, 32 * sizeof (gr[0])); 2281.45Schs tf->tf_fixreg[_REG_R2] = save_r2; 2291.38Smatt tf->tf_cr = gr[_REG_CR]; 2301.38Smatt tf->tf_lr = gr[_REG_LR]; 2311.38Smatt tf->tf_srr0 = gr[_REG_PC]; 2321.45Schs 2331.26She /* 2341.26She * Accept all user-settable bits without complaint; 2351.26She * userland should not need to know the machine-specific 2361.26She * MSR value. 2371.26She */ 2381.38Smatt tf->tf_srr1 = (gr[_REG_MSR] & PSL_USERMOD) | PSL_USERSET; 2391.38Smatt tf->tf_ctr = gr[_REG_CTR]; 2401.38Smatt tf->tf_xer = gr[_REG_XER]; 2411.11Smatt#ifdef PPC_OEA 2421.38Smatt tf->tf_mq = gr[_REG_MQ]; 2431.11Smatt#endif 2441.8Sthorpej } 2451.8Sthorpej 2461.45Schs if (flags & _UC_TLSBASE) 2471.51Srin lwp_setprivate(l, (void *)(uintptr_t)gr[_REG_R2]); 2481.45Schs 2491.38Smatt#ifdef PPC_HAVE_FPU 2501.38Smatt /* Restore FPU context, if any. */ 2511.38Smatt if (flags & _UC_FPU) 2521.38Smatt fpu_restore_from_mcontext(l, mcp); 2531.8Sthorpej#endif 2541.8Sthorpej 2551.22Smatt#ifdef ALTIVEC 2561.22Smatt /* Restore AltiVec context, if any. */ 2571.38Smatt if (flags & _UC_POWERPC_VEC) 2581.38Smatt vec_restore_from_mcontext(l, mcp); 2591.38Smatt#endif 2601.38Smatt 2611.38Smatt#ifdef PPC_HAVE_SPE 2621.38Smatt /* Restore SPE context, if any. */ 2631.38Smatt if (flags & _UC_POWERPC_SPE) 2641.38Smatt vec_restore_from_mcontext(l, mcp); 2651.22Smatt#endif 2661.22Smatt 2671.49Srin mutex_enter(p->p_lock); 2681.49Srin if (flags & _UC_SETSTACK) 2691.49Srin l->l_sigstk.ss_flags |= SS_ONSTACK; 2701.49Srin if (flags & _UC_CLRSTACK) 2711.49Srin l->l_sigstk.ss_flags &= ~SS_ONSTACK; 2721.49Srin mutex_exit(p->p_lock); 2731.49Srin 2741.8Sthorpej return (0); 2751.1Skleink} 2761.44Schs 2771.44Schsint 2781.44Schscpu_lwp_setprivate(lwp_t *l, void *addr) 2791.44Schs{ 2801.44Schs struct trapframe * const tf = l->l_md.md_utf; 2811.44Schs 2821.51Srin tf->tf_fixreg[_REG_R2] = (register_t)addr; 2831.50Srin 2841.44Schs return 0; 2851.44Schs} 286