1 /* $NetBSD: sig_machdep.c,v 1.15 2002/09/15 20:11:55 skrll Exp $ */ 2 3 /* 4 * Copyright (c) 1994-1998 Mark Brinicombe. 5 * Copyright (c) 1994 Brini. 6 * All rights reserved. 7 * 8 * This code is derived from software written for Brini by Mark Brinicombe 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 Mark Brinicombe 21 * for the NetBSD Project. 22 * 4. The name of the company nor the name of the author may be used to 23 * endorse or promote products derived from this software without specific 24 * prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 30 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * Machine dependant functions for kernel setup 39 * 40 * Created : 17/09/94 41 */ 42 43 #include "opt_compat_netbsd.h" 44 45 #include <sys/param.h> 46 47 __KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.15 2002/09/15 20:11:55 skrll Exp $"); 48 49 #include <sys/mount.h> /* XXX only needed by syscallargs.h */ 50 #include <sys/proc.h> 51 #include <sys/signal.h> 52 #include <sys/syscallargs.h> 53 #include <sys/systm.h> 54 #include <sys/user.h> 55 56 #include <arm/armreg.h> 57 58 #include <machine/cpu.h> 59 #include <machine/frame.h> 60 #include <machine/pcb.h> 61 #ifndef acorn26 62 #include <arm/cpufunc.h> 63 #endif 64 65 static __inline struct trapframe * 66 process_frame(struct proc *p) 67 { 68 69 return p->p_addr->u_pcb.pcb_tf; 70 } 71 72 /* 73 * Send an interrupt to process. 74 * 75 * Stack is set up to allow sigcode stored 76 * in u. to call routine, followed by kcall 77 * to sigreturn routine below. After sigreturn 78 * resets the signal mask, the stack, and the 79 * frame pointer, it returns to the user specified pc. 80 */ 81 void 82 sendsig(int sig, sigset_t *mask, u_long code) 83 { 84 struct proc *p = curproc; 85 struct sigacts *ps = p->p_sigacts; 86 struct trapframe *tf; 87 struct sigframe *fp, frame; 88 int onstack; 89 sig_t catcher = SIGACTION(p, sig).sa_handler; 90 91 tf = process_frame(p); 92 93 /* Do we need to jump onto the signal stack? */ 94 onstack = 95 (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 96 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 97 98 /* Allocate space for the signal handler context. */ 99 if (onstack) 100 fp = (struct sigframe *)((caddr_t)p->p_sigctx.ps_sigstk.ss_sp + 101 p->p_sigctx.ps_sigstk.ss_size); 102 else 103 fp = (struct sigframe *)tf->tf_usr_sp; 104 fp--; 105 (u_int)fp = STACKALIGN(fp); 106 107 /* Save register context. */ 108 frame.sf_sc.sc_r0 = tf->tf_r0; 109 frame.sf_sc.sc_r1 = tf->tf_r1; 110 frame.sf_sc.sc_r2 = tf->tf_r2; 111 frame.sf_sc.sc_r3 = tf->tf_r3; 112 frame.sf_sc.sc_r4 = tf->tf_r4; 113 frame.sf_sc.sc_r5 = tf->tf_r5; 114 frame.sf_sc.sc_r6 = tf->tf_r6; 115 frame.sf_sc.sc_r7 = tf->tf_r7; 116 frame.sf_sc.sc_r8 = tf->tf_r8; 117 frame.sf_sc.sc_r9 = tf->tf_r9; 118 frame.sf_sc.sc_r10 = tf->tf_r10; 119 frame.sf_sc.sc_r11 = tf->tf_r11; 120 frame.sf_sc.sc_r12 = tf->tf_r12; 121 frame.sf_sc.sc_usr_sp = tf->tf_usr_sp; 122 frame.sf_sc.sc_usr_lr = tf->tf_usr_lr; 123 frame.sf_sc.sc_svc_lr = tf->tf_svc_lr; 124 frame.sf_sc.sc_pc = tf->tf_pc; 125 frame.sf_sc.sc_spsr = tf->tf_spsr; 126 127 /* Save signal stack. */ 128 frame.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK; 129 130 /* Save signal mask. */ 131 frame.sf_sc.sc_mask = *mask; 132 133 #ifdef COMPAT_13 134 /* 135 * XXX We always have to save an old style signal mask because 136 * XXX we might be delivering a signal to a process which will 137 * XXX escape from the signal in a non-standard way and invoke 138 * XXX sigreturn() directly. 139 */ 140 native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13); 141 #endif 142 143 if (copyout(&frame, fp, sizeof(frame)) != 0) { 144 /* 145 * Process has trashed its stack; give it an illegal 146 * instruction to halt it in its tracks. 147 */ 148 sigexit(p, SIGILL); 149 /* NOTREACHED */ 150 } 151 152 /* 153 * Build context to run handler in. We invoke the handler 154 * directly, only returning via the trampoline. Note the 155 * trampoline version numbers are coordinated with machine- 156 * dependent code in libc. 157 */ 158 switch (ps->sa_sigdesc[sig].sd_vers) { 159 #if 1 /* COMPAT_16 */ 160 case 0: /* legacy on-stack sigtramp */ 161 tf->tf_r0 = sig; 162 tf->tf_r1 = code; 163 tf->tf_r2 = (int)&fp->sf_sc; 164 tf->tf_pc = (int)catcher; 165 tf->tf_usr_sp = (int)fp; 166 tf->tf_usr_lr = (int)p->p_sigctx.ps_sigcode; 167 #ifndef acorn26 168 /* XXX This should not be needed. */ 169 cpu_icache_sync_all(); 170 #endif 171 break; 172 #endif /* COMPAT_16 */ 173 174 case 1: 175 tf->tf_r0 = sig; 176 tf->tf_r1 = code; 177 tf->tf_r2 = (int)&fp->sf_sc; 178 tf->tf_pc = (int)catcher; 179 tf->tf_usr_sp = (int)fp; 180 tf->tf_usr_lr = (int)ps->sa_sigdesc[sig].sd_tramp; 181 break; 182 183 default: 184 /* Don't know what trampoline version; kill it. */ 185 sigexit(p, SIGILL); 186 } 187 188 /* Remember that we're now on the signal stack. */ 189 if (onstack) 190 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 191 } 192 193 194 /* 195 * System call to cleanup state after a signal 196 * has been taken. Reset signal mask and 197 * stack state from context left by sendsig (above). 198 * Return to previous pc and psl as specified by 199 * context left by sendsig. Check carefully to 200 * make sure that the user has not modified the 201 * psr to gain improper privileges or to cause 202 * a machine fault. 203 */ 204 int 205 sys___sigreturn14(struct proc *p, void *v, register_t *retval) 206 { 207 struct sys___sigreturn14_args /* { 208 syscallarg(struct sigcontext *) sigcntxp; 209 } */ *uap = v; 210 struct sigcontext *scp, context; 211 struct trapframe *tf; 212 213 /* 214 * The trampoline code hands us the context. 215 * It is unsafe to keep track of it ourselves, in the event that a 216 * program jumps out of a signal handler. 217 */ 218 scp = SCARG(uap, sigcntxp); 219 if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0) 220 return (EFAULT); 221 222 /* 223 * Make sure the processor mode has not been tampered with and 224 * interrupts have not been disabled. 225 */ 226 #ifdef __PROG32 227 if ((context.sc_spsr & PSR_MODE) != PSR_USR32_MODE || 228 (context.sc_spsr & (I32_bit | F32_bit)) != 0) 229 return (EINVAL); 230 #else /* __PROG26 */ 231 if ((context.sc_pc & R15_MODE) != R15_MODE_USR || 232 (context.sc_pc & (R15_IRQ_DISABLE | R15_FIQ_DISABLE)) != 0) 233 return EINVAL; 234 #endif 235 236 /* Restore register context. */ 237 tf = process_frame(p); 238 tf->tf_r0 = context.sc_r0; 239 tf->tf_r1 = context.sc_r1; 240 tf->tf_r2 = context.sc_r2; 241 tf->tf_r3 = context.sc_r3; 242 tf->tf_r4 = context.sc_r4; 243 tf->tf_r5 = context.sc_r5; 244 tf->tf_r6 = context.sc_r6; 245 tf->tf_r7 = context.sc_r7; 246 tf->tf_r8 = context.sc_r8; 247 tf->tf_r9 = context.sc_r9; 248 tf->tf_r10 = context.sc_r10; 249 tf->tf_r11 = context.sc_r11; 250 tf->tf_r12 = context.sc_r12; 251 tf->tf_usr_sp = context.sc_usr_sp; 252 tf->tf_usr_lr = context.sc_usr_lr; 253 tf->tf_svc_lr = context.sc_svc_lr; 254 tf->tf_pc = context.sc_pc; 255 tf->tf_spsr = context.sc_spsr; 256 257 /* Restore signal stack. */ 258 if (context.sc_onstack & SS_ONSTACK) 259 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 260 else 261 p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; 262 263 /* Restore signal mask. */ 264 (void) sigprocmask1(p, SIG_SETMASK, &context.sc_mask, 0); 265 266 return (EJUSTRETURN); 267 } 268