1 /* $OpenBSD: sig_machdep.c,v 1.32 2024/10/14 08:42:39 jsg 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 79 vaddr_t local_stack_frame(struct trapframe *, vaddr_t, size_t); 80 81 /* 82 * WARNING: sigcode() in subr.s assumes sf_scp is the first field of the 83 * sigframe. 84 */ 85 struct sigframe { 86 struct sigcontext *sf_scp; /* context ptr for handler */ 87 struct sigcontext sf_sc; /* actual context */ 88 siginfo_t sf_si; 89 }; 90 91 #ifdef DEBUG 92 int sigdebug = 0; 93 pid_t sigpid = 0; 94 #define SDB_FOLLOW 0x01 95 #define SDB_KSTACK 0x02 96 #endif 97 98 /* 99 * Send an interrupt to process. 100 */ 101 int 102 sendsig(sig_t catcher, int sig, sigset_t mask, const siginfo_t *ksip, 103 int info, int onstack) 104 { 105 struct proc *p = curproc; 106 struct trapframe *tf; 107 struct sigframe *fp; 108 size_t fsize; 109 struct sigframe sf; 110 vaddr_t addr; 111 112 tf = p->p_md.md_tf; 113 114 if (info) 115 fsize = sizeof(struct sigframe); 116 else 117 fsize = offsetof(struct sigframe, sf_si); 118 119 /* 120 * Allocate space for the signal handler context. 121 */ 122 if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && 123 !sigonstack(tf->tf_r[31]) && onstack) { 124 addr = local_stack_frame(tf, 125 trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size), 126 fsize); 127 } else 128 addr = local_stack_frame(tf, tf->tf_r[31], fsize); 129 130 fp = (struct sigframe *)addr; 131 132 /* 133 * Build the signal context to be used by sigreturn. 134 */ 135 bzero(&sf, fsize); 136 sf.sf_scp = &fp->sf_sc; 137 sf.sf_sc.sc_mask = mask; 138 sf.sf_sc.sc_cookie = (long)sf.sf_scp ^ p->p_p->ps_sigcookie; 139 140 if (info) 141 sf.sf_si = *ksip; 142 143 /* 144 * Copy the whole user context into signal context that we 145 * are building. 146 */ 147 bcopy((const void *)&tf->tf_regs, (void *)&sf.sf_sc.sc_regs, 148 sizeof(sf.sf_sc.sc_regs)); 149 150 if (copyout((caddr_t)&sf, (caddr_t)fp, fsize)) 151 return 1; 152 153 /* 154 * Set up registers for the signal handler invocation. 155 */ 156 tf->tf_r[1] = p->p_p->ps_sigcode; /* return to sigcode */ 157 tf->tf_r[2] = sig; /* first arg is signo */ 158 tf->tf_r[3] = info ? (vaddr_t)&fp->sf_si : 0; 159 tf->tf_r[4] = (vaddr_t)&fp->sf_sc; 160 tf->tf_r[31] = (vaddr_t)fp; 161 addr = (vaddr_t)catcher; /* and resume in the handler */ 162 #ifdef M88100 163 if (CPU_IS88100) { 164 tf->tf_snip = (addr & NIP_ADDR) | NIP_V; 165 tf->tf_sfip = (tf->tf_snip + 4) | FIP_V; 166 } 167 #endif 168 #ifdef M88110 169 if (CPU_IS88110) 170 tf->tf_exip = (addr & XIP_ADDR); 171 #endif 172 173 #ifdef DEBUG 174 if ((sigdebug & SDB_FOLLOW) || 175 ((sigdebug & SDB_KSTACK) && p->p_p->ps_pid == sigpid)) 176 printf("sendsig(%d): sig %d returns\n", p->p_p->ps_pid, sig); 177 #endif 178 179 return 0; 180 } 181 182 /* 183 * System call to cleanup state after a signal has been taken. Reset signal 184 * mask and stack state from context left by sendsig (above). Return to 185 * previous pc and psl as specified by context left by sendsig. Check 186 * carefully to make sure that the user has not modified the psl to gain 187 * improper privileges or to cause a machine fault. 188 */ 189 int 190 sys_sigreturn(struct proc *p, void *v, register_t *retval) 191 { 192 struct sys_sigreturn_args /* { 193 syscallarg(struct sigcontext *) sigcntxp; 194 } */ *uap = v; 195 struct sigcontext ksc, *scp = SCARG(uap, sigcntxp); 196 struct trapframe *tf; 197 int error; 198 vaddr_t pc; 199 200 tf = p->p_md.md_tf; 201 202 /* 203 * This is simpler than PROC_PC, assuming XIP is always valid 204 * on 88100, and doesn't have a delay slot on 88110 205 * (which is the status we expect from the signal code). 206 */ 207 pc = CPU_IS88110 ? tf->tf_regs.exip : tf->tf_regs.sxip ^ XIP_V; 208 if (pc != p->p_p->ps_sigcoderet) { 209 sigexit(p, SIGILL); 210 return (EPERM); 211 } 212 213 if (((vaddr_t)scp & 3) != 0) 214 return (EFAULT); 215 216 if ((error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(*scp)))) 217 return (error); 218 219 if (ksc.sc_cookie != ((long)scp ^ p->p_p->ps_sigcookie)) { 220 sigexit(p, SIGILL); 221 return (EFAULT); 222 } 223 224 /* Prevent reuse of the sigcontext cookie */ 225 ksc.sc_cookie = 0; 226 (void)copyout(&ksc.sc_cookie, (caddr_t)scp + 227 offsetof(struct sigcontext, sc_cookie), sizeof (ksc.sc_cookie)); 228 229 if ((((struct reg *)&ksc.sc_regs)->epsr ^ tf->tf_regs.epsr) & 230 PSR_USERSTATIC) 231 return (EINVAL); 232 233 bcopy((const void *)&ksc.sc_regs, (caddr_t)&tf->tf_regs, 234 sizeof(ksc.sc_regs)); 235 236 /* 237 * Restore the user supplied information 238 */ 239 p->p_sigmask = ksc.sc_mask & ~sigcantmask; 240 241 #ifdef M88100 242 if (CPU_IS88100) { 243 /* 244 * If we are returning from a signal handler triggered by 245 * a data access exception, the interrupted access has 246 * never been performed, and will not be reissued upon 247 * returning to userland. 248 * 249 * We can't simply call data_access_emulation(), for 250 * it might fault again. Instead, we invoke trap() 251 * again, which will either trigger another signal, 252 * or end up invoking data_access_emulation if safe. 253 */ 254 if (ISSET(tf->tf_dmt0, DMT_VALID)) 255 m88100_trap(T_DATAFLT, tf); 256 } 257 #endif 258 259 /* 260 * We really want to return to the instruction pointed to by the 261 * sigcontext. However, due to the way exceptions work on 88110, 262 * returning EJUSTRETURN will cause m88110_syscall() to skip one 263 * instruction. We avoid this by returning ERESTART, which will 264 * indeed cause the instruction pointed to by exip to be run 265 * again. 266 */ 267 return CPU_IS88100 ? EJUSTRETURN : ERESTART; 268 } 269 270 /* 271 * Find out a safe place on the process' stack to put the sigframe struct. 272 * While on 88110, this is straightforward, on 88100 we need to be 273 * careful and not stomp over potential uncompleted data accesses, which 274 * we will want to be able to perform upon sigreturn(). 275 */ 276 vaddr_t 277 local_stack_frame(struct trapframe *tf, vaddr_t tos, size_t fsize) 278 { 279 vaddr_t frame; 280 281 frame = (tos - fsize) & ~_STACKALIGNBYTES; 282 283 #ifdef M88100 284 if (CPU_IS88100 && ISSET(tf->tf_dmt0, DMT_VALID)) { 285 for (;;) { 286 tos = frame + fsize; 287 if (/* ISSET(tf->tf_dmt0, DMT_VALID) && */ 288 tf->tf_dma0 >= frame && tf->tf_dma0 < tos) { 289 frame = (tf->tf_dma0 - fsize) & 290 ~_STACKALIGNBYTES; 291 continue; 292 } 293 if (ISSET(tf->tf_dmt1, DMT_VALID) && 294 tf->tf_dma1 >= frame && tf->tf_dma1 < tos) { 295 frame = (tf->tf_dma1 - fsize) & 296 ~_STACKALIGNBYTES; 297 continue; 298 } 299 if (ISSET(tf->tf_dmt2, DMT_VALID) && 300 tf->tf_dma2 >= frame && tf->tf_dma2 < tos) { 301 frame = (tf->tf_dma2 - fsize) & 302 ~_STACKALIGNBYTES; 303 continue; 304 } 305 break; 306 } 307 } 308 #endif 309 310 return frame; 311 } 312