1 /* $NetBSD: netbsd32_machdep.c,v 1.117 2021/11/06 20:42:56 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 2001 Matthew R. Green 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.117 2021/11/06 20:42:56 thorpej Exp $"); 31 32 #ifdef _KERNEL_OPT 33 #include "opt_compat_netbsd.h" 34 #include "opt_compat_sunos.h" 35 #include "opt_modular.h" 36 #include "opt_execfmt.h" 37 #include "firm_events.h" 38 #endif 39 40 #include <sys/param.h> 41 #include <sys/exec.h> 42 #include <sys/exec_aout.h> 43 #include <sys/filedesc.h> 44 #include <sys/file.h> 45 #include <sys/proc.h> 46 #include <sys/signalvar.h> 47 #include <sys/systm.h> 48 #include <sys/core.h> 49 #include <sys/mount.h> 50 #include <sys/buf.h> 51 #include <sys/vnode.h> 52 #include <sys/select.h> 53 #include <sys/socketvar.h> 54 #include <sys/ucontext.h> 55 #include <sys/ioctl.h> 56 #include <sys/kmem.h> 57 #include <sys/compat_stub.h> 58 59 #include <dev/sun/event_var.h> 60 61 #include <net/if.h> 62 #include <net/route.h> 63 64 #include <netinet/in.h> 65 #include <netinet/in_var.h> 66 #include <netinet/igmp.h> 67 #include <netinet/igmp_var.h> 68 #include <netinet/ip_mroute.h> 69 70 #include <compat/netbsd32/netbsd32.h> 71 #include <compat/netbsd32/netbsd32_ioctl.h> 72 #include <compat/netbsd32/netbsd32_syscallargs.h> 73 #include <compat/netbsd32/netbsd32_exec.h> 74 75 #include <compat/sys/signal.h> 76 #include <compat/sys/signalvar.h> 77 #include <compat/sys/siginfo.h> 78 #include <compat/sys/ucontext.h> 79 80 #include <machine/frame.h> 81 #include <machine/pcb.h> 82 #include <machine/reg.h> 83 #include <machine/vmparam.h> 84 #include <machine/vuid_event.h> 85 #include <machine/netbsd32_machdep.h> 86 #include <machine/userret.h> 87 88 /* Provide a the name of the architecture we're emulating */ 89 const char machine32[] = "sparc"; 90 const char machine_arch32[] = "sparc"; 91 92 #if NFIRM_EVENTS > 0 93 static int ev_out32(struct firm_event *, int, struct uio *); 94 #endif 95 96 /* 97 * Set up registers on exec. 98 * 99 * XXX this entire mess must be fixed 100 */ 101 /* ARGSUSED */ 102 void 103 netbsd32_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) 104 { 105 struct proc *p = l->l_proc; 106 struct trapframe64 *tf = l->l_md.md_tf; 107 struct fpstate64 *fs; 108 int64_t tstate; 109 110 /* Don't allow misaligned code by default */ 111 p->p_md.md_flags &= ~MDP_FIXALIGN; 112 113 /* Mark this as a 32-bit emulation */ 114 p->p_flag |= PK_32; 115 116 netbsd32_adjust_limits(p); 117 118 /* Setup the ev_out32 hook */ 119 #if NFIRM_EVENTS > 0 120 if (ev_out32_hook == NULL) 121 ev_out32_hook = ev_out32; 122 #endif 123 124 /* 125 * Set the registers to 0 except for: 126 * %o6: stack pointer, built in exec()) 127 * %tstate: (retain icc and xcc and cwp bits) 128 * %g1: p->p_psstrp (used by crt0) 129 * %tpc,%tnpc: entry point of program 130 */ 131 tstate = ((PSTATE_USER32)<<TSTATE_PSTATE_SHIFT) 132 | (tf->tf_tstate & TSTATE_CWP); 133 if ((fs = l->l_md.md_fpstate) != NULL) { 134 /* 135 * We hold an FPU state. If we own *the* FPU chip state 136 * we must get rid of it, and the only way to do that is 137 * to save it. In any case, get rid of our FPU state. 138 */ 139 fpusave_lwp(l, false); 140 pool_cache_put(fpstate_cache, fs); 141 l->l_md.md_fpstate = NULL; 142 } 143 memset(tf, 0, sizeof *tf); 144 tf->tf_tstate = tstate; 145 tf->tf_global[1] = p->p_psstrp; 146 tf->tf_pc = pack->ep_entry & ~3; 147 tf->tf_npc = tf->tf_pc + 4; 148 149 stack -= sizeof(struct rwindow32); 150 tf->tf_out[6] = stack; 151 tf->tf_out[7] = 0; 152 } 153 154 struct sparc32_sigframe_siginfo { 155 siginfo32_t sf_si; 156 ucontext32_t sf_uc; 157 }; 158 159 void 160 netbsd32_sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) 161 { 162 struct lwp *l = curlwp; 163 struct proc *p = l->l_proc; 164 struct sigacts *ps = p->p_sigacts; 165 int onstack; 166 int sig = ksi->ksi_signo; 167 ucontext32_t uc; 168 struct sparc32_sigframe_siginfo *fp; 169 siginfo32_t si32; 170 netbsd32_intptr_t catcher; 171 struct trapframe64 *tf = l->l_md.md_tf; 172 struct rwindow32 *oldsp, *newsp; 173 register32_t sp; 174 int ucsz, error; 175 176 /* Need to attempt to zero extend this 32-bit pointer */ 177 oldsp = (struct rwindow32*)(u_long)(u_int)tf->tf_out[6]; 178 /* Do we need to jump onto the signal stack? */ 179 onstack = 180 (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 181 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 182 183 /* Allocate space for the signal handler context. */ 184 if (onstack) 185 fp = (struct sparc32_sigframe_siginfo *) 186 ((char *)l->l_sigstk.ss_sp + 187 l->l_sigstk.ss_size); 188 else 189 fp = (struct sparc32_sigframe_siginfo *)oldsp; 190 fp = (struct sparc32_sigframe_siginfo*)((u_long)(fp - 1) & ~7); 191 192 /* 193 * Build the signal context to be used by sigreturn. 194 */ 195 memset(&uc, 0, sizeof uc); 196 uc.uc_flags = _UC_SIGMASK | 197 ((l->l_sigstk.ss_flags & SS_ONSTACK) 198 ? _UC_SETSTACK : _UC_CLRSTACK); 199 uc.uc_sigmask = *mask; 200 uc.uc_link = (uint32_t)(uintptr_t)l->l_ctxlink; 201 202 sendsig_reset(l, sig); 203 204 /* 205 * Now copy the stack contents out to user space. 206 * We need to make sure that when we start the signal handler, 207 * its %i6 (%fp), which is loaded from the newly allocated stack area, 208 * joins seamlessly with the frame it was in when the signal occurred, 209 * so that the debugger and _longjmp code can back up through it. 210 * Since we're calling the handler directly, allocate a full size 211 * C stack frame. 212 */ 213 mutex_exit(p->p_lock); 214 cpu_getmcontext32(l, &uc.uc_mcontext, &uc.uc_flags); 215 netbsd32_si_to_si32(&si32, (const siginfo_t *)&ksi->ksi_info); 216 ucsz = (int)(intptr_t)&uc.__uc_pad - (int)(intptr_t)&uc; 217 newsp = (struct rwindow32*)((intptr_t)fp - sizeof(struct frame32)); 218 sp = NETBSD32PTR32I(oldsp); 219 error = (copyout(&si32, &fp->sf_si, sizeof si32) || 220 copyout(&uc, &fp->sf_uc, ucsz) || 221 copyout(&sp, &newsp->rw_in[6], sizeof(sp))); 222 mutex_enter(p->p_lock); 223 224 if (error) { 225 /* 226 * Process has trashed its stack; give it an illegal 227 * instruction to halt it in its tracks. 228 */ 229 sigexit(l, SIGILL); 230 /* NOTREACHED */ 231 } 232 233 switch (ps->sa_sigdesc[sig].sd_vers) { 234 default: 235 /* Unsupported trampoline version; kill the process. */ 236 sigexit(l, SIGILL); 237 case __SIGTRAMP_SIGINFO_VERSION: 238 /* 239 * Arrange to continue execution at the user's handler. 240 * It needs a new stack pointer, a return address and 241 * three arguments: (signo, siginfo *, ucontext *). 242 */ 243 catcher = (intptr_t)SIGACTION(p, sig).sa_handler; 244 tf->tf_pc = catcher; 245 tf->tf_npc = catcher + 4; 246 tf->tf_out[0] = sig; 247 tf->tf_out[1] = (intptr_t)&fp->sf_si; 248 tf->tf_out[2] = (intptr_t)&fp->sf_uc; 249 tf->tf_out[6] = (intptr_t)newsp; 250 tf->tf_out[7] = (intptr_t)ps->sa_sigdesc[sig].sd_tramp - 8; 251 break; 252 } 253 254 /* Remember that we're now on the signal stack. */ 255 if (onstack) 256 l->l_sigstk.ss_flags |= SS_ONSTACK; 257 } 258 259 #undef DEBUG 260 261 /* Unfortunately we need to convert v9 trapframe to v8 regs */ 262 int 263 netbsd32_process_read_regs(struct lwp *l, struct reg32 *regs) 264 { 265 struct trapframe64* tf = l->l_md.md_tf; 266 int i; 267 268 /* 269 * Um, we should only do this conversion for 32-bit emulation 270 * or when running 32-bit mode. We really need to pass in a 271 * 32-bit emulation flag! 272 */ 273 274 regs->r_psr = TSTATECCR_TO_PSR(tf->tf_tstate); 275 regs->r_pc = tf->tf_pc; 276 regs->r_npc = tf->tf_npc; 277 regs->r_y = tf->tf_y; 278 for (i = 0; i < 8; i++) { 279 regs->r_global[i] = tf->tf_global[i]; 280 regs->r_out[i] = tf->tf_out[i]; 281 } 282 /* We should also write out the ins and locals. See signal stuff */ 283 return (0); 284 } 285 286 int 287 netbsd32_process_write_regs(struct lwp *l, const struct reg32 *regs) 288 { 289 struct trapframe64* tf = l->l_md.md_tf; 290 int i; 291 292 tf->tf_pc = regs->r_pc; 293 tf->tf_npc = regs->r_npc; 294 tf->tf_y = regs->r_y; 295 for (i = 0; i < 8; i++) { 296 tf->tf_global[i] = regs->r_global[i]; 297 tf->tf_out[i] = regs->r_out[i]; 298 } 299 /* We should also read in the ins and locals. See signal stuff */ 300 tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | 301 PSRCC_TO_TSTATE(regs->r_psr); 302 return (0); 303 } 304 305 int 306 netbsd32_process_read_fpregs(struct lwp *l, struct fpreg32 *regs, size_t *sz) 307 { 308 extern const struct fpstate64 initfpstate; 309 const struct fpstate64 *statep = &initfpstate; 310 int i; 311 312 if (l->l_md.md_fpstate) 313 statep = l->l_md.md_fpstate; 314 for (i = 0; i < 32; i++) 315 regs->fr_regs[i] = statep->fs_regs[i]; 316 regs->fr_fsr = statep->fs_fsr; 317 318 return 0; 319 } 320 321 int 322 netbsd32_process_write_fpregs(struct lwp *l, const struct fpreg32 *regs, 323 size_t sz) 324 { 325 struct fpstate64 *statep; 326 int i; 327 328 statep = l->l_md.md_fpstate; 329 if (statep == NULL) 330 return EINVAL; 331 for (i = 0; i < 32; i++) 332 statep->fs_regs[i] = regs->fr_regs[i]; 333 statep->fs_fsr = regs->fr_fsr; 334 statep->fs_qsize = 0; 335 336 return 0; 337 } 338 339 /* 340 * 32-bit version of cpu_coredump. 341 */ 342 int 343 cpu_coredump32(struct lwp *l, struct coredump_iostate *iocookie, 344 struct core32 *chdr) 345 { 346 int i, error; 347 struct md_coredump32 md_core; 348 struct coreseg32 cseg; 349 350 if (iocookie == NULL) { 351 CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0); 352 chdr->c_hdrsize = ALIGN(sizeof(*chdr)); 353 chdr->c_seghdrsize = ALIGN(sizeof(cseg)); 354 chdr->c_cpusize = sizeof(md_core); 355 chdr->c_nseg++; 356 return 0; 357 } 358 359 /* Fake a v8 trapframe */ 360 md_core.md_tf.tf_psr = TSTATECCR_TO_PSR(l->l_md.md_tf->tf_tstate); 361 md_core.md_tf.tf_pc = l->l_md.md_tf->tf_pc; 362 md_core.md_tf.tf_npc = l->l_md.md_tf->tf_npc; 363 md_core.md_tf.tf_y = l->l_md.md_tf->tf_y; 364 for (i=0; i<8; i++) { 365 md_core.md_tf.tf_global[i] = l->l_md.md_tf->tf_global[i]; 366 md_core.md_tf.tf_out[i] = l->l_md.md_tf->tf_out[i]; 367 } 368 369 if (l->l_md.md_fpstate) { 370 fpusave_lwp(l, true); 371 /* Copy individual fields */ 372 for (i=0; i<32; i++) 373 md_core.md_fpstate.fs_regs[i] = 374 l->l_md.md_fpstate->fs_regs[i]; 375 md_core.md_fpstate.fs_fsr = l->l_md.md_fpstate->fs_fsr; 376 i = md_core.md_fpstate.fs_qsize = l->l_md.md_fpstate->fs_qsize; 377 /* Should always be zero */ 378 while (i--) 379 md_core.md_fpstate.fs_queue[i] = 380 l->l_md.md_fpstate->fs_queue[i]; 381 } else 382 memset(&md_core.md_fpstate, 0, 383 sizeof(md_core.md_fpstate)); 384 385 CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU); 386 cseg.c_addr = 0; 387 cseg.c_size = chdr->c_cpusize; 388 389 MODULE_HOOK_CALL(coredump_write_hook, (iocookie, UIO_SYSSPACE, &cseg, 390 chdr->c_seghdrsize), ENOSYS, error); 391 if (error) 392 return error; 393 394 MODULE_HOOK_CALL(coredump_write_hook, (iocookie, UIO_SYSSPACE, &md_core, 395 sizeof(md_core)), ENOSYS, error); 396 397 return error; 398 } 399 400 void netbsd32_cpu_getmcontext(struct lwp *, mcontext_t *, unsigned int *); 401 402 void 403 netbsd32_cpu_getmcontext( 404 struct lwp *l, 405 /* netbsd32_mcontext_t XXX */mcontext_t *mcp, 406 unsigned int *flags) 407 { 408 #if 0 409 /* XXX */ 410 greg32_t *gr = mcp->__gregs; 411 const struct trapframe64 *tf = l->l_md.md_tf; 412 413 /* First ensure consistent stack state (see sendsig). */ /* XXX? */ 414 write_user_windows(); 415 if (rwindow_save(l)) { 416 mutex_enter(l->l_proc->p_lock); 417 sigexit(l, SIGILL); 418 } 419 420 /* For now: Erase any random indicators for optional state. */ 421 (void)memset(mcp, 0, sizeof (*mcp)); 422 423 /* Save general register context. */ 424 gr[_REG_PSR] = TSTATECCR_TO_PSR(tf->tf_tstate); 425 gr[_REG_PC] = tf->tf_pc; 426 gr[_REG_nPC] = tf->tf_npc; 427 gr[_REG_Y] = tf->tf_y; 428 gr[_REG_G1] = tf->tf_global[1]; 429 gr[_REG_G2] = tf->tf_global[2]; 430 gr[_REG_G3] = tf->tf_global[3]; 431 gr[_REG_G4] = tf->tf_global[4]; 432 gr[_REG_G5] = tf->tf_global[5]; 433 gr[_REG_G6] = tf->tf_global[6]; 434 gr[_REG_G7] = tf->tf_global[7]; 435 gr[_REG_O0] = tf->tf_out[0]; 436 gr[_REG_O1] = tf->tf_out[1]; 437 gr[_REG_O2] = tf->tf_out[2]; 438 gr[_REG_O3] = tf->tf_out[3]; 439 gr[_REG_O4] = tf->tf_out[4]; 440 gr[_REG_O5] = tf->tf_out[5]; 441 gr[_REG_O6] = tf->tf_out[6]; 442 gr[_REG_O7] = tf->tf_out[7]; 443 *flags |= (_UC_CPU|_UC_TLSBASE); 444 445 mcp->__gwins = 0; 446 447 448 /* Save FP register context, if any. */ 449 if (l->l_md.md_fpstate != NULL) { 450 struct fpstate *fsp; 451 netbsd32_fpregset_t *fpr = &mcp->__fpregs; 452 453 /* 454 * If our FP context is currently held in the FPU, take a 455 * private snapshot - lazy FPU context switching can deal 456 * with it later when it becomes necessary. 457 * Otherwise, get it from the process's save area. 458 */ 459 fpusave_lwp(l, true); 460 fsp = l->l_md.md_fpstate; 461 memcpy(&fpr->__fpu_fr, fsp->fs_regs, sizeof (fpr->__fpu_fr)); 462 mcp->__fpregs.__fpu_q = NULL; /* `Need more info.' */ 463 mcp->__fpregs.__fpu_fsr = fs.fs_fsr; 464 mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */ 465 mcp->__fpregs.__fpu_q_entrysize = 466 sizeof (struct netbsd32_fq); 467 mcp->__fpregs.__fpu_en = 1; 468 *flags |= _UC_FPU; 469 } else { 470 mcp->__fpregs.__fpu_en = 0; 471 } 472 473 mcp->__xrs.__xrs_id = 0; /* Solaris extension? */ 474 #endif 475 } 476 477 int netbsd32_cpu_setmcontext(struct lwp *, mcontext_t *, unsigned int); 478 479 int 480 netbsd32_cpu_setmcontext( 481 struct lwp *l, 482 /* XXX const netbsd32_*/mcontext_t *mcp, 483 unsigned int flags) 484 { 485 #ifdef NOT_YET 486 /* XXX */ 487 greg32_t *gr = mcp->__gregs; 488 struct trapframe64 *tf = l->l_md.md_tf; 489 490 /* First ensure consistent stack state (see sendsig). */ 491 write_user_windows(); 492 if (rwindow_save(p)) { 493 mutex_enter(l->l_proc->p_lock); 494 sigexit(p, SIGILL); 495 } 496 497 if ((flags & _UC_CPU) != 0) { 498 /* 499 * Only the icc bits in the psr are used, so it need not be 500 * verified. pc and npc must be multiples of 4. This is all 501 * that is required; if it holds, just do it. 502 */ 503 if (((gr[_REG_PC] | gr[_REG_nPC]) & 3) != 0 || 504 gr[_REG_PC] == 0 || gr[_REG_nPC] == 0) 505 return (EINVAL); 506 507 /* Restore general register context. */ 508 /* take only tstate CCR (and ASI) fields */ 509 tf->tf_tstate = (tf->tf_tstate & ~TSTATE_CCR) | 510 PSRCC_TO_TSTATE(gr[_REG_PSR]); 511 tf->tf_pc = (uint64_t)gr[_REG_PC]; 512 tf->tf_npc = (uint64_t)gr[_REG_nPC]; 513 tf->tf_y = (uint64_t)gr[_REG_Y]; 514 tf->tf_global[1] = (uint64_t)gr[_REG_G1]; 515 tf->tf_global[2] = (uint64_t)gr[_REG_G2]; 516 tf->tf_global[3] = (uint64_t)gr[_REG_G3]; 517 tf->tf_global[4] = (uint64_t)gr[_REG_G4]; 518 tf->tf_global[5] = (uint64_t)gr[_REG_G5]; 519 tf->tf_global[6] = (uint64_t)gr[_REG_G6]; 520 tf->tf_global[7] = (uint64_t)gr[_REG_G7]; 521 tf->tf_out[0] = (uint64_t)gr[_REG_O0]; 522 tf->tf_out[1] = (uint64_t)gr[_REG_O1]; 523 tf->tf_out[2] = (uint64_t)gr[_REG_O2]; 524 tf->tf_out[3] = (uint64_t)gr[_REG_O3]; 525 tf->tf_out[4] = (uint64_t)gr[_REG_O4]; 526 tf->tf_out[5] = (uint64_t)gr[_REG_O5]; 527 tf->tf_out[6] = (uint64_t)gr[_REG_O6]; 528 tf->tf_out[7] = (uint64_t)gr[_REG_O7]; 529 /* %asi restored above; %fprs not yet supported. */ 530 531 /* XXX mcp->__gwins */ 532 } 533 534 /* Restore FP register context, if any. */ 535 if ((flags & _UC_FPU) != 0 && mcp->__fpregs.__fpu_en != 0) { 536 struct fpstate *fsp; 537 const netbsd32_fpregset_t *fpr = &mcp->__fpregs; 538 int reload = 0; 539 540 /* 541 * If we're the current FPU owner, simply reload it from 542 * the supplied context. Otherwise, store it into the 543 * process' FPU save area (which is used to restore from 544 * by lazy FPU context switching); allocate it if necessary. 545 */ 546 /* 547 * XXX Should we really activate the supplied FPU context 548 * XXX immediately or just fault it in later? 549 */ 550 if ((fsp = l->l_md.md_fpstate) == NULL) { 551 fsp = pool_cache_get(fpstate_cache, PR_WAITOK); 552 l->l_md.md_fpstate = fsp; 553 } else { 554 /* Drop the live context on the floor. */ 555 fpusave_lwp(l, false); 556 reload = 1; 557 } 558 /* Note: sizeof fpr->__fpu_fr <= sizeof fsp->fs_regs. */ 559 memcpy(fsp->fs_regs, fpr->__fpu_fr, sizeof (fpr->__fpu_fr)); 560 fsp->fs_fsr = fpr->__fpu_fsr; /* don't care about fcc1-3 */ 561 fsp->fs_qsize = 0; 562 563 #if 0 564 /* Need more info! */ 565 mcp->__fpregs.__fpu_q = NULL; /* `Need more info.' */ 566 mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */ 567 #endif 568 569 /* Reload context again, if necessary. */ 570 if (reload) 571 loadfpstate(fsp); 572 } 573 574 /* XXX mcp->__xrs */ 575 /* XXX mcp->__asrs */ 576 #endif 577 return (0); 578 } 579 580 #if NFIRM_EVENTS > 0 581 /* 582 * Write out a series of 32-bit firm_events. 583 */ 584 int 585 ev_out32(struct firm_event *e, int n, struct uio *uio) 586 { 587 struct firm_event32 e32; 588 int error = 0; 589 590 while (n-- && error == 0) { 591 e32.id = e->id; 592 e32.value = e->value; 593 e32.time.tv_sec = e->time.tv_sec; 594 e32.time.tv_usec = e->time.tv_usec; 595 error = uiomove((void *)&e32, sizeof(e32), uio); 596 e++; 597 } 598 return (error); 599 } 600 #endif 601 602 /* 603 * ioctl code 604 */ 605 606 #include <dev/sun/fbio.h> 607 #include <machine/openpromio.h> 608 609 /* from arch/sparc/include/fbio.h */ 610 #if 0 611 /* unused */ 612 #define FBIOGINFO _IOR('F', 2, struct fbinfo) 613 #endif 614 615 struct netbsd32_fbcmap { 616 int index; /* first element (0 origin) */ 617 int count; /* number of elements */ 618 netbsd32_u_charp red; /* red color map elements */ 619 netbsd32_u_charp green; /* green color map elements */ 620 netbsd32_u_charp blue; /* blue color map elements */ 621 }; 622 #if 1 623 #define FBIOPUTCMAP32 _IOW('F', 3, struct netbsd32_fbcmap) 624 #define FBIOGETCMAP32 _IOW('F', 4, struct netbsd32_fbcmap) 625 #endif 626 627 struct netbsd32_fbcursor { 628 short set; /* what to set */ 629 short enable; /* enable/disable cursor */ 630 struct fbcurpos pos; /* cursor's position */ 631 struct fbcurpos hot; /* cursor's hot spot */ 632 struct netbsd32_fbcmap cmap; /* color map info */ 633 struct fbcurpos size; /* cursor's bit map size */ 634 netbsd32_charp image; /* cursor's image bits */ 635 netbsd32_charp mask; /* cursor's mask bits */ 636 }; 637 #if 1 638 #define FBIOSCURSOR32 _IOW('F', 24, struct netbsd32_fbcursor) 639 #define FBIOGCURSOR32 _IOWR('F', 25, struct netbsd32_fbcursor) 640 #endif 641 642 /* from arch/sparc/include/openpromio.h */ 643 struct netbsd32_opiocdesc { 644 int op_nodeid; /* passed or returned node id */ 645 int op_namelen; /* length of op_name */ 646 netbsd32_charp op_name; /* pointer to field name */ 647 int op_buflen; /* length of op_buf (value-result) */ 648 netbsd32_charp op_buf; /* pointer to field value */ 649 }; 650 #if 1 651 #define OPIOCGET32 _IOWR('O', 1, struct netbsd32_opiocdesc) /* get openprom field */ 652 #define OPIOCSET32 _IOW('O', 2, struct netbsd32_opiocdesc) /* set openprom field */ 653 #define OPIOCNEXTPROP32 _IOWR('O', 3, struct netbsd32_opiocdesc) /* get next property */ 654 #endif 655 656 /* prototypes for the converters */ 657 static inline void netbsd32_to_fbcmap(struct netbsd32_fbcmap *, 658 struct fbcmap *, u_long); 659 static inline void netbsd32_to_fbcursor(struct netbsd32_fbcursor *, 660 struct fbcursor *, u_long); 661 static inline void netbsd32_to_opiocdesc(struct netbsd32_opiocdesc *, 662 struct opiocdesc *, u_long); 663 664 static inline void netbsd32_from_fbcmap(struct fbcmap *, 665 struct netbsd32_fbcmap *, u_long); 666 static inline void netbsd32_from_fbcursor(struct fbcursor *, 667 struct netbsd32_fbcursor *, u_long); 668 static inline void netbsd32_from_opiocdesc(struct opiocdesc *, 669 struct netbsd32_opiocdesc *, 670 u_long); 671 672 /* convert to/from different structures */ 673 static inline void 674 netbsd32_to_fbcmap(struct netbsd32_fbcmap *s32p, struct fbcmap *p, u_long cmd) 675 { 676 677 p->index = s32p->index; 678 p->count = s32p->count; 679 p->red = NETBSD32PTR64(s32p->red); 680 p->green = NETBSD32PTR64(s32p->green); 681 p->blue = NETBSD32PTR64(s32p->blue); 682 } 683 684 static inline void 685 netbsd32_to_fbcursor(struct netbsd32_fbcursor *s32p, struct fbcursor *p, u_long cmd) 686 { 687 688 p->set = s32p->set; 689 p->enable = s32p->enable; 690 p->pos = s32p->pos; 691 p->hot = s32p->hot; 692 netbsd32_to_fbcmap(&s32p->cmap, &p->cmap, cmd); 693 p->size = s32p->size; 694 p->image = NETBSD32PTR64(s32p->image); 695 p->mask = NETBSD32PTR64(s32p->mask); 696 } 697 698 static inline void 699 netbsd32_to_opiocdesc(struct netbsd32_opiocdesc *s32p, struct opiocdesc *p, u_long cmd) 700 { 701 702 p->op_nodeid = s32p->op_nodeid; 703 p->op_namelen = s32p->op_namelen; 704 p->op_name = NETBSD32PTR64(s32p->op_name); 705 p->op_buflen = s32p->op_buflen; 706 p->op_buf = NETBSD32PTR64(s32p->op_buf); 707 } 708 709 static inline void 710 netbsd32_from_fbcmap(struct fbcmap *p, struct netbsd32_fbcmap *s32p, u_long cmd) 711 { 712 713 s32p->index = p->index; 714 s32p->count = p->count; 715 /* filled in */ 716 #if 0 717 s32p->red = (netbsd32_u_charp)p->red; 718 s32p->green = (netbsd32_u_charp)p->green; 719 s32p->blue = (netbsd32_u_charp)p->blue; 720 #endif 721 } 722 723 static inline void 724 netbsd32_from_fbcursor(struct fbcursor *p, struct netbsd32_fbcursor *s32p, u_long cmd) 725 { 726 727 s32p->set = p->set; 728 s32p->enable = p->enable; 729 s32p->pos = p->pos; 730 s32p->hot = p->hot; 731 netbsd32_from_fbcmap(&p->cmap, &s32p->cmap, cmd); 732 s32p->size = p->size; 733 /* filled in */ 734 #if 0 735 s32p->image = (netbsd32_charp)p->image; 736 s32p->mask = (netbsd32_charp)p->mask; 737 #endif 738 } 739 740 static inline void 741 netbsd32_from_opiocdesc(struct opiocdesc *p, struct netbsd32_opiocdesc *s32p, u_long cmd) 742 { 743 744 s32p->op_nodeid = p->op_nodeid; 745 s32p->op_namelen = p->op_namelen; 746 NETBSD32PTR32(s32p->op_name, p->op_name); 747 s32p->op_buflen = p->op_buflen; 748 NETBSD32PTR32(s32p->op_buf, p->op_buf); 749 } 750 751 int 752 netbsd32_md_ioctl(struct file *fp, netbsd32_u_long cmd, void *data32, struct lwp *l) 753 { 754 u_int size; 755 void *data, *memp = NULL; 756 #define STK_PARAMS 128 757 u_long stkbuf[STK_PARAMS/sizeof(u_long)]; 758 int error; 759 760 switch (cmd) { 761 case FBIOPUTCMAP32: 762 IOCTL_STRUCT_CONV_TO(FBIOPUTCMAP, fbcmap); 763 case FBIOGETCMAP32: 764 IOCTL_STRUCT_CONV_TO(FBIOGETCMAP, fbcmap); 765 766 case FBIOSCURSOR32: 767 IOCTL_STRUCT_CONV_TO(FBIOSCURSOR, fbcursor); 768 case FBIOGCURSOR32: 769 IOCTL_STRUCT_CONV_TO(FBIOGCURSOR, fbcursor); 770 771 case OPIOCGET32: 772 IOCTL_STRUCT_CONV_TO(OPIOCGET, opiocdesc); 773 case OPIOCSET32: 774 IOCTL_STRUCT_CONV_TO(OPIOCSET, opiocdesc); 775 case OPIOCNEXTPROP32: 776 IOCTL_STRUCT_CONV_TO(OPIOCNEXTPROP, opiocdesc); 777 default: 778 error = (*fp->f_ops->fo_ioctl)(fp, cmd, data32); 779 } 780 if (memp) 781 kmem_free(memp, size); 782 return (error); 783 } 784 785 786 int 787 netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap, register_t *retval) 788 { 789 /* { 790 syscallarg(int) op; 791 syscallarg(netbsd32_voidp) parms; 792 } */ 793 794 switch (SCARG(uap, op)) { 795 default: 796 printf("(%s) netbsd32_sysarch(%d)\n", MACHINE, SCARG(uap, op)); 797 return EINVAL; 798 } 799 } 800 801 int 802 cpu_mcontext32_validate(struct lwp *l, const mcontext32_t *mc) 803 { 804 const __greg32_t *gr = mc->__gregs; 805 806 /* 807 * Only the icc bits in the psr are used, so it need not be 808 * verified. pc and npc must be multiples of 4. This is all 809 * that is required; if it holds, just do it. 810 */ 811 if (((gr[_REG32_PC] | gr[_REG32_nPC]) & 3) != 0 || 812 gr[_REG32_PC] == 0 || gr[_REG32_nPC] == 0) 813 return EINVAL; 814 815 return 0; 816 } 817 818 int 819 cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags) 820 { 821 struct trapframe *tf = l->l_md.md_tf; 822 const __greg32_t *gr = mcp->__gregs; 823 struct proc *p = l->l_proc; 824 int error; 825 826 /* First ensure consistent stack state (see sendsig). */ 827 write_user_windows(); 828 if (rwindow_save(l)) { 829 mutex_enter(p->p_lock); 830 sigexit(l, SIGILL); 831 } 832 833 /* Restore register context, if any. */ 834 if ((flags & _UC_CPU) != 0) { 835 error = cpu_mcontext32_validate(l, mcp); 836 if (error) 837 return error; 838 839 /* Restore general register context. */ 840 /* take only tstate CCR (and ASI) fields */ 841 tf->tf_tstate = (tf->tf_tstate & ~TSTATE_CCR) | 842 PSRCC_TO_TSTATE(gr[_REG32_PSR]); 843 tf->tf_pc = (uint64_t)gr[_REG32_PC]; 844 tf->tf_npc = (uint64_t)gr[_REG32_nPC]; 845 tf->tf_y = (uint64_t)gr[_REG32_Y]; 846 tf->tf_global[1] = (uint64_t)gr[_REG32_G1]; 847 tf->tf_global[2] = (uint64_t)gr[_REG32_G2]; 848 tf->tf_global[3] = (uint64_t)gr[_REG32_G3]; 849 tf->tf_global[4] = (uint64_t)gr[_REG32_G4]; 850 tf->tf_global[5] = (uint64_t)gr[_REG32_G5]; 851 tf->tf_global[6] = (uint64_t)gr[_REG32_G6]; 852 /* done in lwp_setprivate */ 853 /* tf->tf_global[7] = (uint64_t)gr[_REG32_G7]; */ 854 tf->tf_out[0] = (uint64_t)gr[_REG32_O0]; 855 tf->tf_out[1] = (uint64_t)gr[_REG32_O1]; 856 tf->tf_out[2] = (uint64_t)gr[_REG32_O2]; 857 tf->tf_out[3] = (uint64_t)gr[_REG32_O3]; 858 tf->tf_out[4] = (uint64_t)gr[_REG32_O4]; 859 tf->tf_out[5] = (uint64_t)gr[_REG32_O5]; 860 tf->tf_out[6] = (uint64_t)gr[_REG32_O6]; 861 tf->tf_out[7] = (uint64_t)gr[_REG32_O7]; 862 /* %asi restored above; %fprs not yet supported. */ 863 864 if (flags & _UC_TLSBASE) 865 lwp_setprivate(l, (void *)(uintptr_t)gr[_REG32_G7]); 866 867 /* XXX mcp->__gwins */ 868 } 869 870 /* Restore floating point register context, if any. */ 871 if ((flags & _UC_FPU) != 0) { 872 #ifdef notyet 873 struct fpstate64 *fsp; 874 const __fpregset_t *fpr = &mcp->__fpregs; 875 876 /* 877 * If we're the current FPU owner, simply reload it from 878 * the supplied context. Otherwise, store it into the 879 * process' FPU save area (which is used to restore from 880 * by lazy FPU context switching); allocate it if necessary. 881 */ 882 if ((fsp = l->l_md.md_fpstate) == NULL) { 883 fsp = pool_cache_get(fpstate_cache, PR_WAITOK); 884 l->l_md.md_fpstate = fsp; 885 } else { 886 /* Drop the live context on the floor. */ 887 fpusave_lwp(l, false); 888 } 889 /* Note: sizeof fpr->__fpu_fr <= sizeof fsp->fs_regs. */ 890 memcpy(fsp->fs_regs, &fpr->__fpu_fr, sizeof (fpr->__fpu_fr)); 891 fsp->fs_fsr = mcp->__fpregs.__fpu_fsr; 892 fsp->fs_qsize = 0; 893 894 #if 0 895 /* Need more info! */ 896 mcp->__fpregs.__fpu_q = NULL; /* `Need more info.' */ 897 mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */ 898 #endif 899 #endif 900 } 901 #ifdef _UC_SETSTACK 902 mutex_enter(p->p_lock); 903 if (flags & _UC_SETSTACK) 904 l->l_sigstk.ss_flags |= SS_ONSTACK; 905 if (flags & _UC_CLRSTACK) 906 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 907 mutex_exit(p->p_lock); 908 #endif 909 return (0); 910 } 911 912 913 void 914 cpu_getmcontext32(struct lwp *l, mcontext32_t *mcp, unsigned int *flags) 915 { 916 const struct trapframe *tf = l->l_md.md_tf; 917 __greg32_t *gr = mcp->__gregs; 918 919 /* First ensure consistent stack state (see sendsig). */ /* XXX? */ 920 write_user_windows(); 921 if (rwindow_save(l)) { 922 mutex_enter(l->l_proc->p_lock); 923 sigexit(l, SIGILL); 924 } 925 926 /* For now: Erase any random indicators for optional state. */ 927 (void)memset(mcp, '0', sizeof (*mcp)); 928 929 /* Save general register context. */ 930 gr[_REG32_PSR] = TSTATECCR_TO_PSR(tf->tf_tstate); 931 gr[_REG32_PC] = tf->tf_pc; 932 gr[_REG32_nPC] = tf->tf_npc; 933 gr[_REG32_Y] = tf->tf_y; 934 gr[_REG32_G1] = tf->tf_global[1]; 935 gr[_REG32_G2] = tf->tf_global[2]; 936 gr[_REG32_G3] = tf->tf_global[3]; 937 gr[_REG32_G4] = tf->tf_global[4]; 938 gr[_REG32_G5] = tf->tf_global[5]; 939 gr[_REG32_G6] = tf->tf_global[6]; 940 gr[_REG32_G7] = tf->tf_global[7]; 941 gr[_REG32_O0] = tf->tf_out[0]; 942 gr[_REG32_O1] = tf->tf_out[1]; 943 gr[_REG32_O2] = tf->tf_out[2]; 944 gr[_REG32_O3] = tf->tf_out[3]; 945 gr[_REG32_O4] = tf->tf_out[4]; 946 gr[_REG32_O5] = tf->tf_out[5]; 947 gr[_REG32_O6] = tf->tf_out[6]; 948 gr[_REG32_O7] = tf->tf_out[7]; 949 *flags |= (_UC_CPU|_UC_TLSBASE); 950 951 mcp->__gwins = 0; 952 mcp->__xrs.__xrs_id = 0; /* Solaris extension? */ 953 *flags |= (_UC_CPU|_UC_TLSBASE); 954 955 /* Save FP register context, if any. */ 956 if (l->l_md.md_fpstate != NULL) { 957 #ifdef notyet 958 struct fpstate64 *fsp; 959 __fpregset_t *fpr = &mcp->__fpregs; 960 961 /* 962 * If our FP context is currently held in the FPU, take a 963 * private snapshot - lazy FPU context switching can deal 964 * with it later when it becomes necessary. 965 * Otherwise, get it from the process's save area. 966 */ 967 fpusave_lwp(l, true); 968 fsp = l->l_md.md_fpstate; 969 memcpy(&fpr->__fpu_fr, fsp->fs_regs, sizeof (fpr->__fpu_fr)); 970 mcp->__fpregs.__fpu_q = NULL; /* `Need more info.' */ 971 mcp->__fpregs.__fpu_fsr = fs.fs_fsr; 972 mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */ 973 mcp->__fpregs.__fpu_q_entrysize = 974 (unsigned char) sizeof (*mcp->__fpregs.__fpu_q); 975 mcp->__fpregs.__fpu_en = 1; 976 *flags |= _UC_FPU; 977 #endif 978 } else { 979 mcp->__fpregs.__fpu_en = 0; 980 } 981 } 982 983 void 984 startlwp32(void *arg) 985 { 986 ucontext32_t *uc = arg; 987 lwp_t *l = curlwp; 988 int error __diagused; 989 990 error = cpu_setmcontext32(l, &uc->uc_mcontext, uc->uc_flags); 991 KASSERT(error == 0); 992 993 /* Note: we are freeing ucontext_t, not ucontext32_t. */ 994 kmem_free(arg, sizeof(ucontext_t)); 995 userret(l, 0, 0); 996 } 997 998 vaddr_t 999 netbsd32_vm_default_addr(struct proc *p, vaddr_t base, vsize_t size, 1000 int topdown) 1001 { 1002 return round_page((vaddr_t)(base) + (vsize_t)MAXDSIZ32); 1003 } 1004 1005 static const char * 1006 netbsd32_machine32(void) 1007 { 1008 1009 return machine32; 1010 } 1011 1012 void 1013 netbsd32_machdep_md_init(void) 1014 { 1015 1016 MODULE_HOOK_SET(netbsd32_machine32_hook, netbsd32_machine32); 1017 } 1018 1019 void 1020 netbsd32_machdep_md_fini(void) 1021 { 1022 1023 MODULE_HOOK_UNSET(netbsd32_machine32_hook); 1024 } 1025