1/* $OpenBSD: sig_machdep.c,v 1.31 2021/10/06 15:46:03 claudio Exp $ */ 2/* 3 * Copyright (c) 2014 Miodrag Vallat. 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17/* 18 * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr. 19 * Copyright (c) 1996 Nivas Madhur 20 * All rights reserved. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the above copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 3. All advertising materials mentioning features or use of this software 31 * must display the following acknowledgement: 32 * This product includes software developed by Nivas Madhur. 33 * 4. The name of the author may not be used to endorse or promote products 34 * derived from this software without specific prior written permission 35 * 36 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 37 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 39 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 40 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 42 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 43 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 44 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 45 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 46 * 47 */ 48/* 49 * Mach Operating System 50 * Copyright (c) 1993-1991 Carnegie Mellon University 51 * Copyright (c) 1991 OMRON Corporation 52 * All Rights Reserved. 53 * 54 * Permission to use, copy, modify and distribute this software and its 55 * documentation is hereby granted, provided that both the copyright 56 * notice and this permission notice appear in all copies of the 57 * software, derivative works or modified versions, and any portions 58 * thereof, and that both notices appear in supporting documentation. 59 * 60 */ 61 62#include <sys/param.h> 63#include <sys/systm.h> 64#include <sys/signalvar.h> 65#include <sys/kernel.h> 66#include <sys/proc.h> 67#include <sys/mount.h> 68#include <sys/syscallargs.h> 69#include <sys/errno.h> 70 71#include <machine/reg.h> 72#ifdef M88100 73#include <machine/m88100.h> 74#include <machine/trap.h> 75#endif 76 77#include <uvm/uvm_extern.h> 78 79vaddr_t local_stack_frame(struct trapframe *, vaddr_t, size_t); 80 81struct sigstate { 82 int ss_flags; /* which of the following are valid */ 83 struct trapframe ss_frame; /* original exception frame */ 84}; 85 86/* 87 * WARNING: sigcode() in subr.s assumes sf_scp is the first field of the 88 * sigframe. 89 */ 90struct sigframe { 91 struct sigcontext *sf_scp; /* context ptr for handler */ 92 struct sigcontext sf_sc; /* actual context */ 93 siginfo_t sf_si; 94}; 95 96#ifdef DEBUG 97int sigdebug = 0; 98pid_t sigpid = 0; 99#define SDB_FOLLOW 0x01 100#define SDB_KSTACK 0x02 101#endif 102 103/* 104 * Send an interrupt to process. 105 */ 106int 107sendsig(sig_t catcher, int sig, sigset_t mask, const siginfo_t *ksip, 108 int info, int onstack) 109{ 110 struct proc *p = curproc; 111 struct trapframe *tf; 112 struct sigframe *fp; 113 size_t fsize; 114 struct sigframe sf; 115 vaddr_t addr; 116 117 tf = p->p_md.md_tf; 118 119 if (info) 120 fsize = sizeof(struct sigframe); 121 else 122 fsize = offsetof(struct sigframe, sf_si); 123 124 /* 125 * Allocate space for the signal handler context. 126 */ 127 if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && 128 !sigonstack(tf->tf_r[31]) && onstack) { 129 addr = local_stack_frame(tf, 130 trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size), 131 fsize); 132 } else 133 addr = local_stack_frame(tf, tf->tf_r[31], fsize); 134 135 fp = (struct sigframe *)addr; 136 137 /* 138 * Build the signal context to be used by sigreturn. 139 */ 140 bzero(&sf, fsize); 141 sf.sf_scp = &fp->sf_sc; 142 sf.sf_sc.sc_mask = mask; 143 sf.sf_sc.sc_cookie = (long)sf.sf_scp ^ p->p_p->ps_sigcookie; 144 145 if (info) 146 sf.sf_si = *ksip; 147 148 /* 149 * Copy the whole user context into signal context that we 150 * are building. 151 */ 152 bcopy((const void *)&tf->tf_regs, (void *)&sf.sf_sc.sc_regs, 153 sizeof(sf.sf_sc.sc_regs)); 154 155 if (copyout((caddr_t)&sf, (caddr_t)fp, fsize)) 156 return 1; 157 158 /* 159 * Set up registers for the signal handler invocation. 160 */ 161 tf->tf_r[1] = p->p_p->ps_sigcode; /* return to sigcode */ 162 tf->tf_r[2] = sig; /* first arg is signo */ 163 tf->tf_r[3] = info ? (vaddr_t)&fp->sf_si : 0; 164 tf->tf_r[4] = (vaddr_t)&fp->sf_sc; 165 tf->tf_r[31] = (vaddr_t)fp; 166 addr = (vaddr_t)catcher; /* and resume in the handler */ 167#ifdef M88100 168 if (CPU_IS88100) { 169 tf->tf_snip = (addr & NIP_ADDR) | NIP_V; 170 tf->tf_sfip = (tf->tf_snip + 4) | FIP_V; 171 } 172#endif 173#ifdef M88110 174 if (CPU_IS88110) 175 tf->tf_exip = (addr & XIP_ADDR); 176#endif 177 178#ifdef DEBUG 179 if ((sigdebug & SDB_FOLLOW) || 180 ((sigdebug & SDB_KSTACK) && p->p_p->ps_pid == sigpid)) 181 printf("sendsig(%d): sig %d returns\n", p->p_p->ps_pid, sig); 182#endif 183 184 return 0; 185} 186 187/* 188 * System call to cleanup state after a signal has been taken. Reset signal 189 * mask and stack state from context left by sendsig (above). Return to 190 * previous pc and psl as specified by context left by sendsig. Check 191 * carefully to make sure that the user has not modified the psl to gain 192 * improper privileges or to cause a machine fault. 193 */ 194int 195sys_sigreturn(struct proc *p, void *v, register_t *retval) 196{ 197 struct sys_sigreturn_args /* { 198 syscallarg(struct sigcontext *) sigcntxp; 199 } */ *uap = v; 200 struct sigcontext ksc, *scp = SCARG(uap, sigcntxp); 201 struct trapframe *tf; 202 int error; 203 vaddr_t pc; 204 205 tf = p->p_md.md_tf; 206 207 /* 208 * This is simpler than PROC_PC, assuming XIP is always valid 209 * on 88100, and doesn't have a delay slot on 88110 210 * (which is the status we expect from the signal code). 211 */ 212 pc = CPU_IS88110 ? tf->tf_regs.exip : tf->tf_regs.sxip ^ XIP_V; 213 if (pc != p->p_p->ps_sigcoderet) { 214 sigexit(p, SIGILL); 215 return (EPERM); 216 } 217 218 if (((vaddr_t)scp & 3) != 0) 219 return (EFAULT); 220 221 if ((error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(*scp)))) 222 return (error); 223 224 if (ksc.sc_cookie != ((long)scp ^ p->p_p->ps_sigcookie)) { 225 sigexit(p, SIGILL); 226 return (EFAULT); 227 } 228 229 /* Prevent reuse of the sigcontext cookie */ 230 ksc.sc_cookie = 0; 231 (void)copyout(&ksc.sc_cookie, (caddr_t)scp + 232 offsetof(struct sigcontext, sc_cookie), sizeof (ksc.sc_cookie)); 233 234 if ((((struct reg *)&ksc.sc_regs)->epsr ^ tf->tf_regs.epsr) & 235 PSR_USERSTATIC) 236 return (EINVAL); 237 238 bcopy((const void *)&ksc.sc_regs, (caddr_t)&tf->tf_regs, 239 sizeof(ksc.sc_regs)); 240 241 /* 242 * Restore the user supplied information 243 */ 244 p->p_sigmask = ksc.sc_mask & ~sigcantmask; 245 246#ifdef M88100 247 if (CPU_IS88100) { 248 /* 249 * If we are returning from a signal handler triggered by 250 * a data access exception, the interrupted access has 251 * never been performed, and will not be reissued upon 252 * returning to userland. 253 * 254 * We can't simply call data_access_emulation(), for 255 * it might fault again. Instead, we invoke trap() 256 * again, which will either trigger another signal, 257 * or end up invoking data_access_emulation if safe. 258 */ 259 if (ISSET(tf->tf_dmt0, DMT_VALID)) 260 m88100_trap(T_DATAFLT, tf); 261 } 262#endif 263 264 /* 265 * We really want to return to the instruction pointed to by the 266 * sigcontext. However, due to the way exceptions work on 88110, 267 * returning EJUSTRETURN will cause m88110_syscall() to skip one 268 * instruction. We avoid this by returning ERESTART, which will 269 * indeed cause the instruction pointed to by exip to be run 270 * again. 271 */ 272 return CPU_IS88100 ? EJUSTRETURN : ERESTART; 273} 274 275/* 276 * Find out a safe place on the process' stack to put the sigframe struct. 277 * While on 88110, this is straightforward, on 88100 we need to be 278 * careful and not stomp over potential uncompleted data accesses, which 279 * we will want to be able to perform upon sigreturn(). 280 */ 281vaddr_t 282local_stack_frame(struct trapframe *tf, vaddr_t tos, size_t fsize) 283{ 284 vaddr_t frame; 285 286 frame = (tos - fsize) & ~_STACKALIGNBYTES; 287 288#ifdef M88100 289 if (CPU_IS88100 && ISSET(tf->tf_dmt0, DMT_VALID)) { 290 for (;;) { 291 tos = frame + fsize; 292 if (/* ISSET(tf->tf_dmt0, DMT_VALID) && */ 293 tf->tf_dma0 >= frame && tf->tf_dma0 < tos) { 294 frame = (tf->tf_dma0 - fsize) & 295 ~_STACKALIGNBYTES; 296 continue; 297 } 298 if (ISSET(tf->tf_dmt1, DMT_VALID) && 299 tf->tf_dma1 >= frame && tf->tf_dma1 < tos) { 300 frame = (tf->tf_dma1 - fsize) & 301 ~_STACKALIGNBYTES; 302 continue; 303 } 304 if (ISSET(tf->tf_dmt2, DMT_VALID) && 305 tf->tf_dma2 >= frame && tf->tf_dma2 < tos) { 306 frame = (tf->tf_dma2 - fsize) & 307 ~_STACKALIGNBYTES; 308 continue; 309 } 310 break; 311 } 312 } 313#endif 314 315 return frame; 316} 317