1 /* $NetBSD: sunos_machdep.c,v 1.16 2002/07/04 23:32:07 thorpej 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 #ifdef _KERNEL_OPT 32 #include "opt_ddb.h" 33 #endif 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/proc.h> 38 #include <sys/namei.h> 39 #include <sys/user.h> 40 #include <sys/filedesc.h> 41 #include <sys/ioctl.h> 42 #include <sys/mount.h> 43 #include <sys/kernel.h> 44 #include <sys/signal.h> 45 #include <sys/signalvar.h> 46 #include <sys/malloc.h> 47 48 #include <sys/syscallargs.h> 49 #include <compat/sunos/sunos.h> 50 #include <compat/sunos/sunos_syscallargs.h> 51 52 #include <machine/frame.h> 53 #include <machine/cpu.h> 54 55 #ifdef DEBUG 56 #include <sparc64/sparc64/sigdebug.h> 57 #endif 58 59 struct sunos_sigcontext { 60 int sc_onstack; /* sigstack state to restore */ 61 int sc_mask; /* signal mask to restore (old style) */ 62 /* begin machine dependent portion */ 63 int sc_sp; /* %sp to restore */ 64 int sc_pc; /* pc to restore */ 65 int sc_npc; /* npc to restore */ 66 int sc_psr; /* pstate to restore */ 67 int sc_g1; /* %g1 to restore */ 68 int sc_o0; /* %o0 to restore */ 69 }; 70 71 struct sunos_sigframe { 72 int sf_signo; /* signal number */ 73 int sf_code; /* code */ 74 u_int32_t sf_scp; /* SunOS user addr of sigcontext */ 75 int sf_addr; /* SunOS compat, always 0 for now */ 76 struct sunos_sigcontext sf_sc; /* actual sigcontext */ 77 }; 78 79 void 80 sunos_sendsig(sig, mask, code) 81 int sig; 82 sigset_t *mask; 83 u_long code; 84 { 85 register struct proc *p = curproc; 86 register struct sunos_sigframe *fp; 87 register struct trapframe64 *tf; 88 register int addr, onstack; 89 struct rwindow32 *kwin, *oldsp, *newsp; 90 sig_t catcher = SIGACTION(p, sig).sa_handler; 91 struct sunos_sigframe sf; 92 93 tf = p->p_md.md_tf; 94 /* Need to attempt to zero extend this 32-bit pointer */ 95 oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6]; 96 /* 97 * Compute new user stack addresses, subtract off 98 * one signal frame, and align. 99 */ 100 onstack = 101 (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 102 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 103 104 if (onstack) 105 fp = (struct sunos_sigframe *)((char *)p->p_sigctx.ps_sigstk.ss_sp + 106 p->p_sigctx.ps_sigstk.ss_size); 107 else 108 fp = (struct sunos_sigframe *)oldsp; 109 fp = (struct sunos_sigframe *)((long)(fp - 1) & ~7); 110 111 #ifdef DEBUG 112 sigpid = p->p_pid; 113 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { 114 printf("sunos_sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n", 115 p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp); 116 #ifdef DDB 117 if (sigdebug & SDB_DDB) Debugger(); 118 #endif 119 } 120 #endif 121 /* 122 * Now set up the signal frame. We build it in kernel space 123 * and then copy it out. We probably ought to just build it 124 * directly in user space.... 125 */ 126 sf.sf_signo = sig; 127 sf.sf_code = code; 128 sf.sf_scp = (u_long)&fp->sf_sc; 129 sf.sf_addr = 0; /* XXX */ 130 131 /* 132 * Build the signal context to be used by sigreturn. 133 */ 134 sf.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK; 135 native_sigset_to_sigset13(mask, &sf.sf_sc.sc_mask); 136 sf.sf_sc.sc_sp = (long)oldsp; 137 sf.sf_sc.sc_pc = tf->tf_pc; 138 sf.sf_sc.sc_npc = tf->tf_npc; 139 sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */ 140 sf.sf_sc.sc_g1 = tf->tf_global[1]; 141 sf.sf_sc.sc_o0 = tf->tf_out[0]; 142 143 /* 144 * Put the stack in a consistent state before we whack away 145 * at it. Note that write_user_windows may just dump the 146 * registers into the pcb; we need them in the process's memory. 147 * We also need to make sure that when we start the signal handler, 148 * its %i6 (%fp), which is loaded from the newly allocated stack area, 149 * joins seamlessly with the frame it was in when the signal occurred, 150 * so that the debugger and _longjmp code can back up through it. 151 */ 152 newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32)); 153 write_user_windows(); 154 #ifdef DEBUG 155 if ((sigdebug & SDB_KSTACK)) 156 printf("sunos_sendsig: saving sf to %p, setting stack pointer %p to %p\n", 157 fp, &(((struct rwindow32 *)newsp)->rw_in[6]), oldsp); 158 #endif 159 kwin = (struct rwindow32 *)(((caddr_t)tf)-CCFSZ); 160 if (rwindow_save(p) || 161 copyout((caddr_t)&sf, (caddr_t)fp, sizeof sf) || 162 suword(&(((struct rwindow32 *)newsp)->rw_in[6]), (u_long)oldsp)) { 163 /* 164 * Process has trashed its stack; give it an illegal 165 * instruction to halt it in its tracks. 166 */ 167 #ifdef DEBUG 168 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 169 printf("sunos_sendsig: window save or copyout error\n"); 170 printf("sunos_sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig); 171 #ifdef DDB 172 if (sigdebug & SDB_DDB) Debugger(); 173 #endif 174 #endif 175 sigexit(p, SIGILL); 176 /* NOTREACHED */ 177 } 178 179 #ifdef DEBUG 180 if (sigdebug & SDB_FOLLOW) { 181 printf("sunos_sendsig: %s[%d] sig %d scp %p\n", 182 p->p_comm, p->p_pid, sig, &fp->sf_sc); 183 } 184 #endif 185 /* 186 * Arrange to continue execution at the code copied out in exec(). 187 * It needs the function to call in %g1, and a new stack pointer. 188 */ 189 addr = (long)catcher; /* user does his own trampolining */ 190 tf->tf_pc = addr; 191 tf->tf_npc = addr + 4; 192 tf->tf_out[6] = (u_int64_t)(u_int)(u_long)newsp; 193 #ifdef DEBUG 194 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { 195 printf("sunos_sendsig: about to return to catcher %p thru %p\n", 196 catcher, (void *)(u_long)addr); 197 #ifdef DDB 198 if (sigdebug & SDB_DDB) Debugger(); 199 #endif 200 } 201 #endif 202 } 203 204 int 205 sunos_sys_sigreturn(p, v, retval) 206 register struct proc *p; 207 void *v; 208 register_t *retval; 209 { 210 struct sunos_sys_sigreturn_args /* 211 syscallarg(struct sigcontext13 *) sigcntxp; 212 } */ *uap = v; 213 struct sunos_sigcontext sc, *scp; 214 sigset_t mask; 215 struct trapframe64 *tf; 216 217 /* First ensure consistent stack state (see sendsig). */ 218 write_user_windows(); 219 if (rwindow_save(p)) 220 sigexit(p, SIGILL); 221 #ifdef DEBUG 222 if (sigdebug & SDB_FOLLOW) { 223 printf("sunos_sigreturn: %s[%d], sigcntxp %p\n", 224 p->p_comm, p->p_pid, SCARG(uap, sigcntxp)); 225 #ifdef DDB 226 if (sigdebug & SDB_DDB) Debugger(); 227 #endif 228 } 229 #endif 230 231 scp = (struct sunos_sigcontext *)SCARG(uap, sigcntxp); 232 if ((vaddr_t)scp & 3 || (copyin((caddr_t)scp, &sc, sizeof sc) != 0)) 233 return (EFAULT); 234 scp = ≻ 235 236 tf = p->p_md.md_tf; 237 /* 238 * Only the icc bits in the psr are used, so it need not be 239 * verified. pc and npc must be multiples of 4. This is all 240 * that is required; if it holds, just do it. 241 */ 242 if (((scp->sc_pc | scp->sc_npc) & 3) != 0 || scp->sc_pc == 0 || scp->sc_npc == 0) 243 #ifdef DEBUG 244 { 245 printf("sunos_sigreturn: pc %p or npc %p invalid\n", (void *)(u_long)scp->sc_pc, (void *)(u_long)scp->sc_npc); 246 #ifdef DDB 247 Debugger(); 248 #endif 249 return (EINVAL); 250 } 251 #endif 252 return (EINVAL); 253 /* take only psr ICC field */ 254 tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(scp->sc_psr); 255 tf->tf_pc = scp->sc_pc; 256 tf->tf_npc = scp->sc_npc; 257 tf->tf_global[1] = scp->sc_g1; 258 tf->tf_out[0] = scp->sc_o0; 259 tf->tf_out[6] = scp->sc_sp; 260 #ifdef DEBUG 261 if (sigdebug & SDB_FOLLOW) { 262 printf("sunos_sigreturn: return trapframe pc=%p sp=%p tstate=%llx\n", 263 (void *)(u_long)tf->tf_pc, (void *)(u_long)tf->tf_out[6], (unsigned long long)tf->tf_tstate); 264 #ifdef DDB 265 if (sigdebug & SDB_DDB) Debugger(); 266 #endif 267 } 268 #endif 269 270 if (scp->sc_onstack & SS_ONSTACK) 271 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 272 else 273 p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; 274 275 /* Restore signal mask */ 276 native_sigset13_to_sigset(&scp->sc_mask, &mask); 277 (void) sigprocmask1(p, SIG_SETMASK, &mask, 0); 278 279 return (EJUSTRETURN); 280 } 281