1 /* $NetBSD: sig_machdep.c,v 1.11 2002/03/24 16:10:11 bjh21 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.11 2002/03/24 16:10:11 bjh21 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(sig_t catcher, int sig, sigset_t *mask, u_long code) 83 { 84 struct proc *p = curproc; 85 struct trapframe *tf; 86 struct sigframe *fp, frame; 87 int onstack; 88 89 tf = process_frame(p); 90 91 /* Do we need to jump onto the signal stack? */ 92 onstack = 93 (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 94 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 95 96 /* Allocate space for the signal handler context. */ 97 if (onstack) 98 fp = (struct sigframe *)((caddr_t)p->p_sigctx.ps_sigstk.ss_sp + 99 p->p_sigctx.ps_sigstk.ss_size); 100 else 101 fp = (struct sigframe *)tf->tf_usr_sp; 102 fp--; 103 (u_int)fp = STACKALIGN(fp); 104 105 /* Build stack frame for signal trampoline. */ 106 frame.sf_signum = sig; 107 frame.sf_code = code; 108 frame.sf_scp = &fp->sf_sc; 109 frame.sf_handler = catcher; 110 111 /* Save register context. */ 112 frame.sf_sc.sc_r0 = tf->tf_r0; 113 frame.sf_sc.sc_r1 = tf->tf_r1; 114 frame.sf_sc.sc_r2 = tf->tf_r2; 115 frame.sf_sc.sc_r3 = tf->tf_r3; 116 frame.sf_sc.sc_r4 = tf->tf_r4; 117 frame.sf_sc.sc_r5 = tf->tf_r5; 118 frame.sf_sc.sc_r6 = tf->tf_r6; 119 frame.sf_sc.sc_r7 = tf->tf_r7; 120 frame.sf_sc.sc_r8 = tf->tf_r8; 121 frame.sf_sc.sc_r9 = tf->tf_r9; 122 frame.sf_sc.sc_r10 = tf->tf_r10; 123 frame.sf_sc.sc_r11 = tf->tf_r11; 124 frame.sf_sc.sc_r12 = tf->tf_r12; 125 frame.sf_sc.sc_usr_sp = tf->tf_usr_sp; 126 frame.sf_sc.sc_usr_lr = tf->tf_usr_lr; 127 frame.sf_sc.sc_svc_lr = tf->tf_svc_lr; 128 frame.sf_sc.sc_pc = tf->tf_pc; 129 frame.sf_sc.sc_spsr = tf->tf_spsr; 130 131 /* Save signal stack. */ 132 frame.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK; 133 134 /* Save signal mask. */ 135 frame.sf_sc.sc_mask = *mask; 136 137 #ifdef COMPAT_13 138 /* 139 * XXX We always have to save an old style signal mask because 140 * XXX we might be delivering a signal to a process which will 141 * XXX escape from the signal in a non-standard way and invoke 142 * XXX sigreturn() directly. 143 */ 144 native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13); 145 #endif 146 147 if (copyout(&frame, fp, sizeof(frame)) != 0) { 148 /* 149 * Process has trashed its stack; give it an illegal 150 * instruction to halt it in its tracks. 151 */ 152 sigexit(p, SIGILL); 153 /* NOTREACHED */ 154 } 155 156 /* 157 * Build context to run handler in. 158 */ 159 tf->tf_r0 = frame.sf_signum; 160 tf->tf_r1 = frame.sf_code; 161 tf->tf_r2 = (int)frame.sf_scp; 162 tf->tf_r3 = (int)frame.sf_handler; 163 tf->tf_usr_sp = (int)fp; 164 tf->tf_pc = (int)p->p_sigctx.ps_sigcode; 165 #ifndef acorn26 166 /* XXX This should not be needed. */ 167 cpu_icache_sync_all(); 168 #endif 169 170 /* Remember that we're now on the signal stack. */ 171 if (onstack) 172 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 173 } 174 175 176 /* 177 * System call to cleanup state after a signal 178 * has been taken. Reset signal mask and 179 * stack state from context left by sendsig (above). 180 * Return to previous pc and psl as specified by 181 * context left by sendsig. Check carefully to 182 * make sure that the user has not modified the 183 * psr to gain improper privileges or to cause 184 * a machine fault. 185 */ 186 int 187 sys___sigreturn14(struct proc *p, void *v, register_t *retval) 188 { 189 struct sys___sigreturn14_args /* { 190 syscallarg(struct sigcontext *) sigcntxp; 191 } */ *uap = v; 192 struct sigcontext *scp, context; 193 struct trapframe *tf; 194 195 /* 196 * The trampoline code hands us the context. 197 * It is unsafe to keep track of it ourselves, in the event that a 198 * program jumps out of a signal handler. 199 */ 200 scp = SCARG(uap, sigcntxp); 201 if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0) 202 return (EFAULT); 203 204 /* 205 * Make sure the processor mode has not been tampered with and 206 * interrupts have not been disabled. 207 */ 208 #ifdef __PROG32 209 if ((context.sc_spsr & PSR_MODE) != PSR_USR32_MODE || 210 (context.sc_spsr & (I32_bit | F32_bit)) != 0) 211 return (EINVAL); 212 #else /* __PROG26 */ 213 if ((context.sc_pc & R15_MODE) != R15_MODE_USR || 214 (context.sc_pc & (R15_IRQ_DISABLE | R15_FIQ_DISABLE)) != 0) 215 return EINVAL; 216 #endif 217 218 /* Restore register context. */ 219 tf = process_frame(p); 220 tf->tf_r0 = context.sc_r0; 221 tf->tf_r1 = context.sc_r1; 222 tf->tf_r2 = context.sc_r2; 223 tf->tf_r3 = context.sc_r3; 224 tf->tf_r4 = context.sc_r4; 225 tf->tf_r5 = context.sc_r5; 226 tf->tf_r6 = context.sc_r6; 227 tf->tf_r7 = context.sc_r7; 228 tf->tf_r8 = context.sc_r8; 229 tf->tf_r9 = context.sc_r9; 230 tf->tf_r10 = context.sc_r10; 231 tf->tf_r11 = context.sc_r11; 232 tf->tf_r12 = context.sc_r12; 233 tf->tf_usr_sp = context.sc_usr_sp; 234 tf->tf_usr_lr = context.sc_usr_lr; 235 tf->tf_svc_lr = context.sc_svc_lr; 236 tf->tf_pc = context.sc_pc; 237 tf->tf_spsr = context.sc_spsr; 238 239 /* Restore signal stack. */ 240 if (context.sc_onstack & SS_ONSTACK) 241 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 242 else 243 p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; 244 245 /* Restore signal mask. */ 246 (void) sigprocmask1(p, SIG_SETMASK, &context.sc_mask, 0); 247 248 return (EJUSTRETURN); 249 } 250