1/* $OpenBSD: sig_machdep.c,v 1.21 2021/10/06 15:46:03 claudio Exp $ */ 2/* $NetBSD: sig_machdep.c,v 1.22 2003/10/08 00:28:41 thorpej Exp $ */ 3 4/* 5 * Copyright (c) 1994-1998 Mark Brinicombe. 6 * Copyright (c) 1994 Brini. 7 * All rights reserved. 8 * 9 * This code is derived from software written for Brini by Mark Brinicombe 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by Mark Brinicombe 22 * for the NetBSD Project. 23 * 4. The name of the company nor the name of the author may be used to 24 * endorse or promote products derived from this software without specific 25 * prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 28 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 29 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 30 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 31 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 32 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 33 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * Machine dependant functions for kernel setup 40 * 41 * Created : 17/09/94 42 */ 43 44#include <sys/param.h> 45 46#include <sys/mount.h> /* XXX only needed by syscallargs.h */ 47#include <sys/proc.h> 48#include <sys/signal.h> 49#include <sys/signalvar.h> 50#include <sys/syscallargs.h> 51#include <sys/systm.h> 52#include <sys/user.h> 53 54#include <machine/cpu.h> 55#include <machine/frame.h> 56#include <machine/pcb.h> 57 58#include <arm/armreg.h> 59 60#include <uvm/uvm_extern.h> 61 62static __inline struct trapframe * 63process_frame(struct proc *p) 64{ 65 return p->p_addr->u_pcb.pcb_tf; 66} 67 68/* 69 * Send an interrupt to process. 70 * 71 * Stack is set up to allow sigcode to call routine, followed by 72 * syscall to sigreturn routine below. After sigreturn resets the 73 * signal mask, the stack, and the frame pointer, it returns to the 74 * user specified pc. 75 */ 76int 77sendsig(sig_t catcher, int sig, sigset_t mask, const siginfo_t *ksip, 78 int info, int onstack) 79{ 80 struct proc *p = curproc; 81 struct pcb *pcb = &p->p_addr->u_pcb; 82 struct trapframe *tf; 83 struct sigframe *fp, frame; 84 85 tf = process_frame(p); 86 87 /* Allocate space for the signal handler context. */ 88 if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && 89 !sigonstack(tf->tf_usr_sp) && onstack) 90 fp = (struct sigframe *) 91 trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size); 92 else 93 fp = (struct sigframe *)tf->tf_usr_sp; 94 95 /* make room on the stack */ 96 fp--; 97 98 /* make the stack aligned */ 99 fp = (struct sigframe *)STACKALIGN(fp); 100 101 /* Build stack frame for signal trampoline. */ 102 bzero(&frame, sizeof(frame)); 103 frame.sf_signum = sig; 104 frame.sf_sip = NULL; 105 frame.sf_scp = &fp->sf_sc; 106 frame.sf_handler = catcher; 107 108 /* Save register context. */ 109 frame.sf_sc.sc_r0 = tf->tf_r0; 110 frame.sf_sc.sc_r1 = tf->tf_r1; 111 frame.sf_sc.sc_r2 = tf->tf_r2; 112 frame.sf_sc.sc_r3 = tf->tf_r3; 113 frame.sf_sc.sc_r4 = tf->tf_r4; 114 frame.sf_sc.sc_r5 = tf->tf_r5; 115 frame.sf_sc.sc_r6 = tf->tf_r6; 116 frame.sf_sc.sc_r7 = tf->tf_r7; 117 frame.sf_sc.sc_r8 = tf->tf_r8; 118 frame.sf_sc.sc_r9 = tf->tf_r9; 119 frame.sf_sc.sc_r10 = tf->tf_r10; 120 frame.sf_sc.sc_r11 = tf->tf_r11; 121 frame.sf_sc.sc_r12 = tf->tf_r12; 122 frame.sf_sc.sc_usr_sp = tf->tf_usr_sp; 123 frame.sf_sc.sc_usr_lr = tf->tf_usr_lr; 124 frame.sf_sc.sc_svc_lr = tf->tf_svc_lr; 125 frame.sf_sc.sc_pc = tf->tf_pc; 126 frame.sf_sc.sc_spsr = tf->tf_spsr; 127 128 /* Save signal mask. */ 129 frame.sf_sc.sc_mask = mask; 130 131 /* Save FPU registers. */ 132 frame.sf_sc.sc_fpused = pcb->pcb_flags & PCB_FPU; 133 if (frame.sf_sc.sc_fpused) { 134 frame.sf_sc.sc_fpscr = pcb->pcb_fpstate.fp_scr; 135 memcpy(&frame.sf_sc.sc_fpreg, &pcb->pcb_fpstate.fp_reg, 136 sizeof(pcb->pcb_fpstate.fp_reg)); 137 pcb->pcb_flags &= ~PCB_FPU; 138 pcb->pcb_fpcpu = NULL; 139 } 140 141 if (info) { 142 frame.sf_sip = &fp->sf_si; 143 frame.sf_si = *ksip; 144 } 145 146 frame.sf_sc.sc_cookie = (long)&fp->sf_sc ^ p->p_p->ps_sigcookie; 147 if (copyout(&frame, fp, sizeof(frame)) != 0) 148 return 1; 149 150 /* 151 * Build context to run handler in. We invoke the handler 152 * directly, only returning via the trampoline. 153 */ 154 tf->tf_r0 = sig; 155 tf->tf_r1 = (register_t)frame.sf_sip; 156 tf->tf_r2 = (register_t)frame.sf_scp; 157 tf->tf_pc = (register_t)frame.sf_handler; 158 tf->tf_usr_sp = (register_t)fp; 159 160 tf->tf_usr_lr = p->p_p->ps_sigcode; 161 162 return 0; 163} 164 165/* 166 * System call to cleanup state after a signal 167 * has been taken. Reset signal mask and 168 * stack state from context left by sendsig (above). 169 * Return to previous pc and psl as specified by 170 * context left by sendsig. Check carefully to 171 * make sure that the user has not modified the 172 * psr to gain improper privileges or to cause 173 * a machine fault. 174 */ 175 176int 177sys_sigreturn(struct proc *p, void *v, register_t *retval) 178{ 179 struct sys_sigreturn_args /* { 180 syscallarg(struct sigcontext *) sigcntxp; 181 } */ *uap = v; 182 struct sigcontext ksc, *scp = SCARG(uap, sigcntxp); 183 struct pcb *pcb = &p->p_addr->u_pcb; 184 struct trapframe *tf; 185 186 if (PROC_PC(p) != p->p_p->ps_sigcoderet) { 187 sigexit(p, SIGILL); 188 return (EPERM); 189 } 190 191 if (copyin(scp, &ksc, sizeof(*scp)) != 0) 192 return (EFAULT); 193 194 if (ksc.sc_cookie != ((long)scp ^ p->p_p->ps_sigcookie)) { 195 sigexit(p, SIGILL); 196 return (EFAULT); 197 } 198 199 /* Prevent reuse of the sigcontext cookie */ 200 ksc.sc_cookie = 0; 201 (void)copyout(&ksc.sc_cookie, (caddr_t)scp + 202 offsetof(struct sigcontext, sc_cookie), sizeof (ksc.sc_cookie)); 203 204 /* 205 * Make sure the processor mode has not been tampered with and 206 * interrupts have not been disabled. 207 */ 208 if ((ksc.sc_spsr & PSR_MODE) != PSR_USR32_MODE || 209 (ksc.sc_spsr & (PSR_I | PSR_F)) != 0) 210 return (EINVAL); 211 212 /* Restore register context. */ 213 tf = process_frame(p); 214 tf->tf_r0 = ksc.sc_r0; 215 tf->tf_r1 = ksc.sc_r1; 216 tf->tf_r2 = ksc.sc_r2; 217 tf->tf_r3 = ksc.sc_r3; 218 tf->tf_r4 = ksc.sc_r4; 219 tf->tf_r5 = ksc.sc_r5; 220 tf->tf_r6 = ksc.sc_r6; 221 tf->tf_r7 = ksc.sc_r7; 222 tf->tf_r8 = ksc.sc_r8; 223 tf->tf_r9 = ksc.sc_r9; 224 tf->tf_r10 = ksc.sc_r10; 225 tf->tf_r11 = ksc.sc_r11; 226 tf->tf_r12 = ksc.sc_r12; 227 tf->tf_usr_sp = ksc.sc_usr_sp; 228 tf->tf_usr_lr = ksc.sc_usr_lr; 229 tf->tf_svc_lr = ksc.sc_svc_lr; 230 tf->tf_pc = ksc.sc_pc; 231 tf->tf_spsr = ksc.sc_spsr; 232 233 /* Restore signal mask. */ 234 p->p_sigmask = ksc.sc_mask & ~sigcantmask; 235 236 /* Restore FPU registers. */ 237 if (ksc.sc_fpused) { 238 pcb->pcb_fpstate.fp_scr = ksc.sc_fpscr; 239 memcpy(&pcb->pcb_fpstate.fp_reg, &ksc.sc_fpreg, 240 sizeof(pcb->pcb_fpstate.fp_reg)); 241 pcb->pcb_flags |= PCB_FPU; 242 pcb->pcb_fpcpu = NULL; 243 } else { 244 pcb->pcb_flags &= ~PCB_FPU; 245 pcb->pcb_fpcpu = NULL; 246 } 247 248 return (EJUSTRETURN); 249} 250