1 /* $NetBSD: compat_16_machdep.c,v 1.16 2011/01/18 01:02:55 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: compat_16_machdep.c,v 1.16 2011/01/18 01:02:55 matt Exp $"); 36 37 #ifdef _KERNEL_OPT 38 #include "opt_compat_netbsd.h" 39 #include "opt_altivec.h" 40 #include "opt_ppcarch.h" 41 #endif 42 43 #include <sys/param.h> 44 #include <sys/mount.h> 45 #include <sys/proc.h> 46 #include <sys/syscallargs.h> 47 #include <sys/systm.h> 48 #include <sys/ucontext.h> 49 50 #include <uvm/uvm_extern.h> 51 52 #include <compat/sys/signal.h> 53 #include <compat/sys/signalvar.h> 54 55 #include <powerpc/pcb.h> 56 #include <powerpc/fpu.h> 57 58 /* 59 * Send a signal to process. 60 */ 61 void 62 sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) 63 { 64 struct lwp *l = curlwp; 65 struct proc *p = l->l_proc; 66 struct sigacts *ps = p->p_sigacts; 67 struct sigcontext *fp, frame; 68 struct trapframe *tf; 69 struct utrapframe *utf = &frame.sc_frame; 70 int onstack, error; 71 int sig = ksi->ksi_signo; 72 u_long code = KSI_TRAPCODE(ksi); 73 sig_t catcher = SIGACTION(p, sig).sa_handler; 74 75 tf = trapframe(l); 76 77 /* Do we need to jump onto the signal stack? */ 78 onstack = 79 (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 80 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 81 82 /* Allocate space for the signal handler context. */ 83 if (onstack) 84 fp = (struct sigcontext *)((char *)l->l_sigstk.ss_sp + 85 l->l_sigstk.ss_size); 86 else 87 fp = (struct sigcontext *)tf->tf_fixreg[1]; 88 fp = (struct sigcontext *)((uintptr_t)(fp - 1) & -CALLFRAMELEN); 89 90 /* Save register context. */ 91 memcpy(utf->fixreg, tf->tf_fixreg, sizeof(utf->fixreg)); 92 utf->lr = tf->tf_lr; 93 utf->cr = tf->tf_cr; 94 utf->xer = tf->tf_xer; 95 utf->ctr = tf->tf_ctr; 96 utf->srr0 = tf->tf_srr0; 97 utf->srr1 = tf->tf_srr1 & PSL_USERSRR1; 98 99 #ifdef PPC_HAVE_FPU 100 const struct pcb * const pcb = lwp_getpcb(l); 101 utf->srr1 |= pcb->pcb_flags & (PCB_FE0|PCB_FE1); 102 #endif 103 #if defined(ALTIVEC) || defined(PPC_HAVE_SPE) 104 utf->srr1 |= l->l_md.md_flags & MDLWP_USEDVEC ? PSL_VEC : 0; 105 #endif 106 #ifdef PPC_OEA 107 utf->vrsave = tf->tf_vrsave; 108 utf->mq = tf->tf_mq; 109 #endif 110 111 /* Save signal stack. */ 112 frame.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; 113 114 /* Save signal mask. */ 115 frame.sc_mask = *mask; 116 117 #ifdef COMPAT_13 118 /* 119 * XXX We always have to save an old style signal mask because 120 * XXX we might be delivering a signal to a process which will 121 * XXX escape from the signal in a non-standard way and invoke 122 * XXX sigreturn() directly. 123 */ 124 native_sigset_to_sigset13(mask, &frame.__sc_mask13); 125 #endif 126 sendsig_reset(l, sig); 127 mutex_exit(p->p_lock); 128 error = copyout(&frame, fp, sizeof frame); 129 mutex_enter(p->p_lock); 130 131 if (error != 0) { 132 /* 133 * Process has trashed its stack; give it an illegal 134 * instructoin to halt it in its tracks. 135 */ 136 sigexit(l, SIGILL); 137 /* NOTREACHED */ 138 } 139 140 /* 141 * Build context to run handler in. Note the trampoline version 142 * numbers are coordinated with machine-dependent code in libc. 143 */ 144 switch (ps->sa_sigdesc[sig].sd_vers) { 145 #if 1 /* COMPAT_16 */ 146 case 0: /* legacy on-stack sigtramp */ 147 tf->tf_fixreg[1] = (register_t)fp; 148 tf->tf_lr = (register_t)catcher; 149 tf->tf_fixreg[3] = (register_t)sig; 150 tf->tf_fixreg[4] = (register_t)code; 151 tf->tf_fixreg[5] = (register_t)fp; 152 tf->tf_srr0 = (register_t)p->p_sigctx.ps_sigcode; 153 break; 154 #endif /* COMPAT_16 */ 155 156 case 1: 157 tf->tf_fixreg[1] = (register_t)fp; 158 tf->tf_lr = (register_t)catcher; 159 tf->tf_fixreg[3] = (register_t)sig; 160 tf->tf_fixreg[4] = (register_t)code; 161 tf->tf_fixreg[5] = (register_t)fp; 162 tf->tf_srr0 = (register_t)ps->sa_sigdesc[sig].sd_tramp; 163 break; 164 165 default: 166 /* Don't know what trampoline version; kill it. */ 167 sigexit(l, SIGILL); 168 } 169 170 /* Remember that we're now on the signal stack. */ 171 if (onstack) 172 l->l_sigstk.ss_flags |= SS_ONSTACK; 173 } 174 175 /* 176 * System call to cleanup state after a signal handler returns. 177 */ 178 int 179 compat_16_sys___sigreturn14(struct lwp *l, 180 const struct compat_16_sys___sigreturn14_args *uap, register_t *retval) 181 { 182 /* { 183 syscallarg(struct sigcontext *) sigcntxp; 184 } */ 185 struct proc * const p = l->l_proc; 186 struct sigcontext sc; 187 struct utrapframe * const utf = &sc.sc_frame; 188 int error; 189 190 /* 191 * The trampoline hands us the context. 192 * It is unsafe to keep track of it ourselves, in the event that a 193 * program jumps out of a signal hander. 194 */ 195 if ((error = copyin(SCARG(uap, sigcntxp), &sc, sizeof sc)) != 0) 196 return (error); 197 198 /* Restore the register context. */ 199 struct trapframe * const tf = trapframe(l); 200 201 /* 202 * Make sure SRR1 hasn't been maliciously tampered with. 203 */ 204 if (!PSL_USEROK_P(sc.sc_frame.srr1)) 205 return (EINVAL); 206 207 /* Restore register context. */ 208 memcpy(tf->tf_fixreg, utf->fixreg, sizeof(tf->tf_fixreg)); 209 tf->tf_lr = utf->lr; 210 tf->tf_cr = utf->cr; 211 tf->tf_xer = utf->xer; 212 tf->tf_ctr = utf->ctr; 213 tf->tf_srr0 = utf->srr0; 214 tf->tf_srr1 = utf->srr1; 215 216 #ifdef PPC_HAVE_FPU 217 struct pcb * const pcb = lwp_getpcb(l); 218 pcb->pcb_flags &= ~(PCB_FE0|PCB_FE1); 219 pcb->pcb_flags |= utf->srr1 & (PCB_FE0|PCB_FE1); 220 #endif 221 #ifdef PPC_OEA 222 tf->tf_vrsave = utf->vrsave; 223 tf->tf_mq = utf->mq; 224 #endif 225 226 mutex_enter(p->p_lock); 227 /* Restore signal stack. */ 228 if (sc.sc_onstack & SS_ONSTACK) 229 l->l_sigstk.ss_flags |= SS_ONSTACK; 230 else 231 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 232 /* Restore signal mask. */ 233 (void) sigprocmask1(l, SIG_SETMASK, &sc.sc_mask, 0); 234 mutex_exit(p->p_lock); 235 236 return (EJUSTRETURN); 237 } 238