sig_machdep.c revision 1.13
1/* $NetBSD: sig_machdep.c,v 1.13 2003/09/25 18:42:18 matt Exp $ */ 2 3/* 4 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 * Copyright (C) 1995, 1996 TooLs GmbH. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by TooLs GmbH. 19 * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34#include <sys/cdefs.h> 35__KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.13 2003/09/25 18:42:18 matt Exp $"); 36 37#include "opt_compat_netbsd.h" 38#include "opt_ppcarch.h" 39 40#include <sys/param.h> 41#include <sys/mount.h> 42#include <sys/proc.h> 43#include <sys/sa.h> 44#include <sys/savar.h> 45#include <sys/syscallargs.h> 46#include <sys/systm.h> 47#include <sys/ucontext.h> 48#include <sys/user.h> 49 50#include <machine/fpu.h> 51 52/* 53 * Send a signal to process. 54 */ 55void 56sendsig(ksiginfo_t *ksi, sigset_t *mask) 57{ 58 struct lwp * const l = curlwp; 59 struct proc * const p = l->l_proc; 60 struct trapframe * const tf = trapframe(l); 61 struct sigaltstack *ss = &p->p_sigctx.ps_sigstk; 62 const struct sigact_sigdesc *sd = 63 &p->p_sigacts->sa_sigdesc[ksi->ksi_signo]; 64 ucontext_t uc; 65 vaddr_t sp, sip, ucp; 66 int onstack; 67 68#ifdef COMPAT_16 69 if (sd->sd_vers < 2) { 70 sendsig_sigcontext(ksi->ksi_signo, mask, ksi->ksi_trap); 71 return; 72 } 73#endif 74 75 /* Do we need to jump onto the signal stack? */ 76 onstack = (ss->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 77 (sd->sd_sigact.sa_flags & SA_ONSTACK) != 0; 78 79 /* Find top of stack. */ 80 sp = (onstack ? (vaddr_t)ss->ss_sp + ss->ss_size : tf->fixreg[1]); 81 sp &= ~(CALLFRAMELEN-1); 82 83 /* Allocate space for the ucontext. */ 84 sp -= sizeof(ucontext_t); 85 ucp = sp; 86 87 /* Allocate space for the siginfo. */ 88 sp -= sizeof(siginfo_t); 89 sip = sp; 90 91 sp &= ~(CALLFRAMELEN-1); 92 93 /* Save register context. */ 94 uc.uc_flags = _UC_SIGMASK; 95 uc.uc_sigmask = *mask; 96 uc.uc_link = NULL; 97 memset(&uc.uc_stack, 0, sizeof(uc.uc_stack)); 98 cpu_getmcontext(l, &uc.uc_mcontext, &uc.uc_flags); 99 100 /* 101 * Copy the siginfo and ucontext onto the user's stack. 102 */ 103 if (copyout(ksi, (caddr_t)sip, sizeof(ksi)) != 0 || 104 copyout(&uc, (caddr_t)ucp, sizeof(uc)) != 0) { 105 /* 106 * Process has trashed its stack; give it an illegal 107 * instructoin to halt it in its tracks. 108 */ 109 sigexit(l, SIGILL); 110 /* NOTREACHED */ 111 } 112 113 /* 114 * Build context to run handler in. Note the trampoline version 115 * numbers are coordinated with machine-dependent code in libc. 116 */ 117 switch (sd->sd_vers) { 118 case 2: /* siginfo sigtramp */ 119 tf->fixreg[1] = (register_t)sp; 120 tf->lr = (register_t)sd->sd_sigact.sa_handler; 121 tf->fixreg[3] = (register_t)ksi->_signo; 122 tf->fixreg[4] = (register_t)sip; 123 tf->fixreg[5] = (register_t)ucp; 124 tf->srr0 = (register_t)sd->sd_tramp; 125 break; 126 127 default: 128 /* Don't know what trampoline version; kill it. */ 129 printf("sendsig_siginfo(sig %d): bad version %d\n", 130 ksi->_signo, sd->sd_vers); 131 sigexit(l, SIGILL); 132 } 133 134 /* Remember that we're now on the signal stack. */ 135 if (onstack) 136 ss->ss_flags |= SS_ONSTACK; 137} 138 139void 140cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flagp) 141{ 142 const struct trapframe *tf = trapframe(l); 143 __greg_t *gr = mcp->__gregs; 144#ifdef PPC_HAVE_FPU 145 struct pcb *pcb = &l->l_addr->u_pcb; 146#endif 147 148 /* Save GPR context. */ 149 (void)memcpy(gr, &tf->fixreg, 32 * sizeof (gr[0])); /* GR0-31 */ 150 gr[_REG_CR] = tf->cr; 151 gr[_REG_LR] = tf->lr; 152 gr[_REG_PC] = tf->srr0; 153 gr[_REG_MSR] = tf->srr1; 154 gr[_REG_CTR] = tf->ctr; 155 gr[_REG_XER] = tf->xer; 156#ifdef PPC_OEA 157 gr[_REG_MQ] = tf->tf_xtra[TF_MQ]; 158#else 159 gr[_REG_MQ] = 0; 160#endif 161 *flagp |= _UC_CPU; 162 163#ifdef PPC_HAVE_FPU 164 /* Save FPR context, if any. */ 165 if ((pcb->pcb_flags & PCB_FPU) != 0) { 166 /* If we're the FPU owner, dump its context to the PCB first. */ 167 if (pcb->pcb_fpcpu) 168 save_fpu_lwp(l); 169 (void)memcpy(mcp->__fpregs.__fpu_regs, pcb->pcb_fpu.fpr, 170 sizeof (mcp->__fpregs.__fpu_regs)); 171 mcp->__fpregs.__fpu_fpscr = 172 ((int *)&pcb->pcb_fpu.fpscr)[_QUAD_LOWWORD]; 173 mcp->__fpregs.__fpu_valid = 1; 174 *flagp |= _UC_FPU; 175 } else 176#endif 177 memset(&mcp->__fpregs, 0, sizeof(mcp->__fpregs)); 178 179 /* No AltiVec support, for now. */ 180 memset(&mcp->__vrf, 0, sizeof (mcp->__vrf)); 181} 182 183int 184cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) 185{ 186 struct trapframe *tf = trapframe(l); 187 __greg_t *gr = mcp->__gregs; 188#ifdef PPC_HAVE_FPU 189 struct pcb *pcb = &l->l_addr->u_pcb; 190#endif 191 192 /* Restore GPR context, if any. */ 193 if (flags & _UC_CPU) { 194 if ((gr[_REG_MSR] & PSL_USERSTATIC) != 195 (tf->srr1 & PSL_USERSTATIC)) 196 return (EINVAL); 197 198 (void)memcpy(&tf->fixreg, gr, 32 * sizeof (gr[0])); 199 tf->cr = gr[_REG_CR]; 200 tf->lr = gr[_REG_LR]; 201 tf->srr0 = gr[_REG_PC]; 202 tf->srr1 = gr[_REG_MSR]; 203 tf->ctr = gr[_REG_CTR]; 204 tf->xer = gr[_REG_XER]; 205#ifdef PPC_OEA 206 tf->tf_xtra[TF_MQ] = gr[_REG_MQ]; 207#endif 208 } 209 210#ifdef PPC_HAVE_FPU 211 /* Restore FPR context, if any. */ 212 if ((flags & _UC_FPU) && mcp->__fpregs.__fpu_valid != 0) { 213 /* XXX we don't need to save the state, just to drop it */ 214 save_fpu_lwp(l); 215 (void)memcpy(&pcb->pcb_fpu.fpr, &mcp->__fpregs.__fpu_regs, 216 sizeof (pcb->pcb_fpu.fpr)); 217 pcb->pcb_fpu.fpscr = *(double *)&mcp->__fpregs.__fpu_fpscr; 218 } 219#endif 220 221 return (0); 222} 223