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