1/*	$NetBSD: svr4_machdep.c,v 1.54 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_machdep.c,v 1.54 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 <compat/svr4/svr4_types.h>
56#include <compat/svr4/svr4_lwp.h>
57#include <compat/svr4/svr4_ucontext.h>
58#include <compat/svr4/svr4_syscallargs.h>
59#include <compat/svr4/svr4_util.h>
60#include <compat/svr4/svr4_exec.h>
61
62#include <machine/cpu.h>
63#include <machine/psl.h>
64#include <machine/reg.h>
65#include <machine/frame.h>
66#include <machine/trap.h>
67#include <machine/vmparam.h>
68#include <machine/svr4_machdep.h>
69
70static void svr4_getsiginfo(union svr4_siginfo *, int, u_long, void *);
71
72void
73svr4_setregs(struct lwp *l, struct exec_package *epp, vaddr_t stack)
74{
75	register struct trapframe64 *tf = l->l_md.md_tf;
76
77	setregs(l, epp, stack);
78
79	/* This should be the exit function, not p->p_psstrp. */
80	tf->tf_global[1] = (vaddr_t)0;
81}
82
83#ifdef DEBUG
84#include <sparc64/sparc64/sigdebug.h>
85#endif
86
87#ifdef DEBUG_SVR4
88static void svr4_printmcontext(const char *, struct svr4_mcontext *);
89
90static void
91svr4_printmcontext(const char *fun, struct svr4_mcontext *mc)
92{
93	svr4_greg_t *r = mc->greg;
94
95	printf("%s at %p\n", fun, mc);
96
97	printf("Regs: ");
98#ifdef __arch64__
99	printf("CCR = 0x%lx ", r[SVR4_SPARC_CCR]);
100#else
101	printf("PSR = 0x%lx ", r[SVR4_SPARC_PSR]);
102#endif
103	printf("PC = 0x%lx ",  r[SVR4_SPARC_PC]);
104	printf("nPC = 0x%lx ", r[SVR4_SPARC_nPC]);
105	printf("Y = 0x%lx ",   r[SVR4_SPARC_Y]);
106	printf("G1 = 0x%lx ",  r[SVR4_SPARC_G1]);
107	printf("G2 = 0x%lx ",  r[SVR4_SPARC_G2]);
108	printf("G3 = 0x%lx ",  r[SVR4_SPARC_G3]);
109	printf("G4 = 0x%lx ",  r[SVR4_SPARC_G4]);
110	printf("G5 = 0x%lx ",  r[SVR4_SPARC_G5]);
111	printf("G6 = 0x%lx ",  r[SVR4_SPARC_G6]);
112	printf("G7 = 0x%lx ",  r[SVR4_SPARC_G7]);
113	printf("O0 = 0x%lx ",  r[SVR4_SPARC_O0]);
114	printf("O1 = 0x%lx ",  r[SVR4_SPARC_O1]);
115	printf("O2 = 0x%lx ",  r[SVR4_SPARC_O2]);
116	printf("O3 = 0x%lx ",  r[SVR4_SPARC_O3]);
117	printf("O4 = 0x%lx ",  r[SVR4_SPARC_O4]);
118	printf("O5 = 0x%lx ",  r[SVR4_SPARC_O5]);
119	printf("O6 = 0x%lx ",  r[SVR4_SPARC_O6]);
120	printf("O7 = 0x%lx ",  r[SVR4_SPARC_O7]);
121#ifdef __arch64__
122	printf("ASI = 0x%lx ",  r[SVR4_SPARC_ASI]);
123	printf("FPRS = 0x%lx ",  r[SVR4_SPARC_FPRS]);
124#endif
125	printf("\n");
126}
127#endif
128
129void *
130svr4_getmcontext(struct lwp *l, struct svr4_mcontext *mc, u_long *flags)
131{
132	struct trapframe64 *tf = (struct trapframe64 *)l->l_md.md_tf;
133	svr4_greg_t *r = mc->greg;
134#ifdef FPU_CONTEXT
135	svr4_fregset_t *f = &mc->freg;
136	struct fpstate *fps = l->l_md.md_fpstate;
137#endif
138
139	write_user_windows();
140	if (rwindow_save(l)) {
141#ifdef DEBUG
142		printf("svr4_getcontext: rwindow_save(%p) failed, sending SIGILL\n", l->l_proc);
143#ifdef DDB
144		Debugger();
145#endif
146#endif
147		mutex_enter(l->l_proc->p_lock);
148		sigexit(l, SIGILL);
149	}
150
151	/*
152	 * Get the general purpose registers
153	 */
154#ifdef __arch64__
155	r[SVR4_SPARC_CCR] = (tf->tf_tstate & TSTATE_CCR) >> TSTATE_CCR_SHIFT;
156#else
157	r[SVR4_SPARC_PSR] = TSTATECCR_TO_PSR(tf->tf_tstate);
158#endif
159	r[SVR4_SPARC_PC] = tf->tf_pc;
160	r[SVR4_SPARC_nPC] = tf->tf_npc;
161	r[SVR4_SPARC_Y] = tf->tf_y;
162	r[SVR4_SPARC_G1] = tf->tf_global[1];
163	r[SVR4_SPARC_G2] = tf->tf_global[2];
164	r[SVR4_SPARC_G3] = tf->tf_global[3];
165	r[SVR4_SPARC_G4] = tf->tf_global[4];
166	r[SVR4_SPARC_G5] = tf->tf_global[5];
167	r[SVR4_SPARC_G6] = tf->tf_global[6];
168	r[SVR4_SPARC_G7] = tf->tf_global[7];
169	r[SVR4_SPARC_O0] = tf->tf_out[0];
170	r[SVR4_SPARC_O1] = tf->tf_out[1];
171	r[SVR4_SPARC_O2] = tf->tf_out[2];
172	r[SVR4_SPARC_O3] = tf->tf_out[3];
173	r[SVR4_SPARC_O4] = tf->tf_out[4];
174	r[SVR4_SPARC_O5] = tf->tf_out[5];
175	r[SVR4_SPARC_O6] = tf->tf_out[6];
176	r[SVR4_SPARC_O7] = tf->tf_out[7];
177#ifdef __arch64__
178	r[SVR4_SPARC_ASI] = (tf->tf_tstate & TSTATE_ASI) >> TSTATE_ASI_SHIFT;
179#endif
180
181	*flags |= SVR4_UC_CPU;
182
183#ifdef FPU_CONTEXT
184	/*
185	 * Get the floating point registers
186	 */
187	memcpy(f->fpu_regs, fps->fs_regs, sizeof(f->fpu_regs));
188	f->fp_nqsize = sizeof(struct fp_qentry);
189	f->fp_nqel = fps->fs_qsize;
190	f->fp_fsr = fps->fs_fsr;
191	if (f->fp_q != NULL) {
192		size_t sz = f->fp_nqel * f->fp_nqsize;
193		if (sz > sizeof(fps->fs_queue)) {
194#ifdef DIAGNOSTIC
195			printf("getcontext: fp_queue too large\n");
196#endif
197			return;
198		}
199		if (copyout(fps->fs_queue, f->fp_q, sz) != 0) {
200#ifdef DIAGNOSTIC
201			printf("getcontext: copy of fp_queue failed %d\n",
202			    error);
203#endif
204			return;
205		}
206	}
207	f->fp_busy = 0;	/* XXX: How do we determine that? */
208	*flags |= SVR4_UC_FPU;
209#endif
210
211
212#ifdef DEBUG_SVR4
213	svr4_printmcontext("getmcontext", mc);
214#endif
215	return (void *)(u_long)tf->tf_out[6];
216}
217
218
219/*
220 * Set to mcontext specified.
221 * Return to previous pc and psl as specified by
222 * context left by sendsig. Check carefully to
223 * make sure that the user has not modified the
224 * psl to gain improper privileges or to cause
225 * a machine fault.
226 * This is almost like sigreturn() and it shows.
227 */
228int
229svr4_setmcontext(struct lwp *l, struct svr4_mcontext *mc, u_long flags)
230{
231	register struct trapframe64 *tf;
232	svr4_greg_t *r = mc->greg;
233#ifdef FPU_CONTEXT
234	svr4_fregset_t *f = &mc->freg;
235	struct fpstate64 *fps = l->l_md.md_fpstate;
236#endif
237
238#ifdef DEBUG_SVR4
239	svr4_printmcontext("setmcontext", uc);
240#endif
241
242	write_user_windows();
243	if (rwindow_save(l)) {
244#ifdef DEBUG
245		printf("svr4_setcontext: rwindow_save(%p) failed, sending SIGILL\n", l->l_proc);
246#ifdef DDB
247		Debugger();
248#endif
249#endif
250		mutex_enter(l->l_proc->p_lock);
251		sigexit(l, SIGILL);
252	}
253
254#ifdef DEBUG
255	if (sigdebug & SDB_FOLLOW)
256		printf("svr4_setmcontext: %s[%d], svr4_mcontext %p\n",
257		    l->l_proc->p_comm, l->l_proc->p_pid, mc);
258#endif
259
260	if (flags & SVR4_UC_CPU) {
261		/* Restore register context. */
262		tf = (struct trapframe64 *)l->l_md.md_tf;
263
264		/*
265		 * Only the icc bits in the psr are used, so it need not be
266		 * verified.  pc and npc must be multiples of 4.  This is all
267		 * that is required; if it holds, just do it.
268		 */
269		if (((r[SVR4_SPARC_PC] | r[SVR4_SPARC_nPC]) & 3) != 0) {
270			printf("pc or npc are not multiples of 4!\n");
271			return EINVAL;
272		}
273
274#ifdef __arch64__
275		/* take only tstate ASI and CCR fields */
276		tf->tf_tstate = (tf->tf_tstate & ~(TSTATE_CCR | TSTATE_ASI)) |
277		    ((r[SVR4_SPARC_CCR] << TSTATE_CCR_SHIFT) & TSTATE_CCR) |
278		    ((r[SVR4_SPARC_ASI] << TSTATE_ASI_SHIFT) & TSTATE_ASI);
279#else
280		/* take only tstate CCR field */
281		tf->tf_tstate = (tf->tf_tstate & ~TSTATE_CCR) |
282		    PSRCC_TO_TSTATE(r[SVR4_SPARC_PSR]);
283#endif
284		tf->tf_pc = r[SVR4_SPARC_PC];
285		tf->tf_npc = r[SVR4_SPARC_nPC];
286		tf->tf_y = r[SVR4_SPARC_Y];
287
288		/* Restore everything */
289		tf->tf_global[1] = r[SVR4_SPARC_G1];
290		tf->tf_global[2] = r[SVR4_SPARC_G2];
291		tf->tf_global[3] = r[SVR4_SPARC_G3];
292		tf->tf_global[4] = r[SVR4_SPARC_G4];
293		tf->tf_global[5] = r[SVR4_SPARC_G5];
294		tf->tf_global[6] = r[SVR4_SPARC_G6];
295		tf->tf_global[7] = r[SVR4_SPARC_G7];
296
297		tf->tf_out[0] = r[SVR4_SPARC_O0];
298		tf->tf_out[1] = r[SVR4_SPARC_O1];
299		tf->tf_out[2] = r[SVR4_SPARC_O2];
300		tf->tf_out[3] = r[SVR4_SPARC_O3];
301		tf->tf_out[4] = r[SVR4_SPARC_O4];
302		tf->tf_out[5] = r[SVR4_SPARC_O5];
303		tf->tf_out[6] = r[SVR4_SPARC_O6];
304		tf->tf_out[7] = r[SVR4_SPARC_O7];
305
306		/* SVR4_SPARC_ASI restored above */
307	}
308
309
310#ifdef FPU_CONTEXT
311	if (flags & SVR4_UC_FPU) {
312		/*
313		 * Set the floating point registers
314		 */
315		int error;
316		size_t sz = f->fp_nqel * f->fp_nqsize;
317		if (sz > sizeof(fps->fs_queue)) {
318#ifdef DIAGNOSTIC
319			printf("setmcontext: fp_queue too large\n");
320#endif
321			return EINVAL;
322		}
323		/* Note: only copy as much FP registers as in the mcontext. */
324		memcpy(fps->fs_regs, f->fpu_regs, sizeof(f->fpu_regs));
325		fps->fs_qsize = f->fp_nqel;
326		fps->fs_fsr = f->fp_fsr;
327		if (f->fp_q != NULL) {
328			if ((error = copyin(f->fp_q, fps->fs_queue,
329					    f->fp_nqel * f->fp_nqsize)) != 0) {
330#ifdef DIAGNOSTIC
331				printf("setmcontext: fp_queue copy failed\n");
332#endif
333				return error;
334			}
335		}
336	}
337#endif
338
339	return 0;
340}
341
342/*
343 * map the trap code into the svr4 siginfo as best we can
344 */
345static void
346svr4_getsiginfo(union svr4_siginfo *si, int sig, u_long code, void *addr)
347{
348	si->si_signo = native_to_svr4_signo[sig];
349	si->si_errno = 0;
350	si->si_addr  = addr;
351	/*
352	 * we can do this direct map as they are the same as all sparc
353	 * architectures.
354	 */
355	si->si_trap = code;
356	switch (code) {
357	case T_POR:
358	case T_WDR:
359	case T_XIR:
360	case T_SIR:
361	case T_RED_EXCEPTION:
362		si->si_code = 0;
363		break;
364
365	case T_TEXTFAULT:
366		si->si_code = SVR4_BUS_ADRALN;
367		break;
368
369	case T_ILLINST:
370		si->si_code = SVR4_ILL_ILLOPC;
371		break;
372
373	case T_PRIVINST:
374		si->si_code = SVR4_ILL_PRVOPC;
375		break;
376
377	case T_FPDISABLED:
378		si->si_code = SVR4_FPE_FLTINV;
379		break;
380
381	case T_ALIGN:
382		si->si_code = SVR4_BUS_ADRALN;
383		break;
384
385	case T_FP_IEEE_754:
386	case T_FP_OTHER:
387		si->si_code = SVR4_FPE_FLTINV;
388		break;
389
390	case T_DATAFAULT:
391		si->si_code = SVR4_BUS_ADRALN;
392		break;
393
394	case T_TAGOF:
395		si->si_code = SVR4_EMT_TAGOVF;
396		break;
397
398	case T_IDIV0:
399		si->si_code = SVR4_FPE_INTDIV;
400		break;
401
402	case T_INTOF:
403		si->si_code = SVR4_FPE_INTOVF;
404		break;
405
406	case T_BREAKPOINT:
407		si->si_code = SVR4_TRAP_BRKPT;
408		break;
409
410	/*
411	 * XXX - hardware traps with unknown code
412	 */
413	case T_L1INT:
414	case T_L2INT:
415	case T_L3INT:
416	case T_L4INT:
417	case T_L5INT:
418	case T_L6INT:
419	case T_L7INT:
420	case T_L8INT:
421	case T_L9INT:
422	case T_L10INT:
423	case T_L11INT:
424	case T_L12INT:
425	case T_L13INT:
426	case T_L14INT:
427	case T_L15INT:
428		si->si_code = 0;
429		break;
430
431	/*
432	 * XXX - software traps with unknown code
433	 */
434	case T_SUN_SYSCALL:
435	case T_FLUSHWIN:
436	case T_CLEANWIN:
437	case T_RANGECHECK:
438	case T_FIXALIGN:
439	case T_SVR4_SYSCALL:
440	case T_BSD_SYSCALL:
441	case T_KGDB_EXEC:
442		si->si_code = 0;
443		break;
444
445	default:
446		si->si_code = 0;
447#ifdef notyet
448		/*
449		 * XXX: in trap.c, code gets passed the address
450		 * of the fault! not the trap code on SEGV!
451		 */
452#ifdef DIAGNOSTIC
453		printf("sig %d code %ld\n", sig, code);
454		panic("svr4_getsiginfo");
455#endif
456#endif
457		break;
458	}
459}
460
461/*
462 * Send an interrupt to process.
463 *
464 * Stack is set up to allow sigcode stored
465 * in u. to call routine. After the handler is
466 * done svr4 will call setcontext for us
467 * with the user context we just set up, and we
468 * will return to the user pc, psl.
469 */
470#ifdef __arch64__
471#define STACK_OFFSET	BIAS
472#define CPOUTREG(l,v)	copyout(&(v), (l), sizeof(v))
473#undef CCFSZ
474#define CCFSZ	CC64FSZ
475#define rwindow	rwindow64
476#else
477#define STACK_OFFSET	0
478#define CPOUTREG(l,v)	copyout(&(v), (l), sizeof(v))
479#define rwindow	rwindow32
480#endif
481
482void
483svr4_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
484{
485	int sig = ksi->ksi_signo;
486	register struct lwp *l = curlwp;
487	struct proc *p = l->l_proc;
488	register struct trapframe64 *tf;
489	struct svr4_sigframe *fp, frame;
490	int onstack, error;
491	vaddr_t oldsp, newsp, addr;
492	sig_t catcher = SIGACTION(p, sig).sa_handler;
493
494	tf = (struct trapframe64 *)l->l_md.md_tf;
495	oldsp = tf->tf_out[6] + STACK_OFFSET;
496
497	/* Do we need to jump onto the signal stack? */
498	onstack =
499	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
500	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
501
502	/*
503	 * Allocate space for the signal handler context.
504	 */
505	if (onstack)
506		fp = (struct svr4_sigframe *)((char *)l->l_sigstk.ss_sp +
507						l->l_sigstk.ss_size);
508	else
509		fp = (struct svr4_sigframe *)oldsp;
510	fp = (struct svr4_sigframe *) ((long) (fp - 1) & ~0x0f);
511
512#ifdef DEBUG
513	sigpid = p->p_pid;
514	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
515		printf("svr4_sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n",
516		    p->p_comm, p->p_pid, sig, fp, &fp->sf_uc, (void *)(u_long)oldsp);
517#ifdef DDB
518		if (sigdebug & SDB_DDB) Debugger();
519#endif
520	}
521#endif
522	/*
523	 * Build the argument list for the signal handler.
524	 */
525	svr4_getsiginfo(&frame.sf_si, sig, ksi->ksi_trap,
526	    (void *)(u_long)tf->tf_pc);
527
528	/* Build stack frame for signal trampoline. */
529	frame.sf_signum = frame.sf_si.si_signo;
530	frame.sf_sip = &fp->sf_si;
531	frame.sf_ucp = &fp->sf_uc;
532	frame.sf_handler = catcher;
533
534	DPRINTF(("svr4_sendsig signum=%d si = %p uc = %p handler = %p\n",
535	         frame.sf_signum, frame.sf_sip,
536		 frame.sf_ucp, frame.sf_handler));
537	/*
538	 * Modify the signal context to be used by sigreturn.
539	 */
540	sendsig_reset(l, sig);
541	mutex_exit(p->p_lock);
542	svr4_getcontext(l, &frame.sf_uc);
543	frame.sf_uc.uc_mcontext.greg[SVR4_SPARC_SP] = (long)tf->tf_out[6];
544
545	newsp = (u_long)fp - sizeof(struct rwindow);
546	write_user_windows();
547
548#ifdef DEBUG
549	if ((sigdebug & SDB_KSTACK))
550	    printf("svr4_sendsig: saving sf to %p, setting stack pointer %p to %p\n",
551		   fp, &(((struct rwindow *)newsp)->rw_in[6]), (void *)(u_long)oldsp);
552#endif
553	error = (rwindow_save(l) || copyout(&frame, fp, sizeof(frame)) != 0 ||
554	    CPOUTREG(&((struct rwindow *)newsp)->rw_in[6], oldsp));
555	mutex_enter(p->p_lock);
556
557	if (error) {
558		/*
559		 * Process has trashed its stack; give it an illegal
560		 * instruction to halt it in its tracks.
561		 */
562#ifdef DEBUG
563		mutex_exit(p->p_lock);
564		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
565			printf("svr4_sendsig: window save or copyout error\n");
566		printf("svr4_sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig);
567#ifdef DDB
568		Debugger();
569#endif
570		mutex_enter(p->p_lock);
571#endif
572		sigexit(l, SIGILL);
573		/* NOTREACHED */
574	}
575
576#ifdef DEBUG
577	if (sigdebug & SDB_FOLLOW) {
578		printf("svr4_sendsig: %s[%d] sig %d scp %p\n",
579		       p->p_comm, p->p_pid, sig, &fp->sf_uc);
580	}
581#endif
582	/*
583	 * Build context to run handler in.
584	 */
585	addr = (vaddr_t)p->p_sigctx.ps_sigcode;
586	tf->tf_pc = addr;
587	tf->tf_npc = addr + 4;
588	tf->tf_global[1] = (vaddr_t)catcher;
589	tf->tf_out[6] = newsp;
590
591	/* Remember that we're now on the signal stack. */
592	if (onstack)
593		l->l_sigstk.ss_flags |= SS_ONSTACK;
594#ifdef DEBUG
595	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
596		mutex_exit(p->p_lock);
597		printf("svr4_sendsig: about to return to catcher %p thru %p\n",
598		       catcher, (void *)(u_long)addr);
599#ifdef DDB
600		if (sigdebug & SDB_DDB) Debugger();
601#endif
602		mutex_enter(p->p_lock);
603	}
604#endif
605}
606
607
608#define	ADVANCE (n = tf->tf_npc, tf->tf_pc = n, tf->tf_npc = n + 4)
609int
610svr4_trap(int type, struct lwp *l)
611{
612	struct proc *p = l->l_proc;
613	int n;
614	struct trapframe64 *tf = l->l_md.md_tf;
615	struct timespec ts;
616	struct timeval tv;
617	struct timeval rtime, stime;
618	uint64_t tm;
619
620	if (p->p_emul != &emul_svr4)
621		return 0;
622
623	switch (type) {
624	case T_SVR4_GETCC:
625		uprintf("T_SVR4_GETCC\n");
626		break;
627
628	case T_SVR4_SETCC:
629		uprintf("T_SVR4_SETCC\n");
630		break;
631
632	case T_SVR4_GETPSR:
633		tf->tf_out[0] = TSTATECCR_TO_PSR(tf->tf_tstate);
634		break;
635
636	case T_SVR4_SETPSR:
637		uprintf("T_SVR4_SETPSR\n");
638		break;
639
640	case T_SVR4_GETHRTIME:
641		/*
642		 * This is like gethrtime(3), returning the time expressed
643		 * in nanoseconds since an arbitrary time in the past and
644		 * guaranteed to be monotonically increasing, which we
645		 * obtain from nanouptime()
646		 */
647		nanouptime(&ts);
648
649		tm = ts.tv_nsec;
650		tm += ts.tv_sec * (uint64_t)1000000000u;
651		tf->tf_out[0] = (tm >> 32) & 0x00000000ffffffffUL;
652		tf->tf_out[1] = tm & 0x00000000ffffffffUL;
653		break;
654
655	case T_SVR4_GETHRVTIME:
656		/*
657		 * This is like gethrvtime(3). returning the LWP's (now:
658		 * proc's) virtual time expressed in nanoseconds. It is
659		 * supposedly guaranteed to be monotonically increasing, but
660		 * for now using the process's real time augmented with its
661		 * current runtime is the best we can do.
662		 */
663		microtime(&tv);
664		bintime2timeval(&l->l_rtime, &rtime);
665		bintime2timeval(&l->l_stime, &stime);
666
667		tm = (rtime.tv_sec + tv.tv_sec - stime.tv_sec) * 1000000ull;
668		tm += rtime.tv_usec + tv.tv_usec;
669		tm -= stime.tv_usec;
670		tm *= 1000u;
671		tf->tf_out[0] = (tm >> 32) & 0x00000000ffffffffUL;
672		tf->tf_out[1] = tm & 0x00000000ffffffffUL;
673		break;
674
675	case T_SVR4_GETHRESTIME:
676		/* I assume this is like gettimeofday(3) */
677		nanotime(&ts);
678		tf->tf_out[0] = ts.tv_sec;
679		tf->tf_out[1] = ts.tv_nsec;
680		break;
681
682	default:
683		return 0;
684	}
685
686	ADVANCE;
687	return 1;
688}
689
690/*
691 */
692int
693svr4_sys_sysarch(struct lwp *l, const struct svr4_sys_sysarch_args *uap, register_t *retval)
694{
695
696	switch (SCARG(uap, op)) {
697	default:
698		printf("(sparc64) svr4_sysarch(%d)\n", SCARG(uap, op));
699		return EINVAL;
700	}
701}
702
703void
704svr4_md_init(void)
705{
706
707}
708
709void
710svr4_md_fini(void)
711{
712
713}
714