1 /* $NetBSD: sig_machdep.c,v 1.2 2002/07/04 23:32:04 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matthew Fredette. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Copyright (c) 1988 University of Utah. 41 * Copyright (c) 1982, 1986, 1990, 1993 42 * The Regents of the University of California. All rights reserved. 43 * 44 * This code is derived from software contributed to Berkeley by 45 * the Systems Programming Group of the University of Utah Computer 46 * Science Department. 47 * 48 * Redistribution and use in source and binary forms, with or without 49 * modification, are permitted provided that the following conditions 50 * are met: 51 * 1. Redistributions of source code must retain the above copyright 52 * notice, this list of conditions and the following disclaimer. 53 * 2. Redistributions in binary form must reproduce the above copyright 54 * notice, this list of conditions and the following disclaimer in the 55 * documentation and/or other materials provided with the distribution. 56 * 3. All advertising materials mentioning features or use of this software 57 * must display the following acknowledgement: 58 * This product includes software developed by the University of 59 * California, Berkeley and its contributors. 60 * 4. Neither the name of the University nor the names of its contributors 61 * may be used to endorse or promote products derived from this software 62 * without specific prior written permission. 63 * 64 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 65 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 66 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 67 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 68 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 69 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 70 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 71 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 72 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 73 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 74 * SUCH DAMAGE. 75 * 76 * from: Utah Hdr: machdep.c 1.74 92/12/20 77 * from: @(#)machdep.c 8.10 (Berkeley) 4/20/94 78 */ 79 80 #include "opt_compat_netbsd.h" 81 82 #define __HPPA_SIGNAL_PRIVATE 83 84 #include <sys/param.h> 85 #include <sys/systm.h> 86 #include <sys/kernel.h> 87 #include <sys/proc.h> 88 #include <sys/user.h> 89 #include <sys/signal.h> 90 #include <sys/signalvar.h> 91 92 #include <sys/mount.h> 93 #include <sys/syscallargs.h> 94 95 #include <machine/cpu.h> 96 #include <machine/reg.h> 97 98 #ifdef DEBUG 99 int sigdebug = 0xff; 100 int sigpid = 0; 101 #define SDB_FOLLOW 0x01 102 #define SDB_KSTACK 0x02 103 #define SDB_FPSTATE 0x04 104 #endif 105 106 /* 107 * Send an interrupt to process. 108 */ 109 void 110 sendsig(sig, mask, code) 111 int sig; 112 sigset_t *mask; 113 u_long code; 114 { 115 struct proc *p = curproc; 116 struct sigacts *ps = p->p_sigacts; 117 struct sigframe *fp, kf; 118 caddr_t sp; 119 struct trapframe *tf; 120 int onstack, fsize; 121 sig_t catcher = SIGACTION(p, sig).sa_handler; 122 123 tf = (struct trapframe *)p->p_md.md_regs; 124 125 /* Do we need to jump onto the signal stack? */ 126 onstack = 127 (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 128 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 129 130 /* 131 * Allocate space for the signal handler context. 132 * The PA-RISC calling convention mandates that 133 * the stack pointer must always be 64-byte aligned, 134 * and points to the first *unused* byte. 135 */ 136 fsize = sizeof(struct sigframe); 137 sp = (onstack ? 138 (caddr_t)p->p_sigctx.ps_sigstk.ss_sp : 139 (caddr_t)tf->tf_sp); 140 sp = (caddr_t)(((u_int)(sp + fsize + 63)) & ~63); 141 fp = (struct sigframe *) (sp - fsize); 142 143 #ifdef DEBUG 144 if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) 145 printf("sendsig: %s[%d] sig %d catcher %p\n", 146 p->p_comm, p->p_pid, sig, catcher); 147 #endif 148 149 /* 150 * Save necessary hardware state. Currently this includes: 151 * - original exception frame 152 * - FP coprocessor state 153 */ 154 kf.sf_state.ss_flags = SS_USERREGS; 155 memcpy(&kf.sf_state.ss_frame, tf, sizeof(*tf)); 156 /* XXX FP state */ 157 158 /* Build the signal context to be used by sigreturn. */ 159 kf.sf_sc.sc_sp = tf->tf_sp; 160 kf.sf_sc.sc_fp = tf->tf_sp; /* XXX fredette - is this right? */ 161 kf.sf_sc.sc_ap = (int)&fp->sf_state; 162 kf.sf_sc.sc_pcsqh = tf->tf_iisq_head; 163 kf.sf_sc.sc_pcoqh = tf->tf_iioq_head; 164 kf.sf_sc.sc_pcsqt = tf->tf_iisq_tail; 165 kf.sf_sc.sc_pcoqt = tf->tf_iioq_tail; 166 kf.sf_sc.sc_ps = tf->tf_ipsw; 167 168 /* Save signal stack. */ 169 kf.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK; 170 171 /* Save signal mask. */ 172 kf.sf_sc.sc_mask = *mask; 173 174 /* Fill the calling convention part of the signal frame. */ 175 kf.sf_psp = 0; 176 kf.sf_clup = 0; /* XXX fredette - is this right? */ 177 kf.sf_sl = 0; /* XXX fredette - is this right? */ 178 kf.sf_edp = 0; /* XXX fredette - is this right? */ 179 180 /* Copy out the signal frame. */ 181 if (copyout(&kf, fp, fsize)) { 182 #ifdef DEBUG 183 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 184 printf("sendsig(%d): copyout failed on sig %d\n", 185 p->p_pid, sig); 186 #endif 187 /* 188 * Process has trashed its stack; give it an illegal 189 * instruction to halt it in its tracks. 190 */ 191 sigexit(p, SIGILL); 192 /* NOTREACHED */ 193 } 194 #ifdef DEBUG 195 if (sigdebug & SDB_FOLLOW) 196 printf("sendsig(%d): sig %d scp %p fp %p sc_sp %x sc_ap %x\n", 197 p->p_pid, sig, &fp->sf_sc, fp, 198 kf.sf_sc.sc_sp, kf.sf_sc.sc_ap); 199 #endif 200 201 /* Set up the registers to return to sigcode. */ 202 switch (ps->sa_sigdesc[sig].sd_vers) { 203 #if 1 /* COMPAT_16 */ 204 case 0: /* legacy on-stack sigtramp */ 205 tf->tf_iioq_head = 206 (int)p->p_sigctx.ps_sigcode | HPPA_PC_PRIV_USER; 207 tf->tf_iioq_tail = tf->tf_iioq_head + 4; 208 break; 209 #endif 210 211 case 1: 212 tf->tf_iioq_head = 213 (int)ps->sa_sigdesc[sig].sd_tramp | HPPA_PC_PRIV_USER; 214 tf->tf_iioq_tail = tf->tf_iioq_head + 4; 215 break; 216 217 default: 218 /* Don't know what trampoline version; kill it. */ 219 sigexit(p, SIGILL); 220 } 221 222 tf->tf_sp = (int)sp; 223 tf->tf_r3 = (int)&fp->sf_sc; 224 tf->tf_arg0 = sig; 225 tf->tf_arg1 = code; 226 tf->tf_arg2 = (int)&fp->sf_sc; 227 tf->tf_arg3 = (int)catcher; 228 229 /* Remember that we're now on the signal stack. */ 230 if (onstack) 231 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 232 233 #ifdef DEBUG 234 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 235 printf("sendsig(%d): sig %d returns\n", 236 p->p_pid, sig); 237 #endif 238 } 239 240 int 241 sys___sigreturn14(p, v, retval) 242 struct proc *p; 243 void *v; 244 register_t *retval; 245 { 246 struct sys___sigreturn14_args /* { 247 syscallarg(struct sigcontext *) sigcntxp; 248 } */ *uap = v; 249 struct sigcontext *scp; 250 struct trapframe *tf; 251 struct sigcontext tsigc; 252 struct sigstate tstate; 253 int rf, flags; 254 255 /* 256 * The trampoline code hands us the context. 257 * It is unsafe to keep track of it ourselves, in the event that a 258 * program jumps out of a signal handler. 259 */ 260 scp = SCARG(uap, sigcntxp); 261 #ifdef DEBUG 262 if (sigdebug & SDB_FOLLOW) 263 printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); 264 #endif 265 if ((int)scp & 3) 266 return (EINVAL); 267 268 if (copyin(scp, &tsigc, sizeof(tsigc)) != 0) 269 return (EFAULT); 270 scp = &tsigc; 271 272 /* Make sure the user isn't pulling a fast one on us! */ 273 /* XXX fredette - until this is done, huge security hole here. */ 274 /* XXX fredette - requiring that PSL_R be zero will hurt debuggers. */ 275 #define PSW_MBS (PSW_C|PSW_Q|PSW_P|PSW_D|PSW_I) 276 #define PSW_MBZ (PSW_Y|PSW_Z|PSW_S|PSW_X|PSW_M|PSW_R) 277 if ((scp->sc_ps & (PSW_MBS|PSW_MBZ)) != PSW_MBS) 278 return (EINVAL); 279 280 /* Restore register context. */ 281 tf = (struct trapframe *) p->p_md.md_regs; 282 283 /* 284 * Grab pointer to hardware state information. 285 * If zero, the user is probably doing a longjmp. 286 */ 287 if ((rf = scp->sc_ap) == 0) 288 goto restore; 289 290 /* 291 * See if there is anything to do before we go to the 292 * expense of copying in the trapframe 293 */ 294 flags = fuword((caddr_t)rf); 295 #ifdef DEBUG 296 if (sigdebug & SDB_FOLLOW) 297 printf("sigreturn(%d): sc_ap %x flags %x\n", 298 p->p_pid, rf, flags); 299 #endif 300 /* fuword failed (bogus sc_ap value). */ 301 if (flags == -1) 302 return (EINVAL); 303 304 if (flags == 0 || copyin((caddr_t)rf, &tstate, sizeof(tstate)) != 0) 305 goto restore; 306 #ifdef DEBUG 307 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 308 printf("sigreturn(%d): ssp %p usp %x scp %p\n", 309 p->p_pid, &flags, scp->sc_sp, SCARG(uap, sigcntxp)); 310 #endif 311 312 /* 313 * Restore most of the users registers except for those 314 * in the sigcontext; they will be handled below. 315 */ 316 if (flags & SS_USERREGS) { 317 318 /* 319 * There are more registers that the user can tell 320 * us to bash than registers that, for security 321 * or other reasons, we must protect. So it's 322 * easier (but not faster), to copy these sensitive 323 * register values into the user-provided frame, 324 * then bulk-copy the user-provided frame into 325 * the process' frame. 326 */ 327 #define SIG_PROTECT(r) tstate.ss_frame.r = tf->r 328 /* SRs 5,6,7 must be protected. */ 329 SIG_PROTECT(tf_sr5); 330 SIG_PROTECT(tf_sr6); 331 SIG_PROTECT(tf_sr7); 332 333 /* all CRs except CR11 must be protected. */ 334 SIG_PROTECT(tf_rctr); /* CR0 */ 335 /* CRs 1-8 are reserved */ 336 SIG_PROTECT(tf_pidr1); /* CR8 */ 337 SIG_PROTECT(tf_pidr2); /* CR9 */ 338 SIG_PROTECT(tf_ccr); /* CR10 */ 339 SIG_PROTECT(tf_pidr3); /* CR12 */ 340 SIG_PROTECT(tf_pidr4); /* CR14 */ 341 SIG_PROTECT(tf_eiem); /* CR15 */ 342 /* CR17 is the IISQ head */ 343 /* CR18 is the IIOQ head */ 344 SIG_PROTECT(tf_iir); /* CR19 */ 345 SIG_PROTECT(tf_isr); /* CR20 */ 346 SIG_PROTECT(tf_ior); /* CR21 */ 347 /* CR22 is the IPSW */ 348 SIG_PROTECT(tf_eirr); /* CR23 */ 349 SIG_PROTECT(tf_hptm); /* CR24 */ 350 SIG_PROTECT(tf_vtop); /* CR25 */ 351 /* XXX where are CR26, CR27, CR29, CR31? */ 352 SIG_PROTECT(tf_cr28); /* CR28 */ 353 SIG_PROTECT(tf_cr30); /* CR30 */ 354 #undef SIG_PROTECT 355 356 /* The bulk copy. */ 357 *tf = tstate.ss_frame; 358 } 359 360 /* 361 * Restore the original FP context 362 */ 363 /* XXX fredette */ 364 365 restore: 366 /* 367 * Restore the user supplied information. 368 * This should be at the last so that the error (EINVAL) 369 * is reported to the sigreturn caller, not to the 370 * jump destination. 371 */ 372 373 tf->tf_sp = scp->sc_sp; 374 /* XXX should we be doing the space registers? */ 375 tf->tf_iisq_head = scp->sc_pcsqh; 376 tf->tf_iioq_head = scp->sc_pcoqh | HPPA_PC_PRIV_USER; 377 tf->tf_iisq_tail = scp->sc_pcsqt; 378 tf->tf_iioq_tail = scp->sc_pcoqt | HPPA_PC_PRIV_USER; 379 tf->tf_ipsw = scp->sc_ps; 380 381 /* Restore signal stack. */ 382 if (scp->sc_onstack & SS_ONSTACK) 383 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 384 else 385 p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; 386 387 /* Restore signal mask. */ 388 (void) sigprocmask1(p, SIG_SETMASK, &scp->sc_mask, 0); 389 390 #ifdef DEBUG 391 #if 0 /* XXX FP state */ 392 if ((sigdebug & SDB_FPSTATE) && *(char *)&tstate.ss_fpstate) 393 printf("sigreturn(%d): copied in FP state (%x) at %p\n", 394 p->p_pid, *(u_int *)&tstate.ss_fpstate, 395 &tstate.ss_fpstate); 396 #endif 397 if ((sigdebug & SDB_FOLLOW) || 398 ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) 399 printf("sigreturn(%d): returns\n", p->p_pid); 400 #endif 401 return (EJUSTRETURN); 402 } 403 404