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