1 /* $NetBSD: sig_machdep.c,v 1.15 2001/07/28 13:08:34 tsutsui 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(catcher, sig, mask, code) 80 sig_t catcher; 81 int sig; 82 sigset_t *mask; 83 u_long code; 84 { 85 struct proc *p = curproc; 86 struct sigframe *fp, kf; 87 struct frame *frame; 88 short ft; 89 int onstack, fsize; 90 91 frame = (struct frame *)p->p_md.md_regs; 92 ft = frame->f_format; 93 94 /* Do we need to jump onto the signal stack? */ 95 onstack = 96 (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 97 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 98 99 /* Allocate space for the signal handler context. */ 100 fsize = sizeof(struct sigframe); 101 if (onstack) 102 fp = (struct sigframe *)((caddr_t)p->p_sigctx.ps_sigstk.ss_sp + 103 p->p_sigctx.ps_sigstk.ss_size); 104 else 105 fp = (struct sigframe *)(frame->f_regs[SP]); 106 fp--; 107 108 #ifdef DEBUG 109 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 110 printf("sendsig(%d): sig %d ssp %p usp %p scp %p ft %d\n", 111 p->p_pid, sig, &onstack, fp, &fp->sf_sc, ft); 112 #endif 113 114 /* Build stack frame for signal trampoline. */ 115 kf.sf_signum = sig; 116 kf.sf_code = code; 117 kf.sf_scp = &fp->sf_sc; 118 kf.sf_handler = catcher; 119 120 /* 121 * Save necessary hardware state. Currently this includes: 122 * - general registers 123 * - original exception frame (if not a "normal" frame) 124 * - FP coprocessor state 125 */ 126 kf.sf_state.ss_flags = SS_USERREGS; 127 memcpy(kf.sf_state.ss_frame.f_regs, frame->f_regs, 128 sizeof(frame->f_regs)); 129 if (ft >= FMT4) { 130 #ifdef DEBUG 131 if (ft > 15 || exframesize[ft] < 0) 132 panic("sendsig: bogus frame type"); 133 #endif 134 kf.sf_state.ss_flags |= SS_RTEFRAME; 135 kf.sf_state.ss_frame.f_format = frame->f_format; 136 kf.sf_state.ss_frame.f_vector = frame->f_vector; 137 memcpy(&kf.sf_state.ss_frame.F_u, &frame->F_u, 138 (size_t) exframesize[ft]); 139 /* 140 * Leave an indicator that we need to clean up the kernel 141 * stack. We do this by setting the "pad word" above the 142 * hardware stack frame to the amount the stack must be 143 * adjusted by. 144 * 145 * N.B. we increment rather than just set f_stackadj in 146 * case we are called from syscall when processing a 147 * sigreturn. In that case, f_stackadj may be non-zero. 148 */ 149 frame->f_stackadj += exframesize[ft]; 150 frame->f_format = frame->f_vector = 0; 151 #ifdef DEBUG 152 if (sigdebug & SDB_FOLLOW) 153 printf("sendsig(%d): copy out %d of frame %d\n", 154 p->p_pid, exframesize[ft], ft); 155 #endif 156 } 157 158 if (fputype) { 159 kf.sf_state.ss_flags |= SS_FPSTATE; 160 m68881_save(&kf.sf_state.ss_fpstate); 161 } 162 #ifdef DEBUG 163 if ((sigdebug & SDB_FPSTATE) && *(char *)&kf.sf_state.ss_fpstate) 164 printf("sendsig(%d): copy out FP state (%x) to %p\n", 165 p->p_pid, *(u_int *)&kf.sf_state.ss_fpstate, 166 &kf.sf_state.ss_fpstate); 167 #endif 168 169 /* Build the signal context to be used by sigreturn. */ 170 kf.sf_sc.sc_sp = frame->f_regs[SP]; 171 kf.sf_sc.sc_fp = frame->f_regs[A6]; 172 kf.sf_sc.sc_ap = (int)&fp->sf_state; 173 kf.sf_sc.sc_pc = frame->f_pc; 174 kf.sf_sc.sc_ps = frame->f_sr; 175 176 /* Save signal stack. */ 177 kf.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK; 178 179 /* Save signal mask. */ 180 kf.sf_sc.sc_mask = *mask; 181 182 #ifdef COMPAT_13 183 /* 184 * XXX We always have to save an old style signal mask because 185 * XXX we might be delivering a signal to a process which will 186 * XXX escape from the signal in a non-standard way and invoke 187 * XXX sigreturn() directly. 188 */ 189 native_sigset_to_sigset13(mask, &kf.sf_sc.__sc_mask13); 190 #endif 191 192 if (copyout(&kf, fp, fsize)) { 193 #ifdef DEBUG 194 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 195 printf("sendsig(%d): copyout failed on sig %d\n", 196 p->p_pid, sig); 197 #endif 198 /* 199 * Process has trashed its stack; give it an illegal 200 * instruction to halt it in its tracks. 201 */ 202 sigexit(p, SIGILL); 203 /* NOTREACHED */ 204 } 205 #ifdef DEBUG 206 if (sigdebug & SDB_FOLLOW) 207 printf("sendsig(%d): sig %d scp %p fp %p sc_sp %x sc_ap %x\n", 208 p->p_pid, sig, kf.sf_scp, fp, 209 kf.sf_sc.sc_sp, kf.sf_sc.sc_ap); 210 #endif 211 212 /* Set up the registers to return to sigcode. */ 213 frame->f_regs[SP] = (int)fp; 214 frame->f_pc = (int)p->p_sigctx.ps_sigcode; 215 216 /* Remember that we're now on the signal stack. */ 217 if (onstack) 218 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 219 220 #ifdef DEBUG 221 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 222 printf("sendsig(%d): sig %d returns\n", 223 p->p_pid, sig); 224 #endif 225 } 226 227 /* 228 * System call to cleanup state after a signal 229 * has been taken. Reset signal mask and 230 * stack state from context left by sendsig (above). 231 * Return to previous pc and psl as specified by 232 * context left by sendsig. Check carefully to 233 * make sure that the user has not modified the 234 * psl to gain improper privileges or to cause 235 * a machine fault. 236 */ 237 int 238 sys___sigreturn14(p, v, retval) 239 struct proc *p; 240 void *v; 241 register_t *retval; 242 { 243 struct sys___sigreturn14_args /* { 244 syscallarg(struct sigcontext *) sigcntxp; 245 } */ *uap = v; 246 struct sigcontext *scp; 247 struct frame *frame; 248 struct sigcontext tsigc; 249 struct sigstate tstate; 250 int rf, flags; 251 252 /* 253 * The trampoline code hands us the context. 254 * It is unsafe to keep track of it ourselves, in the event that a 255 * program jumps out of a signal handler. 256 */ 257 scp = SCARG(uap, sigcntxp); 258 #ifdef DEBUG 259 if (sigdebug & SDB_FOLLOW) 260 printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); 261 #endif 262 if ((int)scp & 1) 263 return (EINVAL); 264 265 if (copyin(scp, &tsigc, sizeof(tsigc)) != 0) 266 return (EFAULT); 267 scp = &tsigc; 268 269 /* Make sure the user isn't pulling a fast one on us! */ 270 if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_S)) != 0) 271 return (EINVAL); 272 273 /* Restore register context. */ 274 frame = (struct frame *) p->p_md.md_regs; 275 276 /* 277 * Grab pointer to hardware state information. 278 * If zero, the user is probably doing a longjmp. 279 */ 280 if ((rf = scp->sc_ap) == 0) 281 goto restore; 282 283 /* 284 * See if there is anything to do before we go to the 285 * expense of copying in close to 1/2K of data 286 */ 287 flags = fuword((caddr_t)rf); 288 #ifdef DEBUG 289 if (sigdebug & SDB_FOLLOW) 290 printf("sigreturn(%d): sc_ap %x flags %x\n", 291 p->p_pid, rf, flags); 292 #endif 293 /* fuword failed (bogus sc_ap value). */ 294 if (flags == -1) 295 return (EINVAL); 296 297 if (flags == 0 || copyin((caddr_t)rf, &tstate, sizeof(tstate)) != 0) 298 goto restore; 299 #ifdef DEBUG 300 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 301 printf("sigreturn(%d): ssp %p usp %x scp %p ft %d\n", 302 p->p_pid, &flags, scp->sc_sp, SCARG(uap, sigcntxp), 303 (flags & SS_RTEFRAME) ? tstate.ss_frame.f_format : -1); 304 #endif 305 /* 306 * Restore long stack frames. Note that we do not copy 307 * back the saved SR or PC, they were picked up above from 308 * the sigcontext structure. 309 */ 310 if (flags & SS_RTEFRAME) { 311 register int sz; 312 313 /* grab frame type and validate */ 314 sz = tstate.ss_frame.f_format; 315 if (sz > 15 || (sz = exframesize[sz]) < 0 316 || frame->f_stackadj < sz) 317 return (EINVAL); 318 frame->f_stackadj -= sz; 319 frame->f_format = tstate.ss_frame.f_format; 320 frame->f_vector = tstate.ss_frame.f_vector; 321 memcpy(&frame->F_u, &tstate.ss_frame.F_u, sz); 322 #ifdef DEBUG 323 if (sigdebug & SDB_FOLLOW) 324 printf("sigreturn(%d): copy in %d of frame type %d\n", 325 p->p_pid, sz, tstate.ss_frame.f_format); 326 #endif 327 } 328 329 /* 330 * Restore most of the users registers except for A6 and SP 331 * which will be handled below. 332 */ 333 if (flags & SS_USERREGS) 334 memcpy(frame->f_regs, tstate.ss_frame.f_regs, 335 sizeof(frame->f_regs) - (2 * NBPW)); 336 337 /* 338 * Restore the original FP context 339 */ 340 if (fputype && (flags & SS_FPSTATE)) 341 m68881_restore(&tstate.ss_fpstate); 342 343 restore: 344 /* 345 * Restore the user supplied information. 346 * This should be at the last so that the error (EINVAL) 347 * is reported to the sigreturn caller, not to the 348 * jump destination. 349 */ 350 351 frame->f_regs[SP] = scp->sc_sp; 352 frame->f_regs[A6] = scp->sc_fp; 353 frame->f_pc = scp->sc_pc; 354 frame->f_sr = scp->sc_ps; 355 356 /* Restore signal stack. */ 357 if (scp->sc_onstack & SS_ONSTACK) 358 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 359 else 360 p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; 361 362 /* Restore signal mask. */ 363 (void) sigprocmask1(p, SIG_SETMASK, &scp->sc_mask, 0); 364 365 #ifdef DEBUG 366 if ((sigdebug & SDB_FPSTATE) && *(char *)&tstate.ss_fpstate) 367 printf("sigreturn(%d): copied in FP state (%x) at %p\n", 368 p->p_pid, *(u_int *)&tstate.ss_fpstate, 369 &tstate.ss_fpstate); 370 if ((sigdebug & SDB_FOLLOW) || 371 ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) 372 printf("sigreturn(%d): returns\n", p->p_pid); 373 #endif 374 return (EJUSTRETURN); 375 } 376