1 /* $NetBSD: netbsd32_time.c,v 1.23 2006/07/23 22:06:09 ad 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 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: netbsd32_time.c,v 1.23 2006/07/23 22:06:09 ad Exp $"); 33 34 #if defined(_KERNEL_OPT) 35 #include "opt_ntp.h" 36 #include "opt_compat_netbsd.h" 37 #endif 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/mount.h> 42 #include <sys/time.h> 43 #include <sys/timex.h> 44 #include <sys/timevar.h> 45 #include <sys/timetc.h> 46 #include <sys/proc.h> 47 #include <sys/pool.h> 48 #include <sys/resourcevar.h> 49 #include <sys/dirent.h> 50 #include <sys/kauth.h> 51 52 #include <compat/netbsd32/netbsd32.h> 53 #include <compat/netbsd32/netbsd32_syscallargs.h> 54 #include <compat/netbsd32/netbsd32_conv.h> 55 56 #ifdef NTP 57 58 int 59 netbsd32_ntp_gettime(l, v, retval) 60 struct lwp *l; 61 void *v; 62 register_t *retval; 63 { 64 struct netbsd32_ntp_gettime_args /* { 65 syscallarg(netbsd32_ntptimevalp_t) ntvp; 66 } */ *uap = v; 67 struct netbsd32_ntptimeval ntv32; 68 struct ntptimeval ntv; 69 int error = 0; 70 71 if (SCARG(uap, ntvp)) { 72 ntp_gettime(&ntv); 73 74 ntv32.time.tv_sec = ntv.time.tv_sec; 75 ntv32.time.tv_nsec = ntv.time.tv_nsec; 76 ntv32.maxerror = (netbsd32_long)ntv.maxerror; 77 ntv32.esterror = (netbsd32_long)ntv.esterror; 78 ntv32.tai = (netbsd32_long)ntv.tai; 79 ntv32.time_state = ntv.time_state; 80 error = copyout((caddr_t)&ntv32, 81 (caddr_t)NETBSD32PTR64(SCARG(uap, ntvp)), sizeof(ntv32)); 82 } 83 if (!error) { 84 *retval = ntp_timestatus(); 85 } 86 87 return (error); 88 } 89 90 #ifdef COMPAT_30 91 int 92 compat_30_netbsd32_ntp_gettime(l, v, retval) 93 struct lwp *l; 94 void *v; 95 register_t *retval; 96 { 97 struct compat_30_netbsd32_ntp_gettime_args /* { 98 syscallarg(netbsd32_ntptimevalp_t) ntvp; 99 } */ *uap = v; 100 struct netbsd32_ntptimeval30 ntv32; 101 struct ntptimeval ntv; 102 int error = 0; 103 104 if (SCARG(uap, ntvp)) { 105 ntp_gettime(&ntv); 106 107 ntv32.time.tv_sec = ntv.time.tv_sec; 108 ntv32.time.tv_usec = ntv.time.tv_nsec / 1000; 109 ntv32.maxerror = (netbsd32_long)ntv.maxerror; 110 ntv32.esterror = (netbsd32_long)ntv.esterror; 111 error = copyout((caddr_t)&ntv32, 112 (caddr_t)NETBSD32PTR64(SCARG(uap, ntvp)), sizeof(ntv32)); 113 } 114 if (!error) { 115 *retval = ntp_timestatus(); 116 } 117 118 return (error); 119 } 120 #endif 121 122 int 123 netbsd32_ntp_adjtime(l, v, retval) 124 struct lwp *l; 125 void *v; 126 register_t *retval; 127 { 128 struct netbsd32_ntp_adjtime_args /* { 129 syscallarg(netbsd32_timexp_t) tp; 130 } */ *uap = v; 131 struct netbsd32_timex ntv32; 132 struct timex ntv; 133 int error = 0; 134 int modes; 135 136 if ((error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, tp)), 137 (caddr_t)&ntv32, sizeof(ntv32)))) 138 return (error); 139 140 netbsd32_to_timex(&ntv32, &ntv); 141 142 /* 143 * Update selected clock variables - only the superuser can 144 * change anything. Note that there is no error checking here on 145 * the assumption the superuser should know what it is doing. 146 */ 147 modes = ntv.modes; 148 if (modes != 0 && (error = kauth_authorize_generic(l->l_cred, 149 KAUTH_GENERIC_ISSUSER, &l->l_acflag))) 150 return (error); 151 152 ntp_adjtime1(&ntv); 153 154 netbsd32_from_timex(&ntv, &ntv32); 155 error = copyout((caddr_t)&ntv32, (caddr_t)NETBSD32PTR64(SCARG(uap, tp)), 156 sizeof(ntv32)); 157 if (!error) { 158 *retval = ntp_timestatus(); 159 } 160 return error; 161 } 162 #else /* !NTP */ 163 int 164 netbsd32_ntp_gettime(l, v, retval) 165 struct lwp *l; 166 void *v; 167 register_t *retval; 168 { 169 170 return (ENOSYS); 171 } 172 173 #ifdef COMPAT_30 174 int 175 compat_30_netbsd32_ntp_gettime(l, v, retval) 176 struct lwp *l; 177 void *v; 178 register_t *retval; 179 { 180 181 return (ENOSYS); 182 } 183 #endif 184 185 int 186 netbsd32_ntp_adjtime(l, v, retval) 187 struct lwp *l; 188 void *v; 189 register_t *retval; 190 { 191 192 return (ENOSYS); 193 } 194 #endif /* NTP */ 195 196 int 197 netbsd32_setitimer(l, v, retval) 198 struct lwp *l; 199 void *v; 200 register_t *retval; 201 { 202 struct netbsd32_setitimer_args /* { 203 syscallarg(int) which; 204 syscallarg(const netbsd32_itimervalp_t) itv; 205 syscallarg(netbsd32_itimervalp_t) oitv; 206 } */ *uap = v; 207 struct proc *p = l->l_proc; 208 struct netbsd32_itimerval s32it, *itv32; 209 int which = SCARG(uap, which); 210 struct netbsd32_getitimer_args getargs; 211 struct itimerval aitv; 212 int error; 213 214 if ((u_int)which > ITIMER_PROF) 215 return (EINVAL); 216 itv32 = (struct netbsd32_itimerval *)NETBSD32PTR64(SCARG(uap, itv)); 217 if (itv32) { 218 if ((error = copyin(itv32, &s32it, sizeof(s32it)))) 219 return (error); 220 netbsd32_to_itimerval(&s32it, &aitv); 221 } 222 if (SCARG(uap, oitv) != 0) { 223 SCARG(&getargs, which) = which; 224 SCARG(&getargs, itv) = SCARG(uap, oitv); 225 if ((error = netbsd32_getitimer(l, &getargs, retval)) != 0) 226 return (error); 227 } 228 if (itv32 == 0) 229 return 0; 230 231 return dosetitimer(p, which, &aitv); 232 } 233 234 int 235 netbsd32_getitimer(l, v, retval) 236 struct lwp *l; 237 void *v; 238 register_t *retval; 239 { 240 struct netbsd32_getitimer_args /* { 241 syscallarg(int) which; 242 syscallarg(netbsd32_itimervalp_t) itv; 243 } */ *uap = v; 244 struct proc *p = l->l_proc; 245 struct netbsd32_itimerval s32it; 246 struct itimerval aitv; 247 int error; 248 249 error = dogetitimer(p, SCARG(uap, which), &aitv); 250 if (error) 251 return error; 252 253 netbsd32_from_itimerval(&aitv, &s32it); 254 return (copyout(&s32it, (caddr_t)NETBSD32PTR64(SCARG(uap, itv)), 255 sizeof(s32it))); 256 } 257 258 int 259 netbsd32_gettimeofday(l, v, retval) 260 struct lwp *l; 261 void *v; 262 register_t *retval; 263 { 264 struct netbsd32_gettimeofday_args /* { 265 syscallarg(netbsd32_timevalp_t) tp; 266 syscallarg(netbsd32_timezonep_t) tzp; 267 } */ *uap = v; 268 struct timeval atv; 269 struct netbsd32_timeval tv32; 270 int error = 0; 271 struct netbsd32_timezone tzfake; 272 273 if (SCARG(uap, tp)) { 274 microtime(&atv); 275 netbsd32_from_timeval(&atv, &tv32); 276 error = copyout(&tv32, (caddr_t)NETBSD32PTR64(SCARG(uap, tp)), 277 sizeof(tv32)); 278 if (error) 279 return (error); 280 } 281 if (SCARG(uap, tzp)) { 282 /* 283 * NetBSD has no kernel notion of time zone, so we just 284 * fake up a timezone struct and return it if demanded. 285 */ 286 tzfake.tz_minuteswest = 0; 287 tzfake.tz_dsttime = 0; 288 error = copyout(&tzfake, 289 (caddr_t)NETBSD32PTR64(SCARG(uap, tzp)), sizeof(tzfake)); 290 } 291 return (error); 292 } 293 294 int 295 netbsd32_settimeofday(l, v, retval) 296 struct lwp *l; 297 void *v; 298 register_t *retval; 299 { 300 struct netbsd32_settimeofday_args /* { 301 syscallarg(const netbsd32_timevalp_t) tv; 302 syscallarg(const netbsd32_timezonep_t) tzp; 303 } */ *uap = v; 304 struct netbsd32_timeval atv32; 305 struct timeval atv; 306 struct timespec ats; 307 int error; 308 struct proc *p = l->l_proc; 309 310 /* Verify all parameters before changing time. */ 311 if ((error = kauth_authorize_generic(l->l_cred, 312 KAUTH_GENERIC_ISSUSER, &l->l_acflag)) != 0) 313 return error; 314 315 /* 316 * NetBSD has no kernel notion of time zone, and only an 317 * obsolete program would try to set it, so we log a warning. 318 */ 319 if (SCARG(uap, tzp)) 320 printf("pid %d attempted to set the " 321 "(obsolete) kernel time zone\n", p->p_pid); 322 323 if (SCARG(uap, tv) == 0) 324 return 0; 325 326 if ((error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, tv)), &atv32, 327 sizeof(atv32))) != 0) 328 return error; 329 330 netbsd32_to_timeval(&atv32, &atv); 331 TIMEVAL_TO_TIMESPEC(&atv, &ats); 332 return settime(p, &ats); 333 } 334 335 int 336 netbsd32_adjtime(l, v, retval) 337 struct lwp *l; 338 void *v; 339 register_t *retval; 340 { 341 struct netbsd32_adjtime_args /* { 342 syscallarg(const netbsd32_timevalp_t) delta; 343 syscallarg(netbsd32_timevalp_t) olddelta; 344 } */ *uap = v; 345 struct netbsd32_timeval atv; 346 int error; 347 348 if ((error = kauth_authorize_generic(l->l_cred, 349 KAUTH_GENERIC_ISSUSER, &l->l_acflag)) != 0) 350 return (error); 351 352 #ifdef __HAVE_TIMECOUNTER 353 { 354 extern int time_adjusted; /* in kern_ntptime.c */ 355 extern int64_t time_adjtime; /* in kern_ntptime.c */ 356 if (SCARG(uap, olddelta)) { 357 atv.tv_sec = time_adjtime / 1000000; 358 atv.tv_usec = time_adjtime % 1000000; 359 if (atv.tv_usec < 0) { 360 atv.tv_usec += 1000000; 361 atv.tv_sec--; 362 } 363 (void) copyout(&atv, 364 (caddr_t)NETBSD32PTR64(SCARG(uap, olddelta)), 365 sizeof(atv)); 366 if (error) 367 return (error); 368 } 369 370 if (SCARG(uap, delta)) { 371 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, delta)), &atv, 372 sizeof(struct timeval)); 373 if (error) 374 return (error); 375 376 time_adjtime = (int64_t)atv.tv_sec * 1000000 + 377 atv.tv_usec; 378 379 if (time_adjtime) 380 /* We need to save the system time during shutdown */ 381 time_adjusted |= 1; 382 } 383 } 384 #else /* !__HAVE_TIMECOUNTER */ 385 { 386 int32_t ndelta, ntickdelta, odelta; 387 extern long bigadj, timedelta; 388 extern int tickdelta; 389 int s; 390 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, delta)), &atv, 391 sizeof(struct timeval)); 392 if (error) 393 return (error); 394 /* 395 * Compute the total correction and the rate at which to apply it. 396 * Round the adjustment down to a whole multiple of the per-tick 397 * delta, so that after some number of incremental changes in 398 * hardclock(), tickdelta will become zero, lest the correction 399 * overshoot and start taking us away from the desired final time. 400 */ 401 ndelta = atv.tv_sec * 1000000 + atv.tv_usec; 402 if (ndelta > bigadj) 403 ntickdelta = 10 * tickadj; 404 else 405 ntickdelta = tickadj; 406 if (ndelta % ntickdelta) 407 ndelta = ndelta / ntickdelta * ntickdelta; 408 409 /* 410 * To make hardclock()'s job easier, make the per-tick delta negative 411 * if we want time to run slower; then hardclock can simply compute 412 * tick + tickdelta, and subtract tickdelta from timedelta. 413 */ 414 if (ndelta < 0) 415 ntickdelta = -ntickdelta; 416 s = splclock(); 417 odelta = timedelta; 418 timedelta = ndelta; 419 tickdelta = ntickdelta; 420 splx(s); 421 422 if (SCARG(uap, olddelta)) { 423 atv.tv_sec = odelta / 1000000; 424 atv.tv_usec = odelta % 1000000; 425 (void) copyout(&atv, 426 (caddr_t)NETBSD32PTR64(SCARG(uap, olddelta)), sizeof(atv)); 427 } 428 } 429 #endif /* !__HAVE_TIMECOUNTER */ 430 return (0); 431 } 432 433 int 434 netbsd32_clock_gettime(l, v, retval) 435 struct lwp *l; 436 void *v; 437 register_t *retval; 438 { 439 struct netbsd32_clock_gettime_args /* { 440 syscallarg(netbsd32_clockid_t) clock_id; 441 syscallarg(netbsd32_timespecp_t) tp; 442 } */ *uap = v; 443 clockid_t clock_id; 444 struct timespec ats; 445 struct netbsd32_timespec ts32; 446 447 clock_id = SCARG(uap, clock_id); 448 if (clock_id != CLOCK_REALTIME) 449 return (EINVAL); 450 451 nanotime(&ats); 452 netbsd32_from_timespec(&ats, &ts32); 453 454 return copyout(&ts32, (caddr_t)NETBSD32PTR64(SCARG(uap, tp)), 455 sizeof(ts32)); 456 } 457 458 int 459 netbsd32_clock_settime(l, v, retval) 460 struct lwp *l; 461 void *v; 462 register_t *retval; 463 { 464 struct netbsd32_clock_settime_args /* { 465 syscallarg(netbsd32_clockid_t) clock_id; 466 syscallarg(const netbsd32_timespecp_t) tp; 467 } */ *uap = v; 468 struct netbsd32_timespec ts32; 469 clockid_t clock_id; 470 struct timespec ats; 471 int error; 472 473 if ((error = kauth_authorize_generic(l->l_cred, 474 KAUTH_GENERIC_ISSUSER, &l->l_acflag)) != 0) 475 return (error); 476 477 clock_id = SCARG(uap, clock_id); 478 if (clock_id != CLOCK_REALTIME) 479 return (EINVAL); 480 481 if ((error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, tp)), &ts32, 482 sizeof(ts32))) != 0) 483 return (error); 484 485 netbsd32_to_timespec(&ts32, &ats); 486 return settime(l->l_proc, &ats); 487 } 488 489 int 490 netbsd32_clock_getres(l, v, retval) 491 struct lwp *l; 492 void *v; 493 register_t *retval; 494 { 495 struct netbsd32_clock_getres_args /* { 496 syscallarg(netbsd32_clockid_t) clock_id; 497 syscallarg(netbsd32_timespecp_t) tp; 498 } */ *uap = v; 499 struct netbsd32_timespec ts32; 500 clockid_t clock_id; 501 struct timespec ts; 502 int error = 0; 503 504 clock_id = SCARG(uap, clock_id); 505 if (clock_id != CLOCK_REALTIME) 506 return (EINVAL); 507 508 if (SCARG(uap, tp)) { 509 ts.tv_sec = 0; 510 ts.tv_nsec = 1000000000 / hz; 511 512 netbsd32_from_timespec(&ts, &ts32); 513 error = copyout(&ts, (caddr_t)NETBSD32PTR64(SCARG(uap, tp)), 514 sizeof(ts)); 515 } 516 517 return error; 518 } 519 520 int 521 netbsd32_nanosleep(l, v, retval) 522 struct lwp *l; 523 void *v; 524 register_t *retval; 525 { 526 struct netbsd32_nanosleep_args /* { 527 syscallarg(const netbsd32_timespecp_t) rqtp; 528 syscallarg(netbsd32_timespecp_t) rmtp; 529 } */ *uap = v; 530 static int nanowait; 531 struct netbsd32_timespec ts32; 532 struct timespec rqt; 533 struct timespec rmt; 534 struct timeval atv, utv, ctime; 535 int error, timo; 536 537 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, rqtp)), (caddr_t)&ts32, 538 sizeof(ts32)); 539 if (error) 540 return (error); 541 542 netbsd32_to_timespec(&ts32, &rqt); 543 TIMESPEC_TO_TIMEVAL(&atv,&rqt); 544 if (itimerfix(&atv)) 545 return (EINVAL); 546 547 getmicrotime(&ctime); 548 timeradd(&atv,&ctime,&atv); 549 timo = hzto(&atv); 550 /* 551 * Avoid inadvertantly sleeping forever 552 */ 553 if (timo == 0) 554 timo = 1; 555 556 error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo); 557 if (error == ERESTART) 558 error = EINTR; 559 if (error == EWOULDBLOCK) 560 error = 0; 561 562 if (SCARG(uap, rmtp)) { 563 int error1; 564 565 getmicrotime(&utv); 566 567 timersub(&atv, &utv, &utv); 568 if (utv.tv_sec < 0) 569 timerclear(&utv); 570 571 TIMEVAL_TO_TIMESPEC(&utv,&rmt); 572 netbsd32_from_timespec(&rmt, &ts32); 573 error1 = copyout(&ts32, 574 NETBSD32PTR64(SCARG(uap,rmtp)), sizeof(ts32)); 575 if (error1) 576 return (error1); 577 } 578 579 return error; 580 } 581 582 static int 583 netbsd32_timer_create_fetch(const void *src, void *dst, size_t size) 584 { 585 struct sigevent *evp = dst; 586 struct netbsd32_sigevent ev32; 587 int error; 588 589 error = copyin(src, &ev32, sizeof(ev32)); 590 if (error) 591 return error; 592 593 netbsd32_to_sigevent(&ev32, evp); 594 return 0; 595 } 596 597 int 598 netbsd32_timer_create(struct lwp *l, void *v, register_t *retval) 599 { 600 struct netbsd32_timer_create_args /* { 601 syscallarg(netbsd32_clockid_t) clock_id; 602 syscallarg(netbsd32_sigeventp_t) evp; 603 syscallarg(netbsd32_timerp_t) timerid; 604 } */ *uap = v; 605 606 return timer_create1(NETBSD32PTR64(SCARG(uap, timerid)), 607 SCARG(uap, clock_id), NETBSD32PTR64(SCARG(uap, evp)), 608 netbsd32_timer_create_fetch, l); 609 } 610 611 int 612 netbsd32_timer_delete(struct lwp *l, void *v, register_t *retval) 613 { 614 struct netbsd32_timer_delete_args /* { 615 syscallarg(netbsd32_timer_t) timerid; 616 } */ *uap = v; 617 struct sys_timer_delete_args ua; 618 619 NETBSD32TO64_UAP(timerid); 620 return sys_timer_delete(l, (void *)&ua, retval); 621 } 622 623 int 624 netbsd32_timer_settime(struct lwp *l, void *v, register_t *retval) 625 { 626 struct netbsd32_timer_settime_args /* { 627 syscallarg(netbsd32_timer_t) timerid; 628 syscallarg(int) flags; 629 syscallarg(const netbsd32_itimerspecp_t) value; 630 syscallarg(netbsd32_itimerspecp_t) ovalue; 631 } */ *uap = v; 632 int error; 633 struct itimerspec value, ovalue, *ovp = NULL; 634 struct netbsd32_itimerspec its32; 635 636 if ((error = copyin(NETBSD32PTR64(SCARG(uap, value)), &its32, 637 sizeof(its32))) != 0) 638 return (error); 639 netbsd32_to_timespec(&its32.it_interval, &value.it_interval); 640 netbsd32_to_timespec(&its32.it_value, &value.it_value); 641 642 if (SCARG(uap, ovalue)) 643 ovp = &ovalue; 644 645 if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp, 646 SCARG(uap, flags), l->l_proc)) != 0) 647 return error; 648 649 if (ovp) { 650 netbsd32_from_timespec(&ovp->it_interval, &its32.it_interval); 651 netbsd32_from_timespec(&ovp->it_value, &its32.it_value); 652 return copyout(&its32, NETBSD32PTR64(SCARG(uap, ovalue)), 653 sizeof(its32)); 654 } 655 return 0; 656 } 657 658 int 659 netbsd32_timer_gettime(struct lwp *l, void *v, register_t *retval) 660 { 661 struct netbsd32_timer_gettime_args /* { 662 syscallarg(netbsd32_timer_t) timerid; 663 syscallarg(netbsd32_itimerspecp_t) value; 664 } */ *uap = v; 665 int error; 666 struct itimerspec its; 667 struct netbsd32_itimerspec its32; 668 669 if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc, 670 &its)) != 0) 671 return error; 672 673 netbsd32_from_timespec(&its.it_interval, &its32.it_interval); 674 netbsd32_from_timespec(&its.it_value, &its32.it_value); 675 676 return copyout(&its32, (caddr_t)NETBSD32PTR64(SCARG(uap, value)), 677 sizeof(its32)); 678 } 679 680 int 681 netbsd32_timer_getoverrun(struct lwp *l, void *v, register_t *retval) 682 { 683 struct netbsd32_timer_getoverrun_args /* { 684 syscallarg(netbsd32_timer_t) timerid; 685 } */ *uap = v; 686 struct sys_timer_getoverrun_args ua; 687 688 NETBSD32TO64_UAP(timerid); 689 return sys_timer_getoverrun(l, (void *)&ua, retval); 690 } 691