1 2 /* 3 * Copyright (c) 1998, 2001 Matthew R. Green 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #ifdef _KERNEL_OPT 31 #include "opt_compat_netbsd.h" 32 #endif 33 34 #include <sys/param.h> 35 #include <sys/exec.h> 36 #include <sys/malloc.h> 37 #include <sys/filedesc.h> 38 #include <sys/file.h> 39 #include <sys/proc.h> 40 #include <sys/signalvar.h> 41 #include <sys/systm.h> 42 #include <sys/user.h> 43 #include <sys/core.h> 44 #include <sys/mount.h> 45 #include <sys/buf.h> 46 #include <sys/vnode.h> 47 #include <sys/map.h> 48 #include <sys/select.h> 49 #include <sys/ioctl.h> 50 51 #include <dev/sun/event_var.h> 52 53 #include <net/if.h> 54 #include <net/route.h> 55 56 #include <netinet/in.h> 57 #include <netinet/in_var.h> 58 #include <netinet/igmp.h> 59 #include <netinet/igmp_var.h> 60 #include <netinet/ip_mroute.h> 61 62 #include <compat/netbsd32/netbsd32.h> 63 #include <compat/netbsd32/netbsd32_ioctl.h> 64 #include <compat/netbsd32/netbsd32_syscallargs.h> 65 66 #include <machine/frame.h> 67 #include <machine/reg.h> 68 #include <machine/vmparam.h> 69 #include <machine/vuid_event.h> 70 #include <machine/netbsd32_machdep.h> 71 72 static int ev_out32 __P((struct firm_event *, int, struct uio *)); 73 74 /* 75 * Set up registers on exec. 76 * 77 * XXX this entire mess must be fixed 78 */ 79 /* ARGSUSED */ 80 void 81 netbsd32_setregs(p, pack, stack) 82 struct proc *p; 83 struct exec_package *pack; 84 u_long stack; /* XXX */ 85 { 86 register struct trapframe64 *tf = p->p_md.md_tf; 87 register struct fpstate64 *fs; 88 register int64_t tstate; 89 90 /* Don't allow misaligned code by default */ 91 p->p_md.md_flags &= ~MDP_FIXALIGN; 92 93 /* Mark this as a 32-bit emulation */ 94 p->p_flag |= P_32; 95 96 /* Setup the ev_out32 hook */ 97 if (ev_out32_hook == NULL) 98 ev_out32_hook = ev_out32; 99 100 /* 101 * Set the registers to 0 except for: 102 * %o6: stack pointer, built in exec()) 103 * %tstate: (retain icc and xcc and cwp bits) 104 * %g1: address of p->p_psstr (used by crt0) 105 * %tpc,%tnpc: entry point of program 106 */ 107 tstate = ((PSTATE_USER32)<<TSTATE_PSTATE_SHIFT) 108 | (tf->tf_tstate & TSTATE_CWP); 109 if ((fs = p->p_md.md_fpstate) != NULL) { 110 /* 111 * We hold an FPU state. If we own *the* FPU chip state 112 * we must get rid of it, and the only way to do that is 113 * to save it. In any case, get rid of our FPU state. 114 */ 115 if (p == fpproc) { 116 savefpstate(fs); 117 fpproc = NULL; 118 } 119 free((void *)fs, M_SUBPROC); 120 p->p_md.md_fpstate = NULL; 121 } 122 bzero((caddr_t)tf, sizeof *tf); 123 tf->tf_tstate = tstate; 124 tf->tf_global[1] = (u_int)(u_long)p->p_psstr; 125 tf->tf_pc = pack->ep_entry & ~3; 126 tf->tf_npc = tf->tf_pc + 4; 127 128 stack -= sizeof(struct rwindow32); 129 tf->tf_out[6] = stack; 130 tf->tf_out[7] = NULL; 131 } 132 133 /* 134 * NB: since this is a 32-bit address world, sf_scp and sf_sc 135 * can't be a pointer since those are 64-bits wide. 136 */ 137 struct sparc32_sigframe { 138 int sf_signo; /* signal number */ 139 int sf_code; /* code */ 140 u_int sf_scp; /* SunOS user addr of sigcontext */ 141 int sf_addr; /* SunOS compat, always 0 for now */ 142 struct netbsd32_sigcontext sf_sc; /* actual sigcontext */ 143 }; 144 145 #undef DEBUG 146 #ifdef DEBUG 147 extern int sigdebug; 148 #endif 149 150 void 151 netbsd32_sendsig(catcher, sig, mask, code) 152 sig_t catcher; 153 int sig; 154 sigset_t *mask; 155 u_long code; 156 { 157 register struct proc *p = curproc; 158 register struct sparc32_sigframe *fp; 159 register struct trapframe64 *tf; 160 register int addr, onstack; 161 struct rwindow32 *kwin, *oldsp, *newsp; 162 struct sparc32_sigframe sf; 163 extern char netbsd32_sigcode[], netbsd32_esigcode[]; 164 #define szsigcode (netbsd32_esigcode - netbsd32_sigcode) 165 166 tf = p->p_md.md_tf; 167 /* Need to attempt to zero extend this 32-bit pointer */ 168 oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6]; 169 /* Do we need to jump onto the signal stack? */ 170 onstack = 171 (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 172 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 173 if (onstack) { 174 fp = (struct sparc32_sigframe *)((char *)p->p_sigctx.ps_sigstk.ss_sp + 175 p->p_sigctx.ps_sigstk.ss_size); 176 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 177 } else 178 fp = (struct sparc32_sigframe *)oldsp; 179 fp = (struct sparc32_sigframe *)((u_long)(fp - 1) & ~7); 180 181 #ifdef DEBUG 182 sigpid = p->p_pid; 183 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { 184 printf("sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n", 185 p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp); 186 if (sigdebug & SDB_DDB) Debugger(); 187 } 188 #endif 189 /* 190 * Now set up the signal frame. We build it in kernel space 191 * and then copy it out. We probably ought to just build it 192 * directly in user space.... 193 */ 194 sf.sf_signo = sig; 195 sf.sf_code = (u_int)code; 196 #if defined(COMPAT_SUNOS) || defined(LKM) 197 sf.sf_scp = (u_long)&fp->sf_sc; 198 #endif 199 sf.sf_addr = 0; /* XXX */ 200 201 /* 202 * Build the signal context to be used by sigreturn. 203 */ 204 sf.sf_sc.sc_onstack = onstack; 205 sf.sf_sc.sc_mask = *mask; 206 sf.sf_sc.sc_sp = (u_long)oldsp; 207 sf.sf_sc.sc_pc = tf->tf_pc; 208 sf.sf_sc.sc_npc = tf->tf_npc; 209 sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */ 210 sf.sf_sc.sc_g1 = tf->tf_global[1]; 211 sf.sf_sc.sc_o0 = tf->tf_out[0]; 212 213 /* 214 * Put the stack in a consistent state before we whack away 215 * at it. Note that write_user_windows may just dump the 216 * registers into the pcb; we need them in the process's memory. 217 * We also need to make sure that when we start the signal handler, 218 * its %i6 (%fp), which is loaded from the newly allocated stack area, 219 * joins seamlessly with the frame it was in when the signal occurred, 220 * so that the debugger and _longjmp code can back up through it. 221 */ 222 newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32)); 223 write_user_windows(); 224 #ifdef DEBUG 225 if ((sigdebug & SDB_KSTACK)) 226 printf("sendsig: saving sf to %p, setting stack pointer %p to %p\n", 227 fp, &(((struct rwindow32 *)newsp)->rw_in[6]), oldsp); 228 #endif 229 kwin = (struct rwindow32 *)(((caddr_t)tf)-CCFSZ); 230 if (rwindow_save(p) || 231 copyout((caddr_t)&sf, (caddr_t)fp, sizeof sf) || 232 suword(&(((struct rwindow32 *)newsp)->rw_in[6]), (u_long)oldsp)) { 233 /* 234 * Process has trashed its stack; give it an illegal 235 * instruction to halt it in its tracks. 236 */ 237 #ifdef DEBUG 238 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 239 printf("sendsig: window save or copyout error\n"); 240 printf("sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig); 241 if (sigdebug & SDB_DDB) Debugger(); 242 #endif 243 sigexit(p, SIGILL); 244 /* NOTREACHED */ 245 } 246 247 #ifdef DEBUG 248 if (sigdebug & SDB_FOLLOW) { 249 printf("sendsig: %s[%d] sig %d scp %p\n", 250 p->p_comm, p->p_pid, sig, &fp->sf_sc); 251 } 252 #endif 253 /* 254 * Arrange to continue execution at the code copied out in exec(). 255 * It needs the function to call in %g1, and a new stack pointer. 256 */ 257 addr = (long)p->p_psstr - szsigcode; 258 tf->tf_global[1] = (long)catcher; 259 tf->tf_pc = addr; 260 tf->tf_npc = addr + 4; 261 tf->tf_out[6] = (u_int64_t)(u_int)(u_long)newsp; 262 263 /* Remember that we're now on the signal stack. */ 264 if (onstack) 265 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 266 267 #ifdef DEBUG 268 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { 269 printf("sendsig: about to return to catcher %p thru %p\n", 270 catcher, addr); 271 if (sigdebug & SDB_DDB) Debugger(); 272 } 273 #endif 274 } 275 276 #undef DEBUG 277 278 #ifdef COMPAT_13 279 int 280 compat_13_netbsd32_sigreturn(p, v, retval) 281 struct proc *p; 282 void *v; 283 register_t *retval; 284 { 285 struct compat_13_netbsd32_sigreturn_args /* { 286 syscallarg(struct netbsd32_sigcontext13 *) sigcntxp; 287 } */ *uap = v; 288 struct netbsd32_sigcontext13 *scp; 289 struct netbsd32_sigcontext13 sc; 290 register struct trapframe64 *tf; 291 struct rwindow32 *rwstack, *kstack; 292 sigset_t mask; 293 294 /* First ensure consistent stack state (see sendsig). */ 295 write_user_windows(); 296 if (rwindow_save(p)) { 297 #ifdef DEBUG 298 printf("compat_13_netbsd32_sigreturn: rwindow_save(%p) failed, sending SIGILL\n", p); 299 Debugger(); 300 #endif 301 sigexit(p, SIGILL); 302 } 303 #ifdef DEBUG 304 if (sigdebug & SDB_FOLLOW) { 305 printf("compat_13_netbsd32_sigreturn: %s[%d], sigcntxp %p\n", 306 p->p_comm, p->p_pid, SCARG(uap, sigcntxp)); 307 if (sigdebug & SDB_DDB) Debugger(); 308 } 309 #endif 310 scp = (struct netbsd32_sigcontext13 *)(u_long)SCARG(uap, sigcntxp); 311 if ((vaddr_t)scp & 3 || (copyin((caddr_t)scp, &sc, sizeof sc) != 0)) 312 #ifdef DEBUG 313 { 314 printf("compat_13_netbsd32_sigreturn: copyin failed\n"); 315 Debugger(); 316 return (EINVAL); 317 } 318 #else 319 return (EINVAL); 320 #endif 321 tf = p->p_md.md_tf; 322 /* 323 * Only the icc bits in the psr are used, so it need not be 324 * verified. pc and npc must be multiples of 4. This is all 325 * that is required; if it holds, just do it. 326 */ 327 if (((sc.sc_pc | sc.sc_npc) & 3) != 0) 328 #ifdef DEBUG 329 { 330 printf("compat_13_netbsd32_sigreturn: pc %p or npc %p invalid\n", sc.sc_pc, sc.sc_npc); 331 Debugger(); 332 return (EINVAL); 333 } 334 #else 335 return (EINVAL); 336 #endif 337 /* take only psr ICC field */ 338 tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(sc.sc_psr); 339 tf->tf_pc = (int64_t)sc.sc_pc; 340 tf->tf_npc = (int64_t)sc.sc_npc; 341 tf->tf_global[1] = (int64_t)sc.sc_g1; 342 tf->tf_out[0] = (int64_t)sc.sc_o0; 343 tf->tf_out[6] = (int64_t)sc.sc_sp; 344 rwstack = (struct rwindow32 *)(u_long)tf->tf_out[6]; 345 kstack = (struct rwindow32 *)(((caddr_t)tf)-CCFSZ); 346 #ifdef DEBUG 347 if (sigdebug & SDB_FOLLOW) { 348 printf("compat_13_netbsd32_sys_sigreturn: return trapframe pc=%p sp=%p tstate=%x\n", 349 (int)tf->tf_pc, (int)tf->tf_out[6], (int)tf->tf_tstate); 350 if (sigdebug & SDB_DDB) Debugger(); 351 } 352 #endif 353 if (scp->sc_onstack & SS_ONSTACK) 354 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 355 else 356 p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; 357 358 /* Restore signal mask */ 359 native_sigset13_to_sigset(&scp->sc_mask, &mask); 360 (void) sigprocmask1(p, SIG_SETMASK, &mask, 0); 361 return (EJUSTRETURN); 362 } 363 #endif 364 365 /* 366 * System call to cleanup state after a signal 367 * has been taken. Reset signal mask and 368 * stack state from context left by sendsig (above), 369 * and return to the given trap frame (if there is one). 370 * Check carefully to make sure that the user has not 371 * modified the state to gain improper privileges or to cause 372 * a machine fault. 373 */ 374 /* ARGSUSED */ 375 int 376 netbsd32___sigreturn14(p, v, retval) 377 register struct proc *p; 378 void *v; 379 register_t *retval; 380 { 381 struct netbsd32___sigreturn14_args /* { 382 syscallarg(struct sigcontext *) sigcntxp; 383 } */ *uap = v; 384 struct netbsd32_sigcontext sc, *scp; 385 register struct trapframe64 *tf; 386 387 /* First ensure consistent stack state (see sendsig). */ 388 write_user_windows(); 389 if (rwindow_save(p)) { 390 #ifdef DEBUG 391 printf("netbsd32_sigreturn14: rwindow_save(%p) failed, sending SIGILL\n", p); 392 Debugger(); 393 #endif 394 sigexit(p, SIGILL); 395 } 396 #ifdef DEBUG 397 if (sigdebug & SDB_FOLLOW) { 398 printf("netbsd32_sigreturn14: %s[%d], sigcntxp %p\n", 399 p->p_comm, p->p_pid, SCARG(uap, sigcntxp)); 400 if (sigdebug & SDB_DDB) Debugger(); 401 } 402 #endif 403 scp = (struct netbsd32_sigcontext *)(u_long)SCARG(uap, sigcntxp); 404 if ((vaddr_t)scp & 3 || (copyin((caddr_t)scp, &sc, sizeof sc) != 0)) 405 #ifdef DEBUG 406 { 407 printf("netbsd32_sigreturn14: copyin failed: scp=%p\n", scp); 408 Debugger(); 409 return (EINVAL); 410 } 411 #else 412 return (EINVAL); 413 #endif 414 scp = ≻ 415 416 tf = p->p_md.md_tf; 417 /* 418 * Only the icc bits in the psr are used, so it need not be 419 * verified. pc and npc must be multiples of 4. This is all 420 * that is required; if it holds, just do it. 421 */ 422 if (((sc.sc_pc | sc.sc_npc) & 3) != 0 || (sc.sc_pc == 0) || (sc.sc_npc == 0)) 423 #ifdef DEBUG 424 { 425 printf("netbsd32_sigreturn14: pc %p or npc %p invalid\n", sc.sc_pc, sc.sc_npc); 426 Debugger(); 427 return (EINVAL); 428 } 429 #else 430 return (EINVAL); 431 #endif 432 /* take only psr ICC field */ 433 tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(sc.sc_psr); 434 tf->tf_pc = (int64_t)scp->sc_pc; 435 tf->tf_npc = (int64_t)scp->sc_npc; 436 tf->tf_global[1] = (int64_t)scp->sc_g1; 437 tf->tf_out[0] = (int64_t)scp->sc_o0; 438 tf->tf_out[6] = (int64_t)scp->sc_sp; 439 #ifdef DEBUG 440 if (sigdebug & SDB_FOLLOW) { 441 printf("netbsd32_sigreturn14: return trapframe pc=%p sp=%p tstate=%llx\n", 442 (vaddr_t)tf->tf_pc, (vaddr_t)tf->tf_out[6], tf->tf_tstate); 443 if (sigdebug & SDB_DDB) Debugger(); 444 } 445 #endif 446 447 /* Restore signal stack. */ 448 if (sc.sc_onstack & SS_ONSTACK) 449 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 450 else 451 p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; 452 453 /* Restore signal mask. */ 454 (void) sigprocmask1(p, SIG_SETMASK, &sc.sc_mask, 0); 455 456 return (EJUSTRETURN); 457 } 458 459 #if 0 460 /* Unfortunately we need to convert v9 trapframe to v8 regs */ 461 int 462 netbsd32_process_read_regs(p, regs) 463 struct proc *p; 464 struct reg *regs; 465 { 466 struct reg32* regp = (struct reg32*)regs; 467 struct trapframe64* tf = p->p_md.md_tf; 468 int i; 469 470 /* 471 * Um, we should only do this conversion for 32-bit emulation 472 * or when running 32-bit mode. We really need to pass in a 473 * 32-bit emulation flag! 474 */ 475 476 regp->r_psr = TSTATECCR_TO_PSR(tf->tf_tstate); 477 regp->r_pc = tf->tf_pc; 478 regp->r_npc = tf->tf_npc; 479 regp->r_y = tf->tf_y; 480 for (i = 0; i < 8; i++) { 481 regp->r_global[i] = tf->tf_global[i]; 482 regp->r_out[i] = tf->tf_out[i]; 483 } 484 /* We should also write out the ins and locals. See signal stuff */ 485 return (0); 486 } 487 488 int 489 netbsd32_process_write_regs(p, regs) 490 struct proc *p; 491 struct reg *regs; 492 { 493 struct reg32* regp = (struct reg32*)regs; 494 struct trapframe64* tf = p->p_md.md_tf; 495 int i; 496 497 tf->tf_pc = regp->r_pc; 498 tf->tf_npc = regp->r_npc; 499 tf->tf_y = regp->r_pc; 500 for (i = 0; i < 8; i++) { 501 tf->tf_global[i] = regp->r_global[i]; 502 tf->tf_out[i] = regp->r_out[i]; 503 } 504 /* We should also read in the ins and locals. See signal stuff */ 505 tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(regp->r_psr); 506 return (0); 507 } 508 509 int 510 netbsd32_process_read_fpregs(p, regs) 511 struct proc *p; 512 struct fpreg *regs; 513 { 514 extern struct fpstate64 initfpstate; 515 struct fpstate64 *statep = &initfpstate; 516 struct fpreg32 *regp = (struct fpreg32 *)regs; 517 int i; 518 519 /* NOTE: struct fpreg == struct fpstate */ 520 if (p->p_md.md_fpstate) 521 statep = p->p_md.md_fpstate; 522 for (i=0; i<32; i++) 523 regp->fr_regs[i] = statep->fs_regs[i]; 524 regp->fr_fsr = statep->fs_fsr; 525 regp->fr_qsize = statep->fs_qsize; 526 for (i=0; i<statep->fs_qsize; i++) 527 regp->fr_queue[i] = statep->fs_queue[i]; 528 529 return 0; 530 } 531 532 int 533 netbsd32_process_write_fpregs(p, regs) 534 struct proc *p; 535 struct fpreg *regs; 536 { 537 extern struct fpstate initfpstate; 538 struct fpstate64 *statep = &initfpstate; 539 struct fpreg32 *regp = (struct fpreg32 *)regs; 540 int i; 541 542 /* NOTE: struct fpreg == struct fpstate */ 543 if (p->p_md.md_fpstate) 544 statep = p->p_md.md_fpstate; 545 for (i=0; i<32; i++) 546 statep->fs_regs[i] = regp->fr_regs[i]; 547 statep->fs_fsr = regp->fr_fsr; 548 statep->fs_qsize = regp->fr_qsize; 549 for (i=0; i<regp->fr_qsize; i++) 550 statep->fs_queue[i] = regp->fr_queue[i]; 551 552 return 0; 553 } 554 #endif 555 556 /* 557 * 32-bit version of cpu_coredump. 558 */ 559 int 560 cpu_coredump32(p, vp, cred, chdr) 561 struct proc *p; 562 struct vnode *vp; 563 struct ucred *cred; 564 struct core32 *chdr; 565 { 566 int i, error; 567 struct md_coredump32 md_core; 568 struct coreseg32 cseg; 569 570 CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0); 571 chdr->c_hdrsize = ALIGN(sizeof(*chdr)); 572 chdr->c_seghdrsize = ALIGN(sizeof(cseg)); 573 chdr->c_cpusize = sizeof(md_core); 574 575 /* Fake a v8 trapframe */ 576 md_core.md_tf.tf_psr = TSTATECCR_TO_PSR(p->p_md.md_tf->tf_tstate); 577 md_core.md_tf.tf_pc = p->p_md.md_tf->tf_pc; 578 md_core.md_tf.tf_npc = p->p_md.md_tf->tf_npc; 579 md_core.md_tf.tf_y = p->p_md.md_tf->tf_y; 580 for (i=0; i<8; i++) { 581 md_core.md_tf.tf_global[i] = p->p_md.md_tf->tf_global[i]; 582 md_core.md_tf.tf_out[i] = p->p_md.md_tf->tf_out[i]; 583 } 584 585 if (p->p_md.md_fpstate) { 586 if (p == fpproc) { 587 savefpstate(p->p_md.md_fpstate); 588 fpproc = NULL; 589 } 590 /* Copy individual fields */ 591 for (i=0; i<32; i++) 592 md_core.md_fpstate.fs_regs[i] = 593 p->p_md.md_fpstate->fs_regs[i]; 594 md_core.md_fpstate.fs_fsr = p->p_md.md_fpstate->fs_fsr; 595 i = md_core.md_fpstate.fs_qsize = p->p_md.md_fpstate->fs_qsize; 596 /* Should always be zero */ 597 while (i--) 598 md_core.md_fpstate.fs_queue[i] = 599 p->p_md.md_fpstate->fs_queue[i]; 600 } else 601 bzero((caddr_t)&md_core.md_fpstate, 602 sizeof(md_core.md_fpstate)); 603 604 CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU); 605 cseg.c_addr = 0; 606 cseg.c_size = chdr->c_cpusize; 607 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize, 608 (off_t)chdr->c_hdrsize, UIO_SYSSPACE, 609 IO_NODELOCKED|IO_UNIT, cred, NULL, p); 610 if (error) 611 return error; 612 613 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&md_core, sizeof(md_core), 614 (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE, 615 IO_NODELOCKED|IO_UNIT, cred, NULL, p); 616 if (!error) 617 chdr->c_nseg++; 618 619 return error; 620 } 621 622 /* 623 * Write out a series of 32-bit firm_events. 624 */ 625 int 626 ev_out32(e, n, uio) 627 struct firm_event *e; 628 int n; 629 struct uio *uio; 630 { 631 struct firm_event32 e32; 632 int error = 0; 633 634 while (n-- && error == 0) { 635 e32.id = e->id; 636 e32.value = e->value; 637 e32.time.tv_sec = e->time.tv_sec; 638 e32.time.tv_usec = e->time.tv_usec; 639 error = uiomove((caddr_t)&e32, sizeof(e32), uio); 640 e++; 641 } 642 return (error); 643 } 644 645 /* 646 * ioctl code 647 */ 648 649 #include <dev/sun/fbio.h> 650 #include <machine/openpromio.h> 651 652 /* from arch/sparc/include/fbio.h */ 653 #if 0 654 /* unused */ 655 #define FBIOGINFO _IOR('F', 2, struct fbinfo) 656 #endif 657 658 struct netbsd32_fbcmap { 659 int index; /* first element (0 origin) */ 660 int count; /* number of elements */ 661 netbsd32_u_charp red; /* red color map elements */ 662 netbsd32_u_charp green; /* green color map elements */ 663 netbsd32_u_charp blue; /* blue color map elements */ 664 }; 665 #if 1 666 #define FBIOPUTCMAP32 _IOW('F', 3, struct netbsd32_fbcmap) 667 #define FBIOGETCMAP32 _IOW('F', 4, struct netbsd32_fbcmap) 668 #endif 669 670 struct netbsd32_fbcursor { 671 short set; /* what to set */ 672 short enable; /* enable/disable cursor */ 673 struct fbcurpos pos; /* cursor's position */ 674 struct fbcurpos hot; /* cursor's hot spot */ 675 struct netbsd32_fbcmap cmap; /* color map info */ 676 struct fbcurpos size; /* cursor's bit map size */ 677 netbsd32_charp image; /* cursor's image bits */ 678 netbsd32_charp mask; /* cursor's mask bits */ 679 }; 680 #if 1 681 #define FBIOSCURSOR32 _IOW('F', 24, struct netbsd32_fbcursor) 682 #define FBIOGCURSOR32 _IOWR('F', 25, struct netbsd32_fbcursor) 683 #endif 684 685 /* from arch/sparc/include/openpromio.h */ 686 struct netbsd32_opiocdesc { 687 int op_nodeid; /* passed or returned node id */ 688 int op_namelen; /* length of op_name */ 689 netbsd32_charp op_name; /* pointer to field name */ 690 int op_buflen; /* length of op_buf (value-result) */ 691 netbsd32_charp op_buf; /* pointer to field value */ 692 }; 693 #if 1 694 #define OPIOCGET32 _IOWR('O', 1, struct netbsd32_opiocdesc) /* get openprom field */ 695 #define OPIOCSET32 _IOW('O', 2, struct netbsd32_opiocdesc) /* set openprom field */ 696 #define OPIOCNEXTPROP32 _IOWR('O', 3, struct netbsd32_opiocdesc) /* get next property */ 697 #endif 698 699 /* prototypes for the converters */ 700 static __inline void 701 netbsd32_to_fbcmap(struct netbsd32_fbcmap *, struct fbcmap *, u_long); 702 static __inline void 703 netbsd32_to_fbcursor(struct netbsd32_fbcursor *, struct fbcursor *, u_long); 704 static __inline void 705 netbsd32_to_opiocdesc(struct netbsd32_opiocdesc *, struct opiocdesc *, u_long); 706 707 static __inline void 708 netbsd32_from_fbcmap(struct fbcmap *, struct netbsd32_fbcmap *); 709 static __inline void 710 netbsd32_from_fbcursor(struct fbcursor *, struct netbsd32_fbcursor *); 711 static __inline void 712 netbsd32_from_opiocdesc(struct opiocdesc *, struct netbsd32_opiocdesc *); 713 714 /* convert to/from different structures */ 715 static __inline void 716 netbsd32_to_fbcmap(s32p, p, cmd) 717 struct netbsd32_fbcmap *s32p; 718 struct fbcmap *p; 719 u_long cmd; 720 { 721 722 p->index = s32p->index; 723 p->count = s32p->count; 724 p->red = (u_char *)(u_long)s32p->red; 725 p->green = (u_char *)(u_long)s32p->green; 726 p->blue = (u_char *)(u_long)s32p->blue; 727 } 728 729 static __inline void 730 netbsd32_to_fbcursor(s32p, p, cmd) 731 struct netbsd32_fbcursor *s32p; 732 struct fbcursor *p; 733 u_long cmd; 734 { 735 736 p->set = s32p->set; 737 p->enable = s32p->enable; 738 p->pos = s32p->pos; 739 p->hot = s32p->hot; 740 netbsd32_to_fbcmap(&s32p->cmap, &p->cmap, cmd); 741 p->size = s32p->size; 742 p->image = (char *)(u_long)s32p->image; 743 p->mask = (char *)(u_long)s32p->mask; 744 } 745 746 static __inline void 747 netbsd32_to_opiocdesc(s32p, p, cmd) 748 struct netbsd32_opiocdesc *s32p; 749 struct opiocdesc *p; 750 u_long cmd; 751 { 752 753 p->op_nodeid = s32p->op_nodeid; 754 p->op_namelen = s32p->op_namelen; 755 p->op_name = (char *)(u_long)s32p->op_name; 756 p->op_buflen = s32p->op_buflen; 757 p->op_buf = (char *)(u_long)s32p->op_buf; 758 } 759 760 static __inline void 761 netbsd32_from_fbcmap(p, s32p) 762 struct fbcmap *p; 763 struct netbsd32_fbcmap *s32p; 764 { 765 766 s32p->index = p->index; 767 s32p->count = p->count; 768 /* filled in */ 769 #if 0 770 s32p->red = (netbsd32_u_charp)p->red; 771 s32p->green = (netbsd32_u_charp)p->green; 772 s32p->blue = (netbsd32_u_charp)p->blue; 773 #endif 774 } 775 776 static __inline void 777 netbsd32_from_fbcursor(p, s32p) 778 struct fbcursor *p; 779 struct netbsd32_fbcursor *s32p; 780 { 781 782 s32p->set = p->set; 783 s32p->enable = p->enable; 784 s32p->pos = p->pos; 785 s32p->hot = p->hot; 786 netbsd32_from_fbcmap(&p->cmap, &s32p->cmap); 787 s32p->size = p->size; 788 /* filled in */ 789 #if 0 790 s32p->image = (netbsd32_charp)p->image; 791 s32p->mask = (netbsd32_charp)p->mask; 792 #endif 793 } 794 795 static __inline void 796 netbsd32_from_opiocdesc(p, s32p) 797 struct opiocdesc *p; 798 struct netbsd32_opiocdesc *s32p; 799 { 800 801 s32p->op_nodeid = p->op_nodeid; 802 s32p->op_namelen = p->op_namelen; 803 s32p->op_name = (netbsd32_charp)(u_long)p->op_name; 804 s32p->op_buflen = p->op_buflen; 805 s32p->op_buf = (netbsd32_charp)(u_long)p->op_buf; 806 } 807 808 int 809 netbsd32_md_ioctl(fp, com, data32, p) 810 struct file *fp; 811 netbsd32_u_long com; 812 caddr_t data32; 813 struct proc *p; 814 { 815 u_int size; 816 caddr_t data, memp = NULL; 817 #define STK_PARAMS 128 818 u_long stkbuf[STK_PARAMS/sizeof(u_long)]; 819 int error; 820 821 switch (com) { 822 case FBIOPUTCMAP32: 823 IOCTL_STRUCT_CONV_TO(FBIOPUTCMAP, fbcmap); 824 case FBIOGETCMAP32: 825 IOCTL_STRUCT_CONV_TO(FBIOGETCMAP, fbcmap); 826 827 case FBIOSCURSOR32: 828 IOCTL_STRUCT_CONV_TO(FBIOSCURSOR, fbcursor); 829 case FBIOGCURSOR32: 830 IOCTL_STRUCT_CONV_TO(FBIOGCURSOR, fbcursor); 831 832 case OPIOCGET32: 833 IOCTL_STRUCT_CONV_TO(OPIOCGET, opiocdesc); 834 case OPIOCSET32: 835 IOCTL_STRUCT_CONV_TO(OPIOCSET, opiocdesc); 836 case OPIOCNEXTPROP32: 837 IOCTL_STRUCT_CONV_TO(OPIOCNEXTPROP, opiocdesc); 838 default: 839 error = (*fp->f_ops->fo_ioctl)(fp, com, data32, p); 840 } 841 if (memp) 842 free(memp, M_IOCTLOPS); 843 return (error); 844 } 845