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
sendsig(sig_t catcher,int sig,sigset_t mask,const siginfo_t * ksip,int info,int onstack)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
sys_sigreturn(struct proc * p,void * v,register_t * retval)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
local_stack_frame(struct trapframe * tf,vaddr_t tos,size_t fsize)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