1/*	$NetBSD: svr4_32_machdep.c,v 1.37 2009/12/10 14:13:52 matt Exp $	 */
2
3/*-
4 * Copyright (c) 1994 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: svr4_32_machdep.c,v 1.37 2009/12/10 14:13:52 matt Exp $");
34
35#ifdef _KERNEL_OPT
36#include "opt_ddb.h"
37#endif
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/namei.h>
42#include <sys/proc.h>
43#include <sys/exec.h>
44#include <sys/filedesc.h>
45#include <sys/ioctl.h>
46#include <sys/kernel.h>
47#include <sys/signal.h>
48#include <sys/signalvar.h>
49#include <sys/malloc.h>
50#include <sys/mount.h>
51#include <sys/syscallargs.h>
52#include <sys/exec_elf.h>
53#include <sys/types.h>
54
55#include <uvm/uvm_param.h>
56
57#include <compat/svr4_32/svr4_32_types.h>
58#include <compat/svr4_32/svr4_32_lwp.h>
59#include <compat/svr4_32/svr4_32_ucontext.h>
60#include <compat/svr4_32/svr4_32_syscallargs.h>
61#include <compat/svr4_32/svr4_32_util.h>
62#include <compat/svr4_32/svr4_32_exec.h>
63#include <compat/netbsd32/netbsd32_exec.h>
64
65#include <machine/cpu.h>
66#include <machine/psl.h>
67#include <machine/reg.h>
68#include <machine/trap.h>
69#include <machine/vmparam.h>
70#include <machine/svr4_machdep.h>
71
72static void svr4_32_getsiginfo(union svr4_32_siginfo *, int, u_long, void *);
73
74void
75svr4_32_setregs(struct lwp *l, struct exec_package *epp, vaddr_t stack)
76{
77	register struct trapframe64 *tf = l->l_md.md_tf;
78
79	netbsd32_setregs(l, epp, stack);
80
81	/* This should be the exit function, not p->p_psstrp. */
82	tf->tf_global[1] = (vaddr_t)0;
83}
84
85#ifdef DEBUG
86#include <sparc64/sparc64/sigdebug.h>
87#endif
88
89#ifdef DEBUG_SVR4
90static void svr4_32_printmcontext(const char *, struct svr4_32_mcontext *);
91
92static void
93svr4_32_printmcontext(const char *fun, struct svr4_32_mcontext *mc)
94{
95	svr4_32_greg_t *r = mc->greg;
96
97	printf("%s at %p\n", fun, mc);
98
99	printf("Regs: ");
100	printf("TSTATE = 0x%x ", r[SVR4_SPARC_PSR]);
101	printf("PC = 0x%x ",  r[SVR4_SPARC_PC]);
102	printf("nPC = 0x%x ", r[SVR4_SPARC_nPC]);
103	printf("Y = 0x%x ",   r[SVR4_SPARC_Y]);
104	printf("G1 = 0x%x ",  r[SVR4_SPARC_G1]);
105	printf("G2 = 0x%x ",  r[SVR4_SPARC_G2]);
106	printf("G3 = 0x%x ",  r[SVR4_SPARC_G3]);
107	printf("G4 = 0x%x ",  r[SVR4_SPARC_G4]);
108	printf("G5 = 0x%x ",  r[SVR4_SPARC_G5]);
109	printf("G6 = 0x%x ",  r[SVR4_SPARC_G6]);
110	printf("G7 = 0x%x ",  r[SVR4_SPARC_G7]);
111	printf("O0 = 0x%x ",  r[SVR4_SPARC_O0]);
112	printf("O1 = 0x%x ",  r[SVR4_SPARC_O1]);
113	printf("O2 = 0x%x ",  r[SVR4_SPARC_O2]);
114	printf("O3 = 0x%x ",  r[SVR4_SPARC_O3]);
115	printf("O4 = 0x%x ",  r[SVR4_SPARC_O4]);
116	printf("O5 = 0x%x ",  r[SVR4_SPARC_O5]);
117	printf("O6 = 0x%x ",  r[SVR4_SPARC_O6]);
118	printf("O7 = 0x%x ",  r[SVR4_SPARC_O7]);
119	printf("\n");
120}
121#endif
122
123void *
124svr4_32_getmcontext(struct lwp *l, struct svr4_32_mcontext *mc,
125	netbsd32_u_long *flags)
126{
127	struct trapframe64 *tf = (struct trapframe64 *)l->l_md.md_tf;
128	svr4_32_greg_t *r = mc->greg;
129#ifdef FPU_CONTEXT
130	svr4_32_fregset_t *f = &mc->freg;
131	struct fpstate *fps = l->l_md.md_fpstate;
132#endif
133
134	write_user_windows();
135	if (rwindow_save(l)) {
136#ifdef DEBUG
137		printf("svr4_32_getcontext: rwindow_save(%p) failed, sending SIGILL\n", l);
138#ifdef DDB
139		Debugger();
140#endif
141#endif
142		mutex_enter(l->l_proc->p_lock);
143		sigexit(l, SIGILL);
144	}
145
146	/*
147	 * Get the general purpose registers
148	 */
149	r[SVR4_SPARC_PSR] = TSTATECCR_TO_PSR(tf->tf_tstate);
150	r[SVR4_SPARC_PC] = tf->tf_pc;
151	r[SVR4_SPARC_nPC] = tf->tf_npc;
152	r[SVR4_SPARC_Y] = tf->tf_y;
153	r[SVR4_SPARC_G1] = tf->tf_global[1];
154	r[SVR4_SPARC_G2] = tf->tf_global[2];
155	r[SVR4_SPARC_G3] = tf->tf_global[3];
156	r[SVR4_SPARC_G4] = tf->tf_global[4];
157	r[SVR4_SPARC_G5] = tf->tf_global[5];
158	r[SVR4_SPARC_G6] = tf->tf_global[6];
159	r[SVR4_SPARC_G7] = tf->tf_global[7];
160	r[SVR4_SPARC_O0] = tf->tf_out[0];
161	r[SVR4_SPARC_O1] = tf->tf_out[1];
162	r[SVR4_SPARC_O2] = tf->tf_out[2];
163	r[SVR4_SPARC_O3] = tf->tf_out[3];
164	r[SVR4_SPARC_O4] = tf->tf_out[4];
165	r[SVR4_SPARC_O5] = tf->tf_out[5];
166	r[SVR4_SPARC_O6] = tf->tf_out[6];
167	r[SVR4_SPARC_O7] = tf->tf_out[7];
168
169	*flags |= SVR4_UC_CPU;
170
171#ifdef FPU_CONTEXT
172	/*
173	 * Get the floating point registers
174	 */
175	/* Note: copies only pre-v9 floating point registers. */
176	memcpy(f->fpu_regs, fps->fs_regs, sizeof(f->fpu_regs));
177	f->fp_nqsize = sizeof(struct fp_qentry);
178	f->fp_nqel = fps->fs_qsize;
179	f->fp_fsr = fps->fs_fsr;
180	if (f->fp_q != NULL) {
181		size_t sz = f->fp_nqel * f->fp_nqsize;
182		if (sz > sizeof(fps->fs_queue)) {
183#ifdef DIAGNOSTIC
184			printf("getcontext: fp_queue too large\n");
185#endif
186			return;
187		}
188		if (copyout(fps->fs_queue, (void *)(u_long)f->fp_q, sz) != 0) {
189#ifdef DIAGNOSTIC
190			printf("getcontext: copy of fp_queue failed %d\n",
191			    error);
192#endif
193			return;
194		}
195	}
196	f->fp_busy = 0;	/* XXX: How do we determine that? */
197	*flags |= SVR4_UC_FPU;
198#endif
199
200
201#ifdef DEBUG_SVR4
202	svr4_32_printmcontext("getmcontext", mc);
203#endif
204	return (void *)(u_long)tf->tf_out[6];
205}
206
207
208/*
209 * Set to mcontext specified.
210 * Return to previous pc and psl as specified by
211 * context left by sendsig. Check carefully to
212 * make sure that the user has not modified the
213 * psl to gain improper privileges or to cause
214 * a machine fault.
215 * This is almost like sigreturn() and it shows.
216 */
217int
218svr4_32_setmcontext(struct lwp *l, struct svr4_32_mcontext *mc,
219	netbsd32_u_long flags)
220{
221	register struct trapframe64 *tf;
222	svr4_32_greg_t *r = mc->greg;
223#ifdef FPU_CONTEXT
224	svr4_32_fregset_t *f = &mc->freg;
225	struct fpstate64 *fps = p->p_md.md_fpstate;
226#endif
227
228#ifdef DEBUG_SVR4
229	svr4_32_printmcontext("setmcontext", uc);
230#endif
231
232	write_user_windows();
233	if (rwindow_save(l)) {
234#ifdef DEBUG
235		printf("svr4_32_setcontext: rwindow_save(%p) failed, sending SIGILL\n", l);
236#ifdef DDB
237		Debugger();
238#endif
239#endif
240		mutex_enter(l->l_proc->p_lock);
241		sigexit(l, SIGILL);
242	}
243
244#ifdef DEBUG
245	if (sigdebug & SDB_FOLLOW)
246		printf("svr4_32_setmcontext: %s[%d], svr4_32_mcontext %p\n",
247		    l->l_proc->p_comm, l->l_proc->p_pid, mc);
248#endif
249
250	if (flags & SVR4_UC_CPU) {
251		/* Restore register context. */
252		tf = (struct trapframe64 *)l->l_md.md_tf;
253
254		/*
255		 * Only the icc bits in the psr are used, so it need not be
256		 * verified.  pc and npc must be multiples of 4.  This is all
257		 * that is required; if it holds, just do it.
258		 */
259		if (((r[SVR4_SPARC_PC] | r[SVR4_SPARC_nPC]) & 3) != 0) {
260			printf("pc or npc are not multiples of 4!\n");
261			return EINVAL;
262		}
263
264		/* take only psr ICC field */
265		tf->tf_tstate = (tf->tf_tstate & ~TSTATE_CCR) |
266		    PSRCC_TO_TSTATE(r[SVR4_SPARC_PSR]);
267		tf->tf_pc = r[SVR4_SPARC_PC];
268		tf->tf_npc = r[SVR4_SPARC_nPC];
269		tf->tf_y = r[SVR4_SPARC_Y];
270
271		/* Restore everything */
272		tf->tf_global[1] = r[SVR4_SPARC_G1];
273		tf->tf_global[2] = r[SVR4_SPARC_G2];
274		tf->tf_global[3] = r[SVR4_SPARC_G3];
275		tf->tf_global[4] = r[SVR4_SPARC_G4];
276		tf->tf_global[5] = r[SVR4_SPARC_G5];
277		tf->tf_global[6] = r[SVR4_SPARC_G6];
278		tf->tf_global[7] = r[SVR4_SPARC_G7];
279
280		tf->tf_out[0] = r[SVR4_SPARC_O0];
281		tf->tf_out[1] = r[SVR4_SPARC_O1];
282		tf->tf_out[2] = r[SVR4_SPARC_O2];
283		tf->tf_out[3] = r[SVR4_SPARC_O3];
284		tf->tf_out[4] = r[SVR4_SPARC_O4];
285		tf->tf_out[5] = r[SVR4_SPARC_O5];
286		tf->tf_out[6] = r[SVR4_SPARC_O6];
287		tf->tf_out[7] = r[SVR4_SPARC_O7];
288	}
289
290
291#ifdef FPU_CONTEXT
292	if (flags & SVR4_UC_FPU) {
293		/*
294		 * Set the floating point registers
295		 */
296		int error;
297		size_t sz = f->fp_nqel * f->fp_nqsize;
298		if (sz > sizeof(fps->fs_queue)) {
299#ifdef DIAGNOSTIC
300			printf("setmcontext: fp_queue too large\n");
301#endif
302			return EINVAL;
303		}
304		/* Note: touches only pre-v9 floating point registers. */
305		memcpy(fps->fs_regs, f->fpu_regs, sizeof(f->fpu_regs));
306		fps->fs_qsize = f->fp_nqel;
307		fps->fs_fsr = f->fp_fsr;
308		if (f->fp_q != 0) {
309			if ((error = copyin((void *)(u_long)f->fp_q,
310			                    fps->fs_queue,
311					    f->fp_nqel * f->fp_nqsize)) != 0) {
312#ifdef DIAGNOSTIC
313				printf("setmcontext: fp_queue copy failed\n");
314#endif
315				return error;
316			}
317		}
318	}
319#endif
320
321	return 0;
322}
323
324/*
325 * map the trap code into the svr4 siginfo as best we can
326 */
327static void
328svr4_32_getsiginfo(union svr4_32_siginfo *si, int sig, u_long code,
329	void *addr)
330{
331	si->si_signo = native_to_svr4_signo[sig];
332	si->si_errno = 0;
333	NETBSD32PTR32(si->si_addr, addr);
334	/*
335	 * we can do this direct map as they are the same as all sparc
336	 * architectures.
337	 */
338	si->si_trap = code;
339	switch (code) {
340	case T_POR:
341	case T_WDR:
342	case T_XIR:
343	case T_SIR:
344	case T_RED_EXCEPTION:
345		si->si_code = 0;
346		break;
347
348	case T_TEXTFAULT:
349		si->si_code = SVR4_BUS_ADRALN;
350		break;
351
352	case T_ILLINST:
353		si->si_code = SVR4_ILL_ILLOPC;
354		break;
355
356	case T_PRIVINST:
357		si->si_code = SVR4_ILL_PRVOPC;
358		break;
359
360	case T_FPDISABLED:
361		si->si_code = SVR4_FPE_FLTINV;
362		break;
363
364	case T_ALIGN:
365		si->si_code = SVR4_BUS_ADRALN;
366		break;
367
368	case T_FP_IEEE_754:
369	case T_FP_OTHER:
370		si->si_code = SVR4_FPE_FLTINV;
371		break;
372
373	case T_DATAFAULT:
374		si->si_code = SVR4_BUS_ADRALN;
375		break;
376
377	case T_TAGOF:
378		si->si_code = SVR4_EMT_TAGOVF;
379		break;
380
381	case T_IDIV0:
382		si->si_code = SVR4_FPE_INTDIV;
383		break;
384
385	case T_INTOF:
386		si->si_code = SVR4_FPE_INTOVF;
387		break;
388
389	case T_BREAKPOINT:
390		si->si_code = SVR4_TRAP_BRKPT;
391		break;
392
393	/*
394	 * XXX - hardware traps with unknown code
395	 */
396	case T_L1INT:
397	case T_L2INT:
398	case T_L3INT:
399	case T_L4INT:
400	case T_L5INT:
401	case T_L6INT:
402	case T_L7INT:
403	case T_L8INT:
404	case T_L9INT:
405	case T_L10INT:
406	case T_L11INT:
407	case T_L12INT:
408	case T_L13INT:
409	case T_L14INT:
410	case T_L15INT:
411		si->si_code = 0;
412		break;
413
414	/*
415	 * XXX - software traps with unknown code
416	 */
417	case T_SUN_SYSCALL:
418	case T_FLUSHWIN:
419	case T_CLEANWIN:
420	case T_RANGECHECK:
421	case T_FIXALIGN:
422	case T_SVR4_SYSCALL:
423	case T_BSD_SYSCALL:
424	case T_KGDB_EXEC:
425		si->si_code = 0;
426		break;
427
428	default:
429		si->si_code = 0;
430#ifdef notyet
431		/*
432		 * XXX: in trap.c, code gets passed the address
433		 * of the fault! not the trap code on SEGV!
434		 */
435#ifdef DIAGNOSTIC
436		printf("sig %d code %ld\n", sig, code);
437		panic("svr4_32_getsiginfo");
438#endif
439#endif
440		break;
441	}
442}
443
444/*
445 * Send an interrupt to process.
446 *
447 * Stack is set up to allow sigcode stored
448 * in u. to call routine. After the handler is
449 * done svr4 will call setcontext for us
450 * with the user context we just set up, and we
451 * will return to the user pc, psl.
452 */
453void
454svr4_32_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
455{
456	int sig = ksi->ksi_signo;
457	register struct lwp *l = curlwp;
458	struct proc *p = l->l_proc;
459	register struct trapframe64 *tf;
460	struct svr4_32_sigframe *fp, frame;
461	int onstack, error;
462	vaddr_t oldsp, newsp, addr;
463	sig_t catcher = SIGACTION(p, sig).sa_handler;
464	sigset_t tmask;
465
466	tf = (struct trapframe64 *)l->l_md.md_tf;
467	oldsp = tf->tf_out[6];
468
469	/* Do we need to jump onto the signal stack? */
470	onstack =
471	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
472	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
473
474	/*
475	 * Allocate space for the signal handler context.
476	 */
477	if (onstack)
478		fp = (struct svr4_32_sigframe *)((char *)l->l_sigstk.ss_sp +
479						l->l_sigstk.ss_size);
480	else
481		fp = (struct svr4_32_sigframe *)oldsp;
482	fp = (struct svr4_32_sigframe *) ((long) (fp - 1) & ~7);
483
484#ifdef DEBUG
485	sigpid = p->p_pid;
486	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
487		printf("svr4_32_sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n",
488		    p->p_comm, p->p_pid, sig, fp, &fp->sf_uc, (void *)(u_long)oldsp);
489#ifdef DDB
490		if (sigdebug & SDB_DDB) Debugger();
491#endif
492	}
493#endif
494	/*
495	 * Build the argument list for the signal handler.
496	 */
497	svr4_32_getsiginfo(&frame.sf_si, sig, ksi->ksi_trap,
498	    (void *)(u_long)tf->tf_pc);
499
500	/* Build stack frame for signal trampoline. */
501	frame.sf_signum = frame.sf_si.si_signo;
502	NETBSD32PTR32(frame.sf_sip, &fp->sf_si);
503	NETBSD32PTR32(frame.sf_ucp, &fp->sf_uc);
504	frame.sf_handler = catcher;
505
506	DPRINTF(("svr4_32_sendsig signum=%d si = %p uc = %p handler = %p\n",
507	         frame.sf_signum, frame.sf_sip,
508		 frame.sf_ucp, frame.sf_handler));
509	/*
510	 * Modify the signal context to be used by sigreturn.
511	 */
512	tmask = *mask;
513	sendsig_reset(l, sig);
514	frame.sf_uc.uc_mcontext.greg[SVR4_SPARC_SP] = oldsp;
515	newsp = (u_long)fp - sizeof(struct rwindow32);
516	mutex_exit(p->p_lock);
517	svr4_32_getcontext(l, &frame.sf_uc, &tmask);
518	write_user_windows();
519
520#ifdef DEBUG
521	if ((sigdebug & SDB_KSTACK))
522	    printf("svr4_32_sendsig: saving sf to %p, setting stack pointer %p to %p\n",
523		   fp, &(((struct rwindow32 *)newsp)->rw_in[6]), (void *)(u_long)oldsp);
524#endif
525	error = (rwindow_save(l) || copyout(&frame, fp, sizeof(frame)) != 0 ||
526	    copyout(&oldsp, &((struct rwindow32 *)newsp)->rw_in[6], sizeof(oldsp)));
527	mutex_enter(p->p_lock);
528
529	if (error) {
530		/*
531		 * Process has trashed its stack; give it an illegal
532		 * instruction to halt it in its tracks.
533		 */
534#ifdef DEBUG
535		mutex_exit(p->p_lock);
536		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
537			printf("svr4_32_sendsig: window save or copyout error\n");
538		printf("svr4_32_sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig);
539#ifdef DDB
540		Debugger();
541#endif
542		mutex_enter(p->p_lock);
543#endif
544		sigexit(l, SIGILL);
545		/* NOTREACHED */
546	}
547
548#ifdef DEBUG
549	if (sigdebug & SDB_FOLLOW) {
550		printf("svr4_32_sendsig: %s[%d] sig %d scp %p\n",
551		       p->p_comm, p->p_pid, sig, &fp->sf_uc);
552	}
553#endif
554	/*
555	 * Build context to run handler in.
556	 */
557	addr = (vaddr_t)p->p_sigctx.ps_sigcode;
558	tf->tf_pc = addr;
559	tf->tf_npc = addr + 4;
560	tf->tf_global[1] = (vaddr_t)catcher;
561	tf->tf_out[6] = newsp;
562
563	/* Remember that we're now on the signal stack. */
564	if (onstack)
565		l->l_sigstk.ss_flags |= SS_ONSTACK;
566#ifdef DEBUG
567	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
568		mutex_exit(p->p_lock);
569		printf("svr4_32_sendsig: about to return to catcher %p thru %p\n",
570		       catcher, (void *)(u_long)addr);
571#ifdef DDB
572		if (sigdebug & SDB_DDB) Debugger();
573#endif
574		mutex_enter(p->p_lock);
575	}
576#endif
577}
578
579
580#define	ADVANCE (n = tf->tf_npc, tf->tf_pc = n, tf->tf_npc = n + 4)
581int
582svr4_32_trap(int type, struct lwp *l)
583{
584	int n;
585	struct proc *p = l->l_proc;
586	struct trapframe64 *tf = l->l_md.md_tf;
587	struct timespec ts;
588	struct timeval tv;
589	struct timeval rtime, stime;
590	uint64_t tm;
591
592	if (p->p_emul != &emul_svr4_32)
593		return 0;
594
595	switch (type) {
596	case T_SVR4_GETCC:
597		uprintf("T_SVR4_GETCC\n");
598		break;
599
600	case T_SVR4_SETCC:
601		uprintf("T_SVR4_SETCC\n");
602		break;
603
604	case T_SVR4_GETPSR:
605		tf->tf_out[0] = TSTATECCR_TO_PSR(tf->tf_tstate);
606		break;
607
608	case T_SVR4_SETPSR:
609		uprintf("T_SVR4_SETPSR\n");
610		break;
611
612	case T_SVR4_GETHRTIME:
613		/*
614		 * This is like gethrtime(3), returning the time expressed
615		 * in nanoseconds since an arbitrary time in the past and
616		 * guaranteed to be monotonically increasing, which we
617		 * obtain from nanouptime(9).
618		 */
619		nanouptime(&ts);
620
621		tm = ts.tv_nsec;
622		tm += ts.tv_sec * (uint64_t)1000000000u;
623		tf->tf_out[0] = (tm >> 32) & 0x00000000ffffffffffUL;
624		tf->tf_out[1] = tm & 0x00000000ffffffffffUL;
625		break;
626
627	case T_SVR4_GETHRVTIME:
628		/*
629		 * This is like gethrvtime(3). returning the LWP's (now:
630		 * proc's) virtual time expressed in nanoseconds. It is
631		 * supposedly guaranteed to be monotonically increasing, but
632		 * for now using the process's real time augmented with its
633		 * current runtime is the best we can do.
634		 */
635		microtime(&tv);
636		bintime2timeval(&l->l_rtime, &rtime);
637		bintime2timeval(&l->l_stime, &stime);
638
639		tm = (rtime.tv_sec + tv.tv_sec - stime.tv_sec) * 1000000ull;
640		tm += rtime.tv_usec + tv.tv_usec;
641		tm -= stime.tv_usec;
642		tm *= 1000u;
643		tf->tf_out[0] = (tm >> 32) & 0x00000000ffffffffffUL;
644		tf->tf_out[1] = tm & 0x00000000ffffffffffUL;
645		break;
646
647	case T_SVR4_GETHRESTIME:
648		/* I assume this is like gettimeofday(3) */
649		nanotime(&ts);
650		tf->tf_out[0] = ts.tv_sec;
651		tf->tf_out[1] = ts.tv_nsec;
652		break;
653
654	default:
655		return 0;
656	}
657
658	ADVANCE;
659	return 1;
660}
661
662/*
663 */
664int
665svr4_32_sys_sysarch(struct lwp *l, const struct svr4_32_sys_sysarch_args *uap, register_t *retval)
666{
667
668	switch (SCARG(uap, op)) {
669	default:
670		printf("(sparc) svr4_32_sysarch(%d)\n", SCARG(uap, op));
671		return EINVAL;
672	}
673}
674
675vaddr_t
676svr4_32_vm_default_addr(struct proc *p, vaddr_t base, vsize_t size)
677{
678	return round_page((vaddr_t)(base) + (vsize_t)MAXDSIZ32);
679}
680