1 /* $NetBSD: sig_machdep.c,v 1.51 2021/04/24 16:14:08 tsutsui Exp $ */
2
3 /*
4 * Copyright (c) 1988 University of Utah.
5 * Copyright (c) 1982, 1986, 1990, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * the Systems Programming Group of the University of Utah Computer
10 * Science Department.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from: Utah Hdr: machdep.c 1.74 92/12/20
37 * from: @(#)machdep.c 8.10 (Berkeley) 4/20/94
38 */
39
40 #include "opt_m68k_arch.h"
41
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.51 2021/04/24 16:14:08 tsutsui Exp $");
44
45 #define __M68K_SIGNAL_PRIVATE
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/kernel.h>
50 #include <sys/cpu.h>
51 #include <sys/pool.h>
52 #include <sys/proc.h>
53 #include <sys/ras.h>
54 #include <sys/signal.h>
55 #include <sys/signalvar.h>
56 #include <sys/ucontext.h>
57
58 #include <sys/mount.h>
59 #include <sys/syscallargs.h>
60
61 #include <machine/pcb.h>
62 #include <machine/frame.h>
63
64 #include <m68k/m68k.h>
65 #include <m68k/fpreg.h>
66
67 extern short exframesize[];
68 struct fpframe m68k_cached_fpu_idle_frame;
69
70 #ifdef DEBUG
71 int sigdebug = 0;
72 int sigpid = 0;
73 #define SDB_FOLLOW 0x01
74 #define SDB_KSTACK 0x02
75 #define SDB_FPSTATE 0x04
76 #endif
77
78 /*
79 * Test for a null floating point frame given a pointer to the start
80 * of an fsave'd frame.
81 */
82 #if defined(M68020) || defined(M68030) || defined(M68040)
83 #if defined(M68060)
84 #define FPFRAME_IS_NULL(fp) \
85 ((fputype == FPU_68060 && \
86 ((struct fpframe060 *)(fp))->fpf6_frmfmt == FPF6_FMT_NULL) || \
87 (fputype != FPU_68060 && \
88 ((union FPF_u1 *)(fp))->FPF_nonnull.FPF_version == 0))
89 #else
90 #define FPFRAME_IS_NULL(fp) \
91 (((union FPF_u1 *)(fp))->FPF_nonnull.FPF_version == 0)
92 #endif
93 #else
94 #define FPFRAME_IS_NULL(fp) \
95 (((struct fpframe060 *)(fp))->fpf6_frmfmt == FPF6_FMT_NULL)
96 #endif
97
98 /* convert 68881 %fpsr code into siginfo ksi_code */
99 u_int
fpsr2siginfocode(u_int fpsr)100 fpsr2siginfocode(u_int fpsr)
101 {
102 if (fpsr & FPSR_DZ)
103 return FPE_FLTDIV;
104 if (fpsr & FPSR_UNFL)
105 return FPE_FLTUND;
106 if (fpsr & FPSR_OVFL)
107 return FPE_FLTOVF;
108 if (fpsr & FPSR_OPERR)
109 return FPE_FLTINV;
110 if (fpsr & (FPSR_INEX1|FPSR_INEX2))
111 return FPE_FLTRES;
112 return 0;
113 }
114
115 void *
getframe(struct lwp * l,int sig,int * onstack)116 getframe(struct lwp *l, int sig, int *onstack)
117 {
118 struct frame *tf = (struct frame *)l->l_md.md_regs;
119
120 /* Do we need to jump onto the signal stack? */
121 *onstack =(l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0
122 && (SIGACTION(l->l_proc, sig).sa_flags & SA_ONSTACK) != 0;
123
124 if (*onstack)
125 return (char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size;
126 else
127 return (void *)tf->f_regs[SP];
128 }
129
130 /*
131 * Build context to run handler in. We invoke the handler
132 * directly, only returning via the trampoline. Note the
133 * trampoline version numbers are coordinated with machine-
134 * dependent code in libc.
135 */
136 void
buildcontext(struct lwp * l,void * catcher,void * fp)137 buildcontext(struct lwp *l, void *catcher, void *fp)
138 {
139 struct frame *frame = (struct frame *)l->l_md.md_regs;
140
141 /*
142 * Set up the registers to return to the signal handler. The
143 * handler will then return to the signal trampoline.
144 */
145 frame->f_regs[SP] = (int)fp;
146 frame->f_pc = (int)catcher;
147 }
148
149 void
sendsig_siginfo(const ksiginfo_t * ksi,const sigset_t * mask)150 sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask)
151 {
152 struct lwp *l = curlwp;
153 struct proc *p = l->l_proc;
154 struct sigacts *ps = p->p_sigacts;
155 int onstack, error;
156 int sig = ksi->ksi_signo;
157 struct sigframe_siginfo *fp = getframe(l, sig, &onstack), kf;
158 sig_t catcher = SIGACTION(p, sig).sa_handler;
159
160 fp--;
161
162 memset(&kf, 0, sizeof(kf));
163 kf.sf_ra = (int)ps->sa_sigdesc[sig].sd_tramp;
164 kf.sf_signum = sig;
165 kf.sf_sip = &fp->sf_si;
166 kf.sf_ucp = &fp->sf_uc;
167 kf.sf_si._info = ksi->ksi_info;
168 kf.sf_uc.uc_flags = _UC_SIGMASK;
169 kf.sf_uc.uc_sigmask = *mask;
170 kf.sf_uc.uc_link = l->l_ctxlink;
171 kf.sf_uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK)
172 ? _UC_SETSTACK : _UC_CLRSTACK;
173 sendsig_reset(l, sig);
174 mutex_exit(p->p_lock);
175 cpu_getmcontext(l, &kf.sf_uc.uc_mcontext, &kf.sf_uc.uc_flags);
176 error = copyout(&kf, fp, sizeof(kf));
177 mutex_enter(p->p_lock);
178
179 if (error != 0) {
180 /*
181 * Process has trashed its stack; give it an illegal
182 * instruction to halt it in its tracks.
183 */
184 sigexit(l, SIGILL);
185 /* NOTREACHED */
186 }
187
188 buildcontext(l, catcher, fp);
189
190 /* Remember that we're now on the signal stack. */
191 if (onstack)
192 l->l_sigstk.ss_flags |= SS_ONSTACK;
193 }
194
195 void
cpu_getmcontext(struct lwp * l,mcontext_t * mcp,u_int * flags)196 cpu_getmcontext(struct lwp *l, mcontext_t *mcp, u_int *flags)
197 {
198 __greg_t *gr = mcp->__gregs;
199 struct frame *frame = (struct frame *)l->l_md.md_regs;
200 unsigned int format = frame->f_format;
201 __greg_t ras_pc;
202
203 /* Save general registers. */
204 gr[_REG_D0] = frame->f_regs[D0];
205 gr[_REG_D1] = frame->f_regs[D1];
206 gr[_REG_D2] = frame->f_regs[D2];
207 gr[_REG_D3] = frame->f_regs[D3];
208 gr[_REG_D4] = frame->f_regs[D4];
209 gr[_REG_D5] = frame->f_regs[D5];
210 gr[_REG_D6] = frame->f_regs[D6];
211 gr[_REG_D7] = frame->f_regs[D7];
212 gr[_REG_A0] = frame->f_regs[A0];
213 gr[_REG_A1] = frame->f_regs[A1];
214 gr[_REG_A2] = frame->f_regs[A2];
215 gr[_REG_A3] = frame->f_regs[A3];
216 gr[_REG_A4] = frame->f_regs[A4];
217 gr[_REG_A5] = frame->f_regs[A5];
218 gr[_REG_A6] = frame->f_regs[A6];
219 gr[_REG_A7] = frame->f_regs[SP];
220 gr[_REG_PS] = frame->f_sr;
221 gr[_REG_PC] = frame->f_pc;
222
223 if ((ras_pc = (__greg_t)ras_lookup(l->l_proc,
224 (void *) gr[_REG_PC])) != -1)
225 gr[_REG_PC] = ras_pc;
226
227 *flags |= _UC_CPU;
228
229 mcp->_mc_tlsbase = (uintptr_t)l->l_private;
230 *flags |= _UC_TLSBASE;
231
232 /* Save exception frame information. */
233 mcp->__mc_pad.__mc_frame.__mcf_format = format;
234 if (format >= FMT4) {
235 mcp->__mc_pad.__mc_frame.__mcf_vector = frame->f_vector;
236 (void)memcpy(&mcp->__mc_pad.__mc_frame.__mcf_exframe,
237 &frame->F_u, (size_t)exframesize[format]);
238
239 /*
240 * Leave indicators that we need to clean up the kernel
241 * stack. We do this by setting the "pad word" above the
242 * hardware stack frame to the amount the stack must be
243 * adjusted by.
244 *
245 * N.B. we increment rather than just set f_stackadj in
246 * case we are called from syscall when processing a
247 * sigreturn. In that case, f_stackadj may be non-zero.
248 */
249 frame->f_stackadj += exframesize[format];
250 frame->f_format = frame->f_vector = 0;
251 }
252
253 if (fputype != FPU_NONE) {
254 /* Save FPU context. */
255 struct pcb *pcb = lwp_getpcb(l);
256 struct fpframe *fpf = &pcb->pcb_fpregs;
257
258 /*
259 * If we're dealing with the current lwp, we need to
260 * save its FP state. Otherwise, its state is already
261 * store in its PCB.
262 */
263 if (l == curlwp)
264 m68881_save(fpf);
265
266 mcp->__mc_pad.__mc_frame.__mcf_fpf_u1 = fpf->FPF_u1;
267
268 /* If it's a null frame there's no need to save/convert. */
269 if (!FPFRAME_IS_NULL(fpf)) {
270 mcp->__mc_pad.__mc_frame.__mcf_fpf_u2 = fpf->FPF_u2;
271 (void)memcpy(mcp->__fpregs.__fp_fpregs,
272 fpf->fpf_regs, sizeof(fpf->fpf_regs));
273 mcp->__fpregs.__fp_pcr = fpf->fpf_fpcr;
274 mcp->__fpregs.__fp_psr = fpf->fpf_fpsr;
275 mcp->__fpregs.__fp_piaddr = fpf->fpf_fpiar;
276 *flags |= _UC_FPU;
277 }
278 }
279 }
280
281 int
cpu_mcontext_validate(struct lwp * l,const mcontext_t * mcp)282 cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp)
283 {
284 const __greg_t *gr = mcp->__gregs;
285
286 if ((gr[_REG_PS] & (PSL_MBZ|PSL_IPL|PSL_S)) != 0)
287 return EINVAL;
288 return 0;
289 }
290
291 int
cpu_setmcontext(struct lwp * l,const mcontext_t * mcp,u_int flags)292 cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, u_int flags)
293 {
294 const __greg_t *gr = mcp->__gregs;
295 struct frame *frame = (struct frame *)l->l_md.md_regs;
296 unsigned int format = mcp->__mc_pad.__mc_frame.__mcf_format;
297 int sz, error;
298
299 /* Validate the supplied context */
300 if ((flags & _UC_CPU) != 0) {
301 error = cpu_mcontext_validate(l, mcp);
302 if (error)
303 return error;
304 }
305
306 /* Restore exception frame information if necessary. */
307 if ((flags & _UC_M68K_UC_USER) == 0 && format >= FMT4) {
308 if (format > FMTB)
309 return (EINVAL);
310 sz = exframesize[format];
311 if (sz < 0)
312 return (EINVAL);
313
314 if (frame->f_stackadj == 0) {
315 /*
316 * Extra stack space is required but not allocated.
317 * Allocate and re-enter syscall().
318 */
319 reenter_syscall(frame, sz);
320 /* NOTREACHED */
321 }
322
323 #ifdef DIAGNOSTIC
324 /* reenter_syscall() should adjust stack for the extra frame. */
325 if (sz != frame->f_stackadj)
326 panic("cpu_setmcontext: %d != %d",
327 sz, frame->f_stackadj);
328 #endif
329
330 /*
331 * Restore long stack frames. Note that we do not copy
332 * back the saved SR or PC, they were picked up below from
333 * the sigcontext structure.
334 */
335 frame->f_format = format;
336 frame->f_vector = mcp->__mc_pad.__mc_frame.__mcf_vector;
337 (void)memcpy(&frame->F_u,
338 &mcp->__mc_pad.__mc_frame.__mcf_exframe, (size_t)sz);
339 frame->f_stackadj -= sz;
340 }
341
342 if ((flags & _UC_CPU) != 0) {
343 /* Restore general registers. */
344 frame->f_regs[D0] = gr[_REG_D0];
345 frame->f_regs[D1] = gr[_REG_D1];
346 frame->f_regs[D2] = gr[_REG_D2];
347 frame->f_regs[D3] = gr[_REG_D3];
348 frame->f_regs[D4] = gr[_REG_D4];
349 frame->f_regs[D5] = gr[_REG_D5];
350 frame->f_regs[D6] = gr[_REG_D6];
351 frame->f_regs[D7] = gr[_REG_D7];
352 frame->f_regs[A0] = gr[_REG_A0];
353 frame->f_regs[A1] = gr[_REG_A1];
354 frame->f_regs[A2] = gr[_REG_A2];
355 frame->f_regs[A3] = gr[_REG_A3];
356 frame->f_regs[A4] = gr[_REG_A4];
357 frame->f_regs[A5] = gr[_REG_A5];
358 frame->f_regs[A6] = gr[_REG_A6];
359 frame->f_regs[SP] = gr[_REG_A7];
360 frame->f_sr = gr[_REG_PS];
361 frame->f_pc = gr[_REG_PC];
362 }
363
364 if (fputype != FPU_NONE) {
365 const __fpregset_t *fpr = &mcp->__fpregs;
366 struct pcb *pcb = lwp_getpcb(l);
367 struct fpframe *fpf = &pcb->pcb_fpregs;
368
369 switch (flags & (_UC_FPU | _UC_M68K_UC_USER)) {
370 case _UC_FPU:
371 /*
372 * We're restoring FPU context saved by the above
373 * cpu_getmcontext(). We can do a full frestore if
374 * something other than an null frame was saved.
375 */
376 fpf->FPF_u1 = mcp->__mc_pad.__mc_frame.__mcf_fpf_u1;
377 if (!FPFRAME_IS_NULL(fpf)) {
378 fpf->FPF_u2 =
379 mcp->__mc_pad.__mc_frame.__mcf_fpf_u2;
380 (void)memcpy(fpf->fpf_regs,
381 fpr->__fp_fpregs, sizeof(fpf->fpf_regs));
382 fpf->fpf_fpcr = fpr->__fp_pcr;
383 fpf->fpf_fpsr = fpr->__fp_psr;
384 fpf->fpf_fpiar = fpr->__fp_piaddr;
385 }
386 break;
387
388 case _UC_FPU | _UC_M68K_UC_USER:
389 /*
390 * We're restoring FPU context saved by the
391 * userland _getcontext_() function. Since there
392 * is no FPU frame to restore. We assume the FPU was
393 * "idle" when the frame was created, so use the
394 * cached idle frame.
395 */
396 fpf->FPF_u1 = m68k_cached_fpu_idle_frame.FPF_u1;
397 fpf->FPF_u2 = m68k_cached_fpu_idle_frame.FPF_u2;
398 (void)memcpy(fpf->fpf_regs, fpr->__fp_fpregs,
399 sizeof(fpf->fpf_regs));
400 fpf->fpf_fpcr = fpr->__fp_pcr;
401 fpf->fpf_fpsr = fpr->__fp_psr;
402 fpf->fpf_fpiar = fpr->__fp_piaddr;
403 break;
404
405 default:
406 /*
407 * The saved context contains no FPU state.
408 * Restore a NULL frame.
409 */
410 fpf->FPF_u1.FPF_null = 0;
411 break;
412 }
413
414 /*
415 * We only need to restore FP state right now if we're
416 * dealing with curlwp. Otherwise, it'll be restored
417 * (from the PCB) when this lwp is given the CPU.
418 */
419 if (l == curlwp)
420 m68881_restore(fpf);
421 }
422
423 if ((flags & _UC_TLSBASE) != 0)
424 lwp_setprivate(l, (void *)(uintptr_t)mcp->_mc_tlsbase);
425
426 mutex_enter(l->l_proc->p_lock);
427 if (flags & _UC_SETSTACK)
428 l->l_sigstk.ss_flags |= SS_ONSTACK;
429 if (flags & _UC_CLRSTACK)
430 l->l_sigstk.ss_flags &= ~SS_ONSTACK;
431 mutex_exit(l->l_proc->p_lock);
432
433 return 0;
434 }
435