1 /* $NetBSD: sunos_machdep.c,v 1.9 2001/06/07 17:49:51 mrg Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Matthew R. Green 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #if defined(_KERNEL_OPT) 32 #include "opt_compat_netbsd.h" 33 #endif 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/proc.h> 38 #include <sys/user.h> 39 #include <sys/kernel.h> 40 #include <sys/mount.h> 41 #include <sys/signal.h> 42 #include <sys/signalvar.h> 43 44 #include <sys/syscallargs.h> 45 #include <compat/sunos/sunos.h> 46 #include <compat/sunos/sunos_syscallargs.h> 47 48 #include <machine/frame.h> 49 #include <machine/cpu.h> 50 51 #ifdef DEBUG 52 int sunos_sigdebug = 0; 53 int sunos_sigpid = 0; 54 #define SDB_FOLLOW 0x01 55 #define SDB_KSTACK 0x02 56 #define SDB_FPSTATE 0x04 57 #endif 58 59 struct sunos_sigframe { 60 int sf_signo; /* signal number */ 61 int sf_code; /* code */ 62 struct sigcontext13 *sf_scp; /* SunOS user addr of sigcontext */ 63 int sf_addr; /* SunOS compat, always 0 for now */ 64 struct sigcontext13 sf_sc; /* actual sigcontext */ 65 }; 66 67 void 68 sunos_sendsig(catcher, sig, mask, code) 69 sig_t catcher; 70 int sig; 71 sigset_t *mask; 72 u_long code; 73 { 74 struct proc *p = curproc; 75 struct sunos_sigframe *fp; 76 struct trapframe *tf; 77 int addr, onstack, oldsp, newsp; 78 struct sunos_sigframe sf; 79 80 tf = p->p_md.md_tf; 81 oldsp = tf->tf_out[6]; 82 83 /* 84 * Compute new user stack addresses, subtract off 85 * one signal frame, and align. 86 */ 87 onstack = 88 (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 89 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 90 91 if (onstack) 92 fp = (struct sunos_sigframe *) 93 ((caddr_t)p->p_sigctx.ps_sigstk.ss_sp + p->p_sigctx.ps_sigstk.ss_size); 94 else 95 fp = (struct sunos_sigframe *)oldsp; 96 97 fp = (struct sunos_sigframe *)((int)(fp - 1) & ~7); 98 99 #ifdef DEBUG 100 if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid) 101 printf("sendsig: %s[%d] sig %d newusp %p scp %p\n", 102 p->p_comm, p->p_pid, sig, fp, &fp->sf_sc); 103 #endif 104 /* 105 * Now set up the signal frame. We build it in kernel space 106 * and then copy it out. We probably ought to just build it 107 * directly in user space.... 108 */ 109 sf.sf_signo = sig; 110 sf.sf_code = code; 111 sf.sf_scp = &fp->sf_sc; 112 sf.sf_addr = 0; /* XXX */ 113 114 /* 115 * Build the signal context to be used by sigreturn. 116 */ 117 sf.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK; 118 native_sigset_to_sigset13(mask, &sf.sf_sc.sc_mask); 119 sf.sf_sc.sc_sp = oldsp; 120 sf.sf_sc.sc_pc = tf->tf_pc; 121 sf.sf_sc.sc_npc = tf->tf_npc; 122 sf.sf_sc.sc_psr = tf->tf_psr; 123 sf.sf_sc.sc_g1 = tf->tf_global[1]; 124 sf.sf_sc.sc_o0 = tf->tf_out[0]; 125 126 /* 127 * Put the stack in a consistent state before we whack away 128 * at it. Note that write_user_windows may just dump the 129 * registers into the pcb; we need them in the process's memory. 130 * We also need to make sure that when we start the signal handler, 131 * its %i6 (%fp), which is loaded from the newly allocated stack area, 132 * joins seamlessly with the frame it was in when the signal occurred, 133 * so that the debugger and _longjmp code can back up through it. 134 */ 135 newsp = (int)fp - sizeof(struct rwindow); 136 write_user_windows(); 137 if (rwindow_save(p) || copyout((caddr_t)&sf, (caddr_t)fp, sizeof sf) || 138 suword(&((struct rwindow *)newsp)->rw_in[6], oldsp)) { 139 /* 140 * Process has trashed its stack; give it an illegal 141 * instruction to halt it in its tracks. 142 */ 143 #ifdef DEBUG 144 if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid) 145 printf("sendsig: window save or copyout error\n"); 146 #endif 147 sigexit(p, SIGILL); 148 /* NOTREACHED */ 149 } 150 #ifdef DEBUG 151 if (sunos_sigdebug & SDB_FOLLOW) 152 printf("sendsig: %s[%d] sig %d scp %p\n", 153 p->p_comm, p->p_pid, sig, &fp->sf_sc); 154 #endif 155 /* 156 * Arrange to continue execution at the code copied out in exec(). 157 * It needs the function to call in %g1, and a new stack pointer. 158 */ 159 addr = (int)catcher; /* user does his own trampolining */ 160 tf->tf_pc = addr; 161 tf->tf_npc = addr + 4; 162 tf->tf_out[6] = newsp; 163 164 /* Remember that we're now on the signal stack. */ 165 if (onstack) 166 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 167 168 #ifdef DEBUG 169 if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid) 170 printf("sendsig: about to return to catcher\n"); 171 #endif 172 } 173 174 int 175 sunos_sys_sigreturn(p, v, retval) 176 register struct proc *p; 177 void *v; 178 register_t *retval; 179 { 180 struct sunos_sys_sigreturn_args *uap = v; 181 182 return (compat_13_sys_sigreturn(p, 183 (struct compat_13_sys_sigreturn_args *)uap, retval)); 184 } 185