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 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 * 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 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 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 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 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 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