1 /* $NetBSD: compat_16_machdep.c,v 1.14 2009/11/23 00:11:44 rmind Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * the Systems Programming Group of the University of Utah Computer 9 * Science Department. 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 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * from: Utah Hdr: machdep.c 1.74 92/12/20 36 * from: @(#)machdep.c 8.10 (Berkeley) 4/20/94 37 */ 38 /* 39 * Copyright (c) 1988 University of Utah. 40 * 41 * This code is derived from software contributed to Berkeley by 42 * the Systems Programming Group of the University of Utah Computer 43 * Science Department. 44 * 45 * Redistribution and use in source and binary forms, with or without 46 * modification, are permitted provided that the following conditions 47 * are met: 48 * 1. Redistributions of source code must retain the above copyright 49 * notice, this list of conditions and the following disclaimer. 50 * 2. Redistributions in binary form must reproduce the above copyright 51 * notice, this list of conditions and the following disclaimer in the 52 * documentation and/or other materials provided with the distribution. 53 * 3. All advertising materials mentioning features or use of this software 54 * must display the following acknowledgement: 55 * This product includes software developed by the University of 56 * California, Berkeley and its contributors. 57 * 4. Neither the name of the University nor the names of its contributors 58 * may be used to endorse or promote products derived from this software 59 * without specific prior written permission. 60 * 61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 71 * SUCH DAMAGE. 72 * 73 * from: Utah Hdr: machdep.c 1.74 92/12/20 74 * from: @(#)machdep.c 8.10 (Berkeley) 4/20/94 75 */ 76 77 #include <sys/cdefs.h> 78 __KERNEL_RCSID(0, "$NetBSD: compat_16_machdep.c,v 1.14 2009/11/23 00:11:44 rmind Exp $"); 79 80 #ifdef _KERNEL_OPT 81 #include "opt_compat_netbsd.h" 82 #endif 83 84 #define __M68K_SIGNAL_PRIVATE 85 86 #include <sys/param.h> 87 #include <sys/systm.h> 88 #include <sys/kernel.h> 89 #include <sys/proc.h> 90 #include <sys/ras.h> 91 #include <sys/signal.h> 92 #include <sys/signalvar.h> 93 #include <sys/ucontext.h> 94 95 #include <sys/mount.h> 96 #include <sys/syscallargs.h> 97 98 #ifdef COMPAT_13 99 #include <compat/sys/signal.h> 100 #include <compat/sys/signalvar.h> 101 #endif 102 103 #include <machine/cpu.h> 104 #include <machine/reg.h> 105 #include <machine/frame.h> 106 107 extern short exframesize[]; 108 void m68881_save(struct fpframe *); 109 void m68881_restore(struct fpframe *); 110 111 #ifdef DEBUG 112 extern int sigdebug; 113 extern int sigpid; 114 #define SDB_FOLLOW 0x01 115 #define SDB_KSTACK 0x02 116 #define SDB_FPSTATE 0x04 117 #endif 118 119 #ifdef COMPAT_16 120 /* 121 * Send an interrupt to process. 122 */ 123 void 124 sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) 125 { 126 struct lwp *l = curlwp; 127 struct proc *p = l->l_proc; 128 struct sigacts *ps = p->p_sigacts; 129 struct frame *frame = (struct frame *)l->l_md.md_regs; 130 int onstack, error; 131 int sig = ksi->ksi_signo; 132 u_long code = KSI_TRAPCODE(ksi); 133 struct sigframe_sigcontext *fp = getframe(l, sig, &onstack), kf; 134 sig_t catcher = SIGACTION(p, sig).sa_handler; 135 short ft = frame->f_format; 136 137 fp--; 138 139 #ifdef DEBUG 140 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 141 printf("sendsig(%d): sig %d ssp %p usp %p scp %p ft %d\n", 142 p->p_pid, sig, &onstack, fp, &fp->sf_sc, ft); 143 #endif 144 145 /* Build stack frame for signal trampoline. */ 146 switch (ps->sa_sigdesc[sig].sd_vers) { 147 case 0: /* legacy on-stack sigtramp */ 148 kf.sf_ra = (int)p->p_sigctx.ps_sigcode; 149 break; 150 151 case 1: 152 kf.sf_ra = (int)ps->sa_sigdesc[sig].sd_tramp; 153 break; 154 155 default: 156 /* Don't know what trampoline version; kill it. */ 157 sigexit(l, SIGILL); 158 } 159 160 kf.sf_signum = sig; 161 kf.sf_code = code; 162 kf.sf_scp = &fp->sf_sc; 163 164 /* 165 * Save necessary hardware state. Currently this includes: 166 * - general registers 167 * - original exception frame (if not a "normal" frame) 168 * - FP coprocessor state 169 */ 170 kf.sf_state.ss_flags = SS_USERREGS; 171 memcpy(kf.sf_state.ss_frame.f_regs, frame->f_regs, 172 sizeof(frame->f_regs)); 173 if (ft >= FMT4) { 174 #ifdef DEBUG 175 if (ft > 15 || exframesize[ft] < 0) 176 panic("sendsig: bogus frame type"); 177 #endif 178 kf.sf_state.ss_flags |= SS_RTEFRAME; 179 kf.sf_state.ss_frame.f_format = frame->f_format; 180 kf.sf_state.ss_frame.f_vector = frame->f_vector; 181 memcpy(&kf.sf_state.ss_frame.F_u, &frame->F_u, 182 (size_t) exframesize[ft]); 183 /* 184 * Leave an indicator that we need to clean up the kernel 185 * stack. We do this by setting the "pad word" above the 186 * hardware stack frame to the amount the stack must be 187 * adjusted by. 188 * 189 * N.B. we increment rather than just set f_stackadj in 190 * case we are called from syscall when processing a 191 * sigreturn. In that case, f_stackadj may be non-zero. 192 */ 193 frame->f_stackadj += exframesize[ft]; 194 frame->f_format = frame->f_vector = 0; 195 #ifdef DEBUG 196 if (sigdebug & SDB_FOLLOW) 197 printf("sendsig(%d): copy out %d of frame %d\n", 198 p->p_pid, exframesize[ft], ft); 199 #endif 200 } 201 202 if (fputype) { 203 kf.sf_state.ss_flags |= SS_FPSTATE; 204 m68881_save(&kf.sf_state.ss_fpstate); 205 } 206 #ifdef DEBUG 207 if ((sigdebug & SDB_FPSTATE) && *(char *)&kf.sf_state.ss_fpstate) 208 printf("sendsig(%d): copy out FP state (%x) to %p\n", 209 p->p_pid, *(u_int *)&kf.sf_state.ss_fpstate, 210 &kf.sf_state.ss_fpstate); 211 #endif 212 213 /* Build the signal context to be used by sigreturn. */ 214 kf.sf_sc.sc_sp = frame->f_regs[SP]; 215 kf.sf_sc.sc_fp = frame->f_regs[A6]; 216 kf.sf_sc.sc_ap = (int)&fp->sf_state; 217 kf.sf_sc.sc_pc = frame->f_pc; 218 kf.sf_sc.sc_ps = frame->f_sr; 219 220 /* Save signal stack. */ 221 kf.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; 222 223 /* Save signal mask. */ 224 kf.sf_sc.sc_mask = *mask; 225 226 #ifdef COMPAT_13 227 /* 228 * XXX We always have to save an old style signal mask because 229 * XXX we might be delivering a signal to a process which will 230 * XXX escape from the signal in a non-standard way and invoke 231 * XXX sigreturn() directly. 232 */ 233 native_sigset_to_sigset13(mask, &kf.sf_sc.__sc_mask13); 234 #endif 235 sendsig_reset(l, sig); 236 mutex_exit(p->p_lock); 237 error = copyout(&kf, fp, sizeof(kf)); 238 mutex_enter(p->p_lock); 239 240 if (error != 0) { 241 #ifdef DEBUG 242 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 243 printf("sendsig(%d): copyout failed on sig %d\n", 244 p->p_pid, sig); 245 #endif 246 /* 247 * Process has trashed its stack; give it an illegal 248 * instruction to halt it in its tracks. 249 */ 250 sigexit(l, SIGILL); 251 /* NOTREACHED */ 252 } 253 #ifdef DEBUG 254 if (sigdebug & SDB_FOLLOW) 255 printf("sendsig(%d): sig %d scp %p fp %p sc_sp %x sc_ap %x\n", 256 p->p_pid, sig, kf.sf_scp, fp, 257 kf.sf_sc.sc_sp, kf.sf_sc.sc_ap); 258 #endif 259 260 buildcontext(l, catcher, fp); 261 262 /* Remember that we're now on the signal stack. */ 263 if (onstack) 264 l->l_sigstk.ss_flags |= SS_ONSTACK; 265 266 #ifdef DEBUG 267 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 268 printf("sendsig(%d): sig %d returns\n", 269 p->p_pid, sig); 270 #endif 271 } 272 #endif 273 274 #ifdef COMPAT_16 275 /* 276 * System call to cleanup state after a signal 277 * has been taken. Reset signal mask and 278 * stack state from context left by sendsig (above). 279 * Return to previous pc and psl as specified by 280 * context left by sendsig. Check carefully to 281 * make sure that the user has not modified the 282 * psl to gain improper privileges or to cause 283 * a machine fault. 284 */ 285 int 286 compat_16_sys___sigreturn14(struct lwp *l, const struct compat_16_sys___sigreturn14_args *uap, register_t *retval) 287 { 288 /* { 289 syscallarg(struct sigcontext *) sigcntxp; 290 } */ 291 struct proc *p = l->l_proc; 292 struct sigcontext *scp; 293 struct frame *frame; 294 struct sigcontext tsigc; 295 struct sigstate tstate; 296 int rf, flags; 297 298 /* 299 * The trampoline code hands us the context. 300 * It is unsafe to keep track of it ourselves, in the event that a 301 * program jumps out of a signal handler. 302 */ 303 scp = SCARG(uap, sigcntxp); 304 #ifdef DEBUG 305 if (sigdebug & SDB_FOLLOW) 306 printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); 307 #endif 308 if ((int)scp & 1) 309 return EINVAL; 310 311 if (copyin(scp, &tsigc, sizeof(tsigc)) != 0) 312 return EFAULT; 313 scp = &tsigc; 314 315 /* Make sure the user isn't pulling a fast one on us! */ 316 if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_S)) != 0) 317 return EINVAL; 318 319 /* Restore register context. */ 320 frame = (struct frame *) l->l_md.md_regs; 321 322 /* 323 * Grab pointer to hardware state information. 324 * If zero, the user is probably doing a longjmp. 325 */ 326 if ((rf = scp->sc_ap) == 0) 327 goto restore; 328 329 /* 330 * See if there is anything to do before we go to the 331 * expense of copying in close to 1/2K of data 332 */ 333 flags = fuword((void *)rf); 334 #ifdef DEBUG 335 if (sigdebug & SDB_FOLLOW) 336 printf("sigreturn(%d): sc_ap %x flags %x\n", 337 p->p_pid, rf, flags); 338 #endif 339 /* fuword failed (bogus sc_ap value). */ 340 if (flags == -1) 341 return EINVAL; 342 343 if (flags == 0 || copyin((void *)rf, &tstate, sizeof(tstate)) != 0) 344 goto restore; 345 #ifdef DEBUG 346 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 347 printf("sigreturn(%d): ssp %p usp %x scp %p ft %d\n", 348 p->p_pid, &flags, scp->sc_sp, SCARG(uap, sigcntxp), 349 (flags & SS_RTEFRAME) ? tstate.ss_frame.f_format : -1); 350 #endif 351 /* 352 * Restore long stack frames. Note that we do not copy 353 * back the saved SR or PC, they were picked up above from 354 * the sigcontext structure. 355 */ 356 if (flags & SS_RTEFRAME) { 357 register int sz; 358 359 /* grab frame type and validate */ 360 sz = tstate.ss_frame.f_format; 361 if (sz > 15 || (sz = exframesize[sz]) < 0 362 || frame->f_stackadj < sz) 363 return EINVAL; 364 frame->f_stackadj -= sz; 365 frame->f_format = tstate.ss_frame.f_format; 366 frame->f_vector = tstate.ss_frame.f_vector; 367 memcpy(&frame->F_u, &tstate.ss_frame.F_u, sz); 368 #ifdef DEBUG 369 if (sigdebug & SDB_FOLLOW) 370 printf("sigreturn(%d): copy in %d of frame type %d\n", 371 p->p_pid, sz, tstate.ss_frame.f_format); 372 #endif 373 } 374 375 /* 376 * Restore most of the users registers except for A6 and SP 377 * which will be handled below. 378 */ 379 if (flags & SS_USERREGS) 380 memcpy(frame->f_regs, tstate.ss_frame.f_regs, 381 sizeof(frame->f_regs) - (2 * NBPW)); 382 383 /* 384 * Restore the original FP context 385 */ 386 if (fputype && (flags & SS_FPSTATE)) 387 m68881_restore(&tstate.ss_fpstate); 388 389 restore: 390 /* 391 * Restore the user supplied information. 392 * This should be at the last so that the error (EINVAL) 393 * is reported to the sigreturn caller, not to the 394 * jump destination. 395 */ 396 397 frame->f_regs[SP] = scp->sc_sp; 398 frame->f_regs[A6] = scp->sc_fp; 399 frame->f_pc = scp->sc_pc; 400 frame->f_sr = scp->sc_ps; 401 402 mutex_enter(p->p_lock); 403 404 /* Restore signal stack. */ 405 if (scp->sc_onstack & SS_ONSTACK) 406 l->l_sigstk.ss_flags |= SS_ONSTACK; 407 else 408 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 409 410 /* Restore signal mask. */ 411 (void) sigprocmask1(l, SIG_SETMASK, &scp->sc_mask, 0); 412 413 mutex_exit(p->p_lock); 414 415 #ifdef DEBUG 416 if ((sigdebug & SDB_FPSTATE) && *(char *)&tstate.ss_fpstate) 417 printf("sigreturn(%d): copied in FP state (%x) at %p\n", 418 p->p_pid, *(u_int *)&tstate.ss_fpstate, 419 &tstate.ss_fpstate); 420 if ((sigdebug & SDB_FOLLOW) || 421 ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) 422 printf("sigreturn(%d): returns\n", p->p_pid); 423 #endif 424 return EJUSTRETURN; 425 } 426 #endif 427