1 /* $NetBSD: compat_16_machdep.c,v 1.20 2026/08/30 00:38:49 thorpej 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 <sys/cdefs.h> 41 __KERNEL_RCSID(0, "$NetBSD: compat_16_machdep.c,v 1.20 2026/08/30 00:38:49 thorpej Exp $"); 42 43 #ifdef _KERNEL_OPT 44 #include "opt_compat_netbsd.h" 45 #endif 46 47 #define __M68K_SIGNAL_PRIVATE 48 49 #include <sys/param.h> 50 #include <sys/systm.h> 51 #include <sys/kernel.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 #ifdef COMPAT_13 62 #include <compat/sys/signal.h> 63 #include <compat/sys/signalvar.h> 64 #endif 65 66 #include <machine/cpu.h> 67 #include <machine/reg.h> 68 #include <machine/frame.h> 69 70 #ifdef DEBUG 71 extern int sigdebug; 72 extern int sigpid; 73 #define SDB_FOLLOW 0x01 74 #define SDB_KSTACK 0x02 75 #define SDB_FPSTATE 0x04 76 #endif 77 78 #ifdef COMPAT_16 79 /* 80 * Send an interrupt to process. 81 */ 82 void 83 sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) 84 { 85 struct lwp *l = curlwp; 86 struct proc *p = l->l_proc; 87 struct sigacts *ps = p->p_sigacts; 88 struct frame *frame = (struct frame *)l->l_md.md_regs; 89 int onstack, error; 90 int sig = ksi->ksi_signo; 91 u_long code = KSI_TRAPCODE(ksi); 92 struct sigframe_sigcontext *fp, kf; 93 sig_t catcher = SIGACTION(p, sig).sa_handler; 94 short ft = frame->f_format; 95 96 fp = getframe(l, sig, &onstack, sizeof(*fp)); 97 98 #ifdef DEBUG 99 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 100 printf("sendsig(%d): sig %d ssp %p usp %p scp %p ft %d\n", 101 p->p_pid, sig, &onstack, fp, &fp->sf_sc, ft); 102 #endif 103 104 /* Build stack frame for signal trampoline. */ 105 switch (ps->sa_sigdesc[sig].sd_vers) { 106 case __SIGTRAMP_SIGCODE_VERSION: /* legacy on-stack sigtramp */ 107 kf.sf_ra = (int)p->p_sigctx.ps_sigcode; 108 break; 109 110 case __SIGTRAMP_SIGCONTEXT_VERSION: 111 kf.sf_ra = (int)ps->sa_sigdesc[sig].sd_tramp; 112 break; 113 114 default: 115 /* Don't know what trampoline version; kill it. */ 116 sigexit(l, SIGILL); 117 } 118 119 kf.sf_signum = sig; 120 kf.sf_code = code; 121 kf.sf_scp = &fp->sf_sc; 122 123 /* 124 * Save necessary hardware state. Currently this includes: 125 * - general registers 126 * - original exception frame (if not a "normal" frame) 127 * - FP coprocessor state 128 */ 129 kf.sf_state.ss_flags = SS_USERREGS; 130 memcpy(kf.sf_state.ss_frame.f_regs, frame->f_regs, 131 sizeof(frame->f_regs)); 132 if (ft >= FMT4) { 133 #ifdef DEBUG 134 if (ft > 15 || exframesize[ft] < 0) 135 panic("sendsig: bogus frame type"); 136 #endif 137 kf.sf_state.ss_flags |= SS_RTEFRAME; 138 kf.sf_state.ss_frame.f_format = frame->f_format; 139 kf.sf_state.ss_frame.f_vector = frame->f_vector; 140 memcpy(&kf.sf_state.ss_frame.F_u, &frame->F_u, 141 (size_t) exframesize[ft]); 142 /* 143 * Leave an indicator that we need to clean up the kernel 144 * stack. We do this by setting the "pad word" above the 145 * hardware stack frame to the amount the stack must be 146 * adjusted by. 147 * 148 * N.B. we increment rather than just set f_stackadj in 149 * case we are called from syscall when processing a 150 * sigreturn. In that case, f_stackadj may be non-zero. 151 */ 152 frame->f_stackadj += exframesize[ft]; 153 frame->f_format = frame->f_vector = 0; 154 #ifdef DEBUG 155 if (sigdebug & SDB_FOLLOW) 156 printf("sendsig(%d): copy out %d of frame %d\n", 157 p->p_pid, exframesize[ft], ft); 158 #endif 159 } 160 161 if (fputype) { 162 kf.sf_state.ss_flags |= SS_FPSTATE; 163 m68881_save(&kf.sf_state.ss_fpstate); 164 } 165 #ifdef DEBUG 166 if ((sigdebug & SDB_FPSTATE) && *(char *)&kf.sf_state.ss_fpstate) 167 printf("sendsig(%d): copy out FP state (%x) to %p\n", 168 p->p_pid, *(u_int *)&kf.sf_state.ss_fpstate, 169 &kf.sf_state.ss_fpstate); 170 #endif 171 172 /* Build the signal context to be used by sigreturn. */ 173 kf.sf_sc.sc_sp = frame->f_regs[SP]; 174 kf.sf_sc.sc_fp = frame->f_regs[A6]; 175 kf.sf_sc.sc_ap = (int)&fp->sf_state; 176 kf.sf_sc.sc_pc = frame->f_pc; 177 kf.sf_sc.sc_ps = frame->f_sr; 178 179 /* Save signal stack. */ 180 kf.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; 181 182 /* Save signal mask. */ 183 kf.sf_sc.sc_mask = *mask; 184 185 #ifdef COMPAT_13 186 /* 187 * XXX We always have to save an old style signal mask because 188 * XXX we might be delivering a signal to a process which will 189 * XXX escape from the signal in a non-standard way and invoke 190 * XXX sigreturn() directly. 191 */ 192 native_sigset_to_sigset13(mask, &kf.sf_sc.__sc_mask13); 193 #endif 194 sendsig_reset(l, sig); 195 mutex_exit(p->p_lock); 196 error = copyout(&kf, fp, sizeof(kf)); 197 mutex_enter(p->p_lock); 198 199 if (error != 0) { 200 #ifdef DEBUG 201 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 202 printf("sendsig(%d): copyout failed on sig %d\n", 203 p->p_pid, sig); 204 #endif 205 /* 206 * Process has trashed its stack; give it an illegal 207 * instruction to halt it in its tracks. 208 */ 209 sigexit(l, SIGILL); 210 /* NOTREACHED */ 211 } 212 #ifdef DEBUG 213 if (sigdebug & SDB_FOLLOW) 214 printf("sendsig(%d): sig %d scp %p fp %p sc_sp %x sc_ap %x\n", 215 p->p_pid, sig, kf.sf_scp, fp, 216 kf.sf_sc.sc_sp, kf.sf_sc.sc_ap); 217 #endif 218 219 buildcontext(l, catcher, fp); 220 221 /* Remember that we're now on the signal stack. */ 222 if (onstack) 223 l->l_sigstk.ss_flags |= SS_ONSTACK; 224 225 #ifdef DEBUG 226 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 227 printf("sendsig(%d): sig %d returns\n", 228 p->p_pid, sig); 229 #endif 230 } 231 #endif 232 233 #ifdef COMPAT_16 234 /* 235 * System call to cleanup state after a signal 236 * has been taken. Reset signal mask and 237 * stack state from context left by sendsig (above). 238 * Return to previous pc and psl as specified by 239 * context left by sendsig. Check carefully to 240 * make sure that the user has not modified the 241 * psl to gain improper privileges or to cause 242 * a machine fault. 243 */ 244 int 245 compat_16_sys___sigreturn14(struct lwp *l, const struct compat_16_sys___sigreturn14_args *uap, register_t *retval) 246 { 247 /* { 248 syscallarg(struct sigcontext *) sigcntxp; 249 } */ 250 struct proc *p = l->l_proc; 251 struct sigcontext *scp; 252 struct frame *frame; 253 struct sigcontext tsigc; 254 struct sigstate tstate; 255 int rf, flags, error; 256 257 /* 258 * The trampoline code hands us the context. 259 * It is unsafe to keep track of it ourselves, in the event that a 260 * program jumps out of a signal handler. 261 */ 262 scp = SCARG(uap, sigcntxp); 263 #ifdef DEBUG 264 if (sigdebug & SDB_FOLLOW) 265 printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp); 266 #endif 267 if ((int)scp & 1) 268 return EINVAL; 269 270 if (copyin(scp, &tsigc, sizeof(tsigc)) != 0) 271 return EFAULT; 272 scp = &tsigc; 273 274 /* Make sure the user isn't pulling a fast one on us! */ 275 if ((scp->sc_ps & (PSL_MBZ|PSL_IPL|PSL_S)) != 0) 276 return EINVAL; 277 278 /* Restore register context. */ 279 frame = (struct frame *) l->l_md.md_regs; 280 281 /* 282 * Grab pointer to hardware state information. 283 * If zero, the user is probably doing a longjmp. 284 */ 285 if ((rf = scp->sc_ap) == 0) 286 goto restore; 287 288 /* 289 * See if there is anything to do before we go to the 290 * expense of copying in close to 1/2K of data 291 */ 292 error = ufetch_int((void *)rf, (u_int *)&flags); 293 #ifdef DEBUG 294 if (sigdebug & SDB_FOLLOW) 295 printf("sigreturn(%d): sc_ap %x flags %x\n", 296 p->p_pid, rf, error ? -1 : flags); 297 #endif 298 /* ufetch_int() failed (bogus sc_ap value). */ 299 if (error) 300 return EINVAL; 301 302 if (flags == 0 || copyin((void *)rf, &tstate, sizeof(tstate)) != 0) 303 goto restore; 304 #ifdef DEBUG 305 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 306 printf("sigreturn(%d): ssp %p usp %x scp %p ft %d\n", 307 p->p_pid, &flags, scp->sc_sp, SCARG(uap, sigcntxp), 308 (flags & SS_RTEFRAME) ? tstate.ss_frame.f_format : -1); 309 #endif 310 /* 311 * Restore long stack frames. Note that we do not copy 312 * back the saved SR or PC, they were picked up above from 313 * the sigcontext structure. 314 */ 315 if (flags & SS_RTEFRAME) { 316 register int sz; 317 318 /* grab frame type and validate */ 319 sz = tstate.ss_frame.f_format; 320 if (sz > 15 || (sz = exframesize[sz]) < 0 321 || frame->f_stackadj < sz) 322 return EINVAL; 323 frame->f_stackadj -= sz; 324 frame->f_format = tstate.ss_frame.f_format; 325 frame->f_vector = tstate.ss_frame.f_vector; 326 memcpy(&frame->F_u, &tstate.ss_frame.F_u, sz); 327 #ifdef DEBUG 328 if (sigdebug & SDB_FOLLOW) 329 printf("sigreturn(%d): copy in %d of frame type %d\n", 330 p->p_pid, sz, tstate.ss_frame.f_format); 331 #endif 332 } 333 334 /* 335 * Restore most of the users registers except for A6 and SP 336 * which will be handled below. 337 */ 338 if (flags & SS_USERREGS) 339 memcpy(frame->f_regs, tstate.ss_frame.f_regs, 340 sizeof(frame->f_regs) - (2 * NBPW)); 341 342 /* 343 * Restore the original FP context 344 */ 345 if (fputype && (flags & SS_FPSTATE)) 346 m68881_restore(&tstate.ss_fpstate); 347 348 restore: 349 /* 350 * Restore the user supplied information. 351 * This should be at the last so that the error (EINVAL) 352 * is reported to the sigreturn caller, not to the 353 * jump destination. 354 */ 355 356 frame->f_regs[SP] = scp->sc_sp; 357 frame->f_regs[A6] = scp->sc_fp; 358 frame->f_pc = scp->sc_pc; 359 frame->f_sr = scp->sc_ps; 360 361 mutex_enter(p->p_lock); 362 363 /* Restore signal stack. */ 364 if (scp->sc_onstack & SS_ONSTACK) 365 l->l_sigstk.ss_flags |= SS_ONSTACK; 366 else 367 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 368 369 /* Restore signal mask. */ 370 (void) sigprocmask1(l, SIG_SETMASK, &scp->sc_mask, 0); 371 372 mutex_exit(p->p_lock); 373 374 #ifdef DEBUG 375 if ((sigdebug & SDB_FPSTATE) && *(char *)&tstate.ss_fpstate) 376 printf("sigreturn(%d): copied in FP state (%x) at %p\n", 377 p->p_pid, *(u_int *)&tstate.ss_fpstate, 378 &tstate.ss_fpstate); 379 if ((sigdebug & SDB_FOLLOW) || 380 ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) 381 printf("sigreturn(%d): returns\n", p->p_pid); 382 #endif 383 return EJUSTRETURN; 384 } 385 #endif 386