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