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