xref: /netbsd-src/sys/arch/sparc64/sparc64/netbsd32_machdep.c (revision 3758c7a856ac957fce1bfc439a40b51e6420706e)
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
netbsd32_setregs(struct lwp * l,struct exec_package * pack,vaddr_t stack)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
netbsd32_sendsig_siginfo(const ksiginfo_t * ksi,const sigset_t * mask)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
netbsd32_process_read_regs(struct lwp * l,struct reg32 * regs)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
netbsd32_process_write_regs(struct lwp * l,const struct reg32 * regs)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
netbsd32_process_read_fpregs(struct lwp * l,struct fpreg32 * regs,size_t * sz)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
netbsd32_process_write_fpregs(struct lwp * l,const struct fpreg32 * regs,size_t sz)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
cpu_coredump32(struct lwp * l,struct coredump_iostate * iocookie,struct core32 * chdr)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
netbsd32_cpu_getmcontext(struct lwp * l,mcontext_t * mcp,unsigned int * flags)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
netbsd32_cpu_setmcontext(struct lwp * l,mcontext_t * mcp,unsigned int flags)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
ev_out32(struct firm_event * e,int n,struct uio * uio)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
netbsd32_to_fbcmap(struct netbsd32_fbcmap * s32p,struct fbcmap * p,u_long cmd)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
netbsd32_to_fbcursor(struct netbsd32_fbcursor * s32p,struct fbcursor * p,u_long cmd)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
netbsd32_to_opiocdesc(struct netbsd32_opiocdesc * s32p,struct opiocdesc * p,u_long cmd)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
netbsd32_from_fbcmap(struct fbcmap * p,struct netbsd32_fbcmap * s32p,u_long cmd)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
netbsd32_from_fbcursor(struct fbcursor * p,struct netbsd32_fbcursor * s32p,u_long cmd)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
netbsd32_from_opiocdesc(struct opiocdesc * p,struct netbsd32_opiocdesc * s32p,u_long cmd)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
netbsd32_md_ioctl(struct file * fp,netbsd32_u_long cmd,void * data32,struct lwp * l)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
netbsd32_sysarch(struct lwp * l,const struct netbsd32_sysarch_args * uap,register_t * retval)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
cpu_mcontext32_validate(struct lwp * l,const mcontext32_t * mc)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
cpu_setmcontext32(struct lwp * l,const mcontext32_t * mcp,unsigned int flags)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
cpu_getmcontext32(struct lwp * l,mcontext32_t * mcp,unsigned int * flags)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
startlwp32(void * arg)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
netbsd32_vm_default_addr(struct proc * p,vaddr_t base,vsize_t size,int topdown)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 *
netbsd32_machine32(void)1006 netbsd32_machine32(void)
1007 {
1008 
1009 	return machine32;
1010 }
1011 
1012 void
netbsd32_machdep_md_init(void)1013 netbsd32_machdep_md_init(void)
1014 {
1015 
1016 	MODULE_HOOK_SET(netbsd32_machine32_hook, netbsd32_machine32);
1017 }
1018 
1019 void
netbsd32_machdep_md_fini(void)1020 netbsd32_machdep_md_fini(void)
1021 {
1022 
1023 	MODULE_HOOK_UNSET(netbsd32_machine32_hook);
1024 }
1025