Home | History | Annotate | Line # | Download | only in sparc64
      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