1 /* $NetBSD: compat_16_machdep.c,v 1.15 2009/11/21 04:16:52 rmind Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: compat_16_machdep.c,v 1.15 2009/11/21 04:16:52 rmind Exp $"); 35 36 #ifdef _KERNEL_OPT 37 #include "opt_compat_netbsd.h" 38 #endif 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/signal.h> 43 #include <sys/signalvar.h> 44 #include <sys/kernel.h> 45 #include <sys/proc.h> 46 #include <sys/mount.h> 47 #include <sys/syscallargs.h> 48 49 #include <machine/signal.h> 50 #include <machine/frame.h> 51 52 #if defined(COMPAT_16) 53 #include <compat/sys/signal.h> 54 #include <compat/sys/signalvar.h> 55 56 #ifdef DEBUG 57 /* See sigdebug.h */ 58 #include <sparc64/sparc64/sigdebug.h> 59 #endif 60 61 #ifdef __arch64__ 62 #define STACK_OFFSET BIAS 63 #define CPOUTREG(l,v) copyout(&(v), (l), sizeof(v)) 64 #undef CCFSZ 65 #define CCFSZ CC64FSZ 66 #else 67 #define STACK_OFFSET 0 68 #define CPOUTREG(l,v) copyout(&(v), (l), sizeof(v)) 69 #endif 70 71 struct sigframe_sigcontext { 72 int sf_signo; /* signal number */ 73 int sf_code; /* code */ 74 #ifndef __arch64__ 75 struct sigcontext *sf_scp; /* SunOS user addr of sigcontext */ 76 int sf_addr; /* SunOS compat, always 0 for now */ 77 #endif 78 struct sigcontext sf_sc; /* actual sigcontext */ 79 }; 80 81 /* 82 * Send an interrupt to process. 83 */ 84 void 85 sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) 86 { 87 struct lwp *l = curlwp; 88 struct proc *p = l->l_proc; 89 struct sigacts *ps = p->p_sigacts; 90 const void *addr; 91 struct rwindow *newsp; 92 #ifdef NOT_DEBUG 93 struct rwindow tmpwin; 94 #endif 95 int onstack, error; 96 int sig = ksi->ksi_signo; 97 struct sigframe_sigcontext *fp = getframe(l, sig, &onstack); 98 struct sigframe_sigcontext sf; 99 sig_t catcher = SIGACTION(p, sig).sa_handler; 100 struct trapframe64 *tf = l->l_md.md_tf; 101 /* Allocate an aligned sigframe */ 102 fp = (void *)((u_long)(fp - 1) & ~0x0f); 103 104 #ifdef DEBUG 105 sigpid = p->p_pid; 106 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { 107 printf("sendsig_sigcontext: %s[%d] sig %d newusp %p scp %p\n", 108 p->p_comm, p->p_pid, sig, fp, &fp->sf_sc); 109 #ifdef DDB 110 if (sigdebug & SDB_DDB) Debugger(); 111 #endif 112 } 113 #endif 114 115 /* 116 * Now set up the signal frame. We build it in kernel space 117 * and then copy it out. We probably ought to just build it 118 * directly in user space.... 119 */ 120 sf.sf_signo = sig; 121 sf.sf_code = ksi->ksi_trap; 122 #ifndef __arch64__ 123 sf.sf_scp = 0; 124 sf.sf_addr = 0; /* XXX */ 125 #endif 126 127 /* 128 * Build the signal context to be used by sigreturn. 129 */ 130 sf.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; 131 sf.sf_sc.sc_mask = *mask; 132 #ifdef COMPAT_13 133 /* 134 * XXX We always have to save an old style signal mask because 135 * XXX we might be delivering a signal to a process which will 136 * XXX escape from the signal in a non-standard way and invoke 137 * XXX sigreturn() directly. 138 */ 139 native_sigset_to_sigset13(mask, &sf.sf_sc.__sc_mask13); 140 #endif 141 /* Save register context. */ 142 sf.sf_sc.sc_sp = (long)tf->tf_out[6]; 143 sf.sf_sc.sc_pc = tf->tf_pc; 144 sf.sf_sc.sc_npc = tf->tf_npc; 145 #ifdef __arch64__ 146 sf.sf_sc.sc_tstate = tf->tf_tstate; /* XXX */ 147 #else 148 sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */ 149 #endif 150 sf.sf_sc.sc_g1 = tf->tf_global[1]; 151 sf.sf_sc.sc_o0 = tf->tf_out[0]; 152 153 /* 154 * Put the stack in a consistent state before we whack away 155 * at it. Note that write_user_windows may just dump the 156 * registers into the pcb; we need them in the process's memory. 157 * We also need to make sure that when we start the signal handler, 158 * its %i6 (%fp), which is loaded from the newly allocated stack area, 159 * joins seamlessly with the frame it was in when the signal occurred, 160 * so that the debugger and _longjmp code can back up through it. 161 */ 162 sendsig_reset(l, sig); 163 mutex_exit(p->p_lock); 164 newsp = (struct rwindow *)((vaddr_t)fp - sizeof(struct rwindow)); 165 write_user_windows(); 166 #ifdef DEBUG 167 if ((sigdebug & SDB_KSTACK)) 168 printf("sendsig: saving sf to %p, setting stack pointer %p to %p\n", 169 fp, &(((struct rwindow *)newsp)->rw_in[6]), 170 (void *)(unsigned long)tf->tf_out[6]); 171 #endif 172 error = (rwindow_save(l) || copyout((void *)&sf, (void *)fp, sizeof sf) || 173 #ifdef NOT_DEBUG 174 copyin(oldsp, &tmpwin, sizeof(tmpwin)) || copyout(&tmpwin, newsp, sizeof(tmpwin)) || 175 #endif 176 CPOUTREG(&(((struct rwindow *)newsp)->rw_in[6]), tf->tf_out[6])); 177 mutex_enter(p->p_lock); 178 179 if (error) { 180 /* 181 * Process has trashed its stack; give it an illegal 182 * instruction to halt it in its tracks. 183 */ 184 #ifdef DEBUG 185 mutex_exit(p->p_lock); 186 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 187 printf("sendsig: window save or copyout error\n"); 188 printf("sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig); 189 #ifdef DDB 190 if (sigdebug & SDB_DDB) Debugger(); 191 #endif 192 mutex_enter(p->p_lock); 193 #endif 194 sigexit(l, SIGILL); 195 /* NOTREACHED */ 196 } 197 198 #ifdef DEBUG 199 if (sigdebug & SDB_FOLLOW) { 200 printf("sendsig: %s[%d] sig %d scp %p\n", 201 p->p_comm, p->p_pid, sig, &fp->sf_sc); 202 } 203 #endif 204 205 /* 206 * Arrange to continue execution at the code copied out in exec(). 207 * It needs the function to call in %g1, and a new stack pointer. 208 */ 209 switch (ps->sa_sigdesc[sig].sd_vers) { 210 case 0: /* legacy on-stack sigtramp */ 211 addr = p->p_sigctx.ps_sigcode; 212 break; 213 214 case 1: 215 addr = ps->sa_sigdesc[sig].sd_tramp; 216 break; 217 218 default: 219 addr = NULL; /* XXX: gcc */ 220 /* Don't know what trampoline version; kill it. */ 221 sigexit(l, SIGILL); 222 } 223 224 tf->tf_global[1] = (vaddr_t)catcher; 225 tf->tf_pc = (const vaddr_t)addr; 226 tf->tf_npc = (const vaddr_t)addr + 4; 227 tf->tf_out[6] = (vaddr_t)newsp - STACK_OFFSET; 228 229 /* Remember that we're now on the signal stack. */ 230 if (onstack) 231 l->l_sigstk.ss_flags |= SS_ONSTACK; 232 233 #ifdef DEBUG 234 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { 235 mutex_exit(p->p_lock); 236 printf("sendsig: about to return to catcher %p thru %p\n", 237 catcher, (void *)(unsigned long)addr); 238 #ifdef DDB 239 if (sigdebug & SDB_DDB) Debugger(); 240 #endif 241 mutex_enter(p->p_lock); 242 } 243 #endif 244 } 245 246 /* 247 * System call to cleanup state after a signal 248 * has been taken. Reset signal mask and 249 * stack state from context left by sendsig (above), 250 * and return to the given trap frame (if there is one). 251 * Check carefully to make sure that the user has not 252 * modified the state to gain improper privileges or to cause 253 * a machine fault. 254 */ 255 int compat_16_sys___sigreturn14(struct lwp *, const struct compat_16_sys___sigreturn14_args *, register_t *); 256 257 /* ARGSUSED */ 258 int 259 compat_16_sys___sigreturn14(struct lwp *l, const struct compat_16_sys___sigreturn14_args *uap, register_t *retval) 260 { 261 /* { 262 syscallarg(struct sigcontext *) sigcntxp; 263 } */ 264 struct sigcontext sc, *scp; 265 struct trapframe64 *tf; 266 int error = EINVAL; 267 struct proc *p = l->l_proc; 268 269 /* First ensure consistent stack state (see sendsig). */ 270 write_user_windows(); 271 if (rwindow_save(l)) { 272 #ifdef DEBUG 273 printf("sigreturn14: rwindow_save(%p) failed, sending SIGILL\n", p); 274 #ifdef DDB 275 if (sigdebug & SDB_DDB) Debugger(); 276 #endif 277 #endif 278 mutex_enter(p->p_lock); 279 sigexit(l, SIGILL); 280 } 281 #ifdef DEBUG 282 if (sigdebug & SDB_FOLLOW) { 283 printf("sigreturn14: %s[%d], sigcntxp %p\n", 284 p->p_comm, p->p_pid, SCARG(uap, sigcntxp)); 285 #ifdef DDB 286 if (sigdebug & SDB_DDB) Debugger(); 287 #endif 288 } 289 #endif 290 scp = SCARG(uap, sigcntxp); 291 if ((vaddr_t)scp & 3 || (error = copyin((void *)scp, &sc, sizeof sc) != 0)) 292 #ifdef DEBUG 293 { 294 printf("sigreturn14: copyin failed: scp=%p\n", scp); 295 #ifdef DDB 296 if (sigdebug & SDB_DDB) Debugger(); 297 #endif 298 return (error); 299 } 300 #else 301 return (error); 302 #endif 303 scp = ≻ 304 305 tf = l->l_md.md_tf; 306 /* 307 * Only the icc bits in the psr are used, so it need not be 308 * verified. pc and npc must be multiples of 4. This is all 309 * that is required; if it holds, just do it. 310 */ 311 if (((sc.sc_pc | sc.sc_npc) & 3) != 0 || (sc.sc_pc == 0) || (sc.sc_npc == 0)) 312 #ifdef DEBUG 313 { 314 printf("sigreturn14: pc %p or npc %p invalid\n", 315 (void *)(unsigned long)sc.sc_pc, 316 (void *)(unsigned long)sc.sc_npc); 317 #ifdef DDB 318 if (sigdebug & SDB_DDB) Debugger(); 319 #endif 320 return (EINVAL); 321 } 322 #else 323 return (EINVAL); 324 #endif 325 /* take only psr ICC field */ 326 #ifdef __arch64__ 327 tf->tf_tstate = (uint64_t)(tf->tf_tstate & ~TSTATE_CCR) | (scp->sc_tstate & TSTATE_CCR); 328 #else 329 tf->tf_tstate = (uint64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(scp->sc_psr); 330 #endif 331 tf->tf_pc = (uint64_t)scp->sc_pc; 332 tf->tf_npc = (uint64_t)scp->sc_npc; 333 tf->tf_global[1] = (uint64_t)scp->sc_g1; 334 tf->tf_out[0] = (uint64_t)scp->sc_o0; 335 tf->tf_out[6] = (uint64_t)scp->sc_sp; 336 #ifdef DEBUG 337 if (sigdebug & SDB_FOLLOW) { 338 printf("sigreturn14: return trapframe pc=%p sp=%p tstate=%llx\n", 339 (void *)(unsigned long)tf->tf_pc, 340 (void *)(unsigned long)tf->tf_out[6], 341 (unsigned long long)tf->tf_tstate); 342 #ifdef DDB 343 if (sigdebug & SDB_DDB) Debugger(); 344 #endif 345 } 346 #endif 347 348 mutex_enter(p->p_lock); 349 /* Restore signal stack. */ 350 if (sc.sc_onstack & SS_ONSTACK) 351 l->l_sigstk.ss_flags |= SS_ONSTACK; 352 else 353 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 354 /* Restore signal mask. */ 355 (void) sigprocmask1(l, SIG_SETMASK, &sc.sc_mask, 0); 356 mutex_exit(p->p_lock); 357 358 return (EJUSTRETURN); 359 } 360 #endif /* COMPAT_16 */ 361