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