sig_machdep.c revision 1.12
1/* $NetBSD: sig_machdep.c,v 1.12 2003/07/15 02:54:48 lukem 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.12 2003/07/15 02:54:48 lukem 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(sig, mask, code) 57 int sig; 58 sigset_t *mask; 59 u_long code; 60{ 61 struct lwp *l = curlwp; 62 struct proc *p = l->l_proc; 63 struct sigacts *ps = p->p_sigacts; 64 struct sigframe *fp, frame; 65 struct trapframe *tf; 66 struct utrapframe *utf = &frame.sf_sc.sc_frame; 67 int onstack; 68 sig_t catcher = SIGACTION(p, sig).sa_handler; 69 70 tf = trapframe(l); 71 72 /* Do we need to jump onto the signal stack? */ 73 onstack = 74 (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 75 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 76 77 /* Allocate space for the signal handler context. */ 78 if (onstack) 79 fp = (struct sigframe *)((caddr_t)p->p_sigctx.ps_sigstk.ss_sp + 80 p->p_sigctx.ps_sigstk.ss_size); 81 else 82 fp = (struct sigframe *)tf->fixreg[1]; 83 fp = (struct sigframe *)((uintptr_t)(fp - 1) & ~0xf); 84 85 /* Save register context. */ 86 memcpy(utf->fixreg, tf->fixreg, sizeof(utf->fixreg)); 87 utf->lr = tf->lr; 88 utf->cr = tf->cr; 89 utf->xer = tf->xer; 90 utf->ctr = tf->ctr; 91 utf->srr0 = tf->srr0; 92 utf->srr1 = tf->srr1; 93#ifdef PPC_OEA 94 utf->vrsave = tf->tf_xtra[TF_VRSAVE]; 95 utf->mq = tf->tf_xtra[TF_MQ]; 96#endif 97 98 /* Save signal stack. */ 99 frame.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK; 100 101 /* Save signal mask. */ 102 frame.sf_sc.sc_mask = *mask; 103 104#ifdef COMPAT_13 105 /* 106 * XXX We always have to save an old style signal mask because 107 * XXX we might be delivering a signal to a process which will 108 * XXX escape from the signal in a non-standard way and invoke 109 * XXX sigreturn() directly. 110 */ 111 native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13); 112#endif 113 114 if (copyout(&frame, fp, sizeof frame) != 0) { 115 /* 116 * Process has trashed its stack; give it an illegal 117 * instructoin to halt it in its tracks. 118 */ 119 sigexit(l, SIGILL); 120 /* NOTREACHED */ 121 } 122 123 /* 124 * Build context to run handler in. Note the trampoline version 125 * numbers are coordinated with machine-dependent code in libc. 126 */ 127 switch (ps->sa_sigdesc[sig].sd_vers) { 128#if 1 /* COMPAT_16 */ 129 case 0: /* legacy on-stack sigtramp */ 130 tf->fixreg[1] = (register_t)fp; 131 tf->lr = (register_t)catcher; 132 tf->fixreg[3] = (register_t)sig; 133 tf->fixreg[4] = (register_t)code; 134 tf->fixreg[5] = (register_t)&fp->sf_sc; 135 tf->srr0 = (register_t)p->p_sigctx.ps_sigcode; 136 break; 137#endif /* COMPAT_16 */ 138 139 case 1: 140 tf->fixreg[1] = (register_t)fp; 141 tf->lr = (register_t)catcher; 142 tf->fixreg[3] = (register_t)sig; 143 tf->fixreg[4] = (register_t)code; 144 tf->fixreg[5] = (register_t)&fp->sf_sc; 145 tf->srr0 = (register_t)ps->sa_sigdesc[sig].sd_tramp; 146 break; 147 148 default: 149 /* Don't know what trampoline version; kill it. */ 150 sigexit(l, SIGILL); 151 } 152 153 /* Remember that we're now on the signal stack. */ 154 if (onstack) 155 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 156} 157 158/* 159 * System call to cleanup state after a signal handler returns. 160 */ 161int 162sys___sigreturn14(l, v, retval) 163 struct lwp *l; 164 void *v; 165 register_t *retval; 166{ 167 struct sys___sigreturn14_args /* { 168 syscallarg(struct sigcontext *) sigcntxp; 169 } */ *uap = v; 170 struct proc *p = l->l_proc; 171 struct sigcontext sc; 172 struct trapframe *tf; 173 struct utrapframe * const utf = &sc.sc_frame; 174 int error; 175 176 /* 177 * The trampoline hands us the context. 178 * It is unsafe to keep track of it ourselves, in the event that a 179 * program jumps out of a signal hander. 180 */ 181 if ((error = copyin(SCARG(uap, sigcntxp), &sc, sizeof sc)) != 0) 182 return (error); 183 184 /* Restore the register context. */ 185 tf = trapframe(l); 186 if ((sc.sc_frame.srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) 187 return (EINVAL); 188 189 /* Restore register context. */ 190 memcpy(tf->fixreg, utf->fixreg, sizeof(tf->fixreg)); 191 tf->lr = utf->lr; 192 tf->cr = utf->cr; 193 tf->xer = utf->xer; 194 tf->ctr = utf->ctr; 195 tf->srr0 = utf->srr0; 196 tf->srr1 = utf->srr1; 197#ifdef PPC_OEA 198 tf->tf_xtra[TF_VRSAVE] = utf->vrsave; 199 tf->tf_xtra[TF_MQ] = utf->mq; 200#endif 201 202 /* Restore signal stack. */ 203 if (sc.sc_onstack & SS_ONSTACK) 204 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 205 else 206 p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; 207 208 /* Restore signal mask. */ 209 (void) sigprocmask1(p, SIG_SETMASK, &sc.sc_mask, 0); 210 211 return (EJUSTRETURN); 212} 213 214void 215cpu_getmcontext(l, mcp, flagp) 216 struct lwp *l; 217 mcontext_t *mcp; 218 unsigned int *flagp; 219{ 220 const struct trapframe *tf = trapframe(l); 221 __greg_t *gr = mcp->__gregs; 222#ifdef PPC_HAVE_FPU 223 struct pcb *pcb = &l->l_addr->u_pcb; 224#endif 225 226 /* Save GPR context. */ 227 (void)memcpy(gr, &tf->fixreg, 32 * sizeof (gr[0])); /* GR0-31 */ 228 gr[_REG_CR] = tf->cr; 229 gr[_REG_LR] = tf->lr; 230 gr[_REG_PC] = tf->srr0; 231 gr[_REG_MSR] = tf->srr1; 232 gr[_REG_CTR] = tf->ctr; 233 gr[_REG_XER] = tf->xer; 234#ifdef PPC_OEA 235 gr[_REG_MQ] = tf->tf_xtra[TF_MQ]; 236#else 237 gr[_REG_MQ] = 0; 238#endif 239 *flagp |= _UC_CPU; 240 241#ifdef PPC_HAVE_FPU 242 /* Save FPR context, if any. */ 243 if ((pcb->pcb_flags & PCB_FPU) != 0) { 244 /* If we're the FPU owner, dump its context to the PCB first. */ 245 if (pcb->pcb_fpcpu) 246 save_fpu_lwp(l); 247 (void)memcpy(mcp->__fpregs.__fpu_regs, pcb->pcb_fpu.fpr, 248 sizeof (mcp->__fpregs.__fpu_regs)); 249 mcp->__fpregs.__fpu_fpscr = 250 ((int *)&pcb->pcb_fpu.fpscr)[_QUAD_LOWWORD]; 251 mcp->__fpregs.__fpu_valid = 1; 252 *flagp |= _UC_FPU; 253 } else 254#endif 255 mcp->__fpregs.__fpu_valid = 0; 256 257 /* No AltiVec support, for now. */ 258 memset(&mcp->__vrf, 0, sizeof (mcp->__vrf)); 259} 260 261int 262cpu_setmcontext(l, mcp, flags) 263 struct lwp *l; 264 const mcontext_t *mcp; 265 unsigned int flags; 266{ 267 struct trapframe *tf = trapframe(l); 268 __greg_t *gr = mcp->__gregs; 269#ifdef PPC_HAVE_FPU 270 struct pcb *pcb = &l->l_addr->u_pcb; 271#endif 272 273 /* Restore GPR context, if any. */ 274 if (flags & _UC_CPU) { 275 if ((gr[_REG_MSR] & PSL_USERSTATIC) != 276 (tf->srr1 & PSL_USERSTATIC)) 277 return (EINVAL); 278 279 (void)memcpy(&tf->fixreg, gr, 32 * sizeof (gr[0])); 280 tf->cr = gr[_REG_CR]; 281 tf->lr = gr[_REG_LR]; 282 tf->srr0 = gr[_REG_PC]; 283 tf->srr1 = gr[_REG_MSR]; 284 tf->ctr = gr[_REG_CTR]; 285 tf->xer = gr[_REG_XER]; 286#ifdef PPC_OEA 287 tf->tf_xtra[TF_MQ] = gr[_REG_MQ]; 288#endif 289 } 290 291#ifdef PPC_HAVE_FPU 292 /* Restore FPR context, if any. */ 293 if ((flags & _UC_FPU) && mcp->__fpregs.__fpu_valid != 0) { 294 /* XXX we don't need to save the state, just to drop it */ 295 save_fpu_lwp(l); 296 (void)memcpy(&pcb->pcb_fpu.fpr, &mcp->__fpregs.__fpu_regs, 297 sizeof (pcb->pcb_fpu.fpr)); 298 pcb->pcb_fpu.fpscr = *(double *)&mcp->__fpregs.__fpu_fpscr; 299 } 300#endif 301 302 return (0); 303} 304