netbsd32_time.c revision 1.19.2.2 1 /* $NetBSD: netbsd32_time.c,v 1.19.2.2 2006/06/26 12:46:19 yamt 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.19.2.2 2006/06/26 12:46:19 yamt 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 struct proc *p = l->l_proc;
136
137 if ((error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, tp)),
138 (caddr_t)&ntv32, sizeof(ntv32))))
139 return (error);
140
141 netbsd32_to_timex(&ntv32, &ntv);
142
143 /*
144 * Update selected clock variables - only the superuser can
145 * change anything. Note that there is no error checking here on
146 * the assumption the superuser should know what it is doing.
147 */
148 modes = ntv.modes;
149 if (modes != 0 && (error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, &p->p_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(p->p_cred, KAUTH_GENERIC_ISSUSER, &p->p_acflag)) != 0)
312 return error;
313
314 /*
315 * NetBSD has no kernel notion of time zone, and only an
316 * obsolete program would try to set it, so we log a warning.
317 */
318 if (SCARG(uap, tzp))
319 printf("pid %d attempted to set the "
320 "(obsolete) kernel time zone\n", p->p_pid);
321
322 if (SCARG(uap, tv) == 0)
323 return 0;
324
325 if ((error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, tv)), &atv32,
326 sizeof(atv32))) != 0)
327 return error;
328
329 netbsd32_to_timeval(&atv32, &atv);
330 TIMEVAL_TO_TIMESPEC(&atv, &ats);
331 return settime(p, &ats);
332 }
333
334 int
335 netbsd32_adjtime(l, v, retval)
336 struct lwp *l;
337 void *v;
338 register_t *retval;
339 {
340 struct netbsd32_adjtime_args /* {
341 syscallarg(const netbsd32_timevalp_t) delta;
342 syscallarg(netbsd32_timevalp_t) olddelta;
343 } */ *uap = v;
344 struct netbsd32_timeval atv;
345 int error;
346 struct proc *p = l->l_proc;
347
348 if ((error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, &p->p_acflag)) != 0)
349 return (error);
350 #ifdef __HAVE_TIMECOUNTER
351 {
352 extern int time_adjusted; /* in kern_ntptime.c */
353 extern int64_t time_adjtime; /* in kern_ntptime.c */
354 if (SCARG(uap, olddelta)) {
355 atv.tv_sec = time_adjtime / 1000000;
356 atv.tv_usec = time_adjtime % 1000000;
357 if (atv.tv_usec < 0) {
358 atv.tv_usec += 1000000;
359 atv.tv_sec--;
360 }
361 (void) copyout(&atv,
362 (caddr_t)NETBSD32PTR64(SCARG(uap, olddelta)),
363 sizeof(atv));
364 if (error)
365 return (error);
366 }
367
368 if (SCARG(uap, delta)) {
369 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, delta)), &atv,
370 sizeof(struct timeval));
371 if (error)
372 return (error);
373
374 time_adjtime = (int64_t)atv.tv_sec * 1000000 +
375 atv.tv_usec;
376
377 if (time_adjtime)
378 /* We need to save the system time during shutdown */
379 time_adjusted |= 1;
380 }
381 }
382 #else /* !__HAVE_TIMECOUNTER */
383 {
384 int32_t ndelta, ntickdelta, odelta;
385 extern long bigadj, timedelta;
386 extern int tickdelta;
387 int s;
388 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, delta)), &atv,
389 sizeof(struct timeval));
390 if (error)
391 return (error);
392 /*
393 * Compute the total correction and the rate at which to apply it.
394 * Round the adjustment down to a whole multiple of the per-tick
395 * delta, so that after some number of incremental changes in
396 * hardclock(), tickdelta will become zero, lest the correction
397 * overshoot and start taking us away from the desired final time.
398 */
399 ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
400 if (ndelta > bigadj)
401 ntickdelta = 10 * tickadj;
402 else
403 ntickdelta = tickadj;
404 if (ndelta % ntickdelta)
405 ndelta = ndelta / ntickdelta * ntickdelta;
406
407 /*
408 * To make hardclock()'s job easier, make the per-tick delta negative
409 * if we want time to run slower; then hardclock can simply compute
410 * tick + tickdelta, and subtract tickdelta from timedelta.
411 */
412 if (ndelta < 0)
413 ntickdelta = -ntickdelta;
414 s = splclock();
415 odelta = timedelta;
416 timedelta = ndelta;
417 tickdelta = ntickdelta;
418 splx(s);
419
420 if (SCARG(uap, olddelta)) {
421 atv.tv_sec = odelta / 1000000;
422 atv.tv_usec = odelta % 1000000;
423 (void) copyout(&atv,
424 (caddr_t)NETBSD32PTR64(SCARG(uap, olddelta)), sizeof(atv));
425 }
426 }
427 #endif /* !__HAVE_TIMECOUNTER */
428 return (0);
429 }
430
431 int
432 netbsd32_clock_gettime(l, v, retval)
433 struct lwp *l;
434 void *v;
435 register_t *retval;
436 {
437 struct netbsd32_clock_gettime_args /* {
438 syscallarg(netbsd32_clockid_t) clock_id;
439 syscallarg(netbsd32_timespecp_t) tp;
440 } */ *uap = v;
441 clockid_t clock_id;
442 struct timespec ats;
443 struct netbsd32_timespec ts32;
444
445 clock_id = SCARG(uap, clock_id);
446 if (clock_id != CLOCK_REALTIME)
447 return (EINVAL);
448
449 nanotime(&ats);
450 netbsd32_from_timespec(&ats, &ts32);
451
452 return copyout(&ts32, (caddr_t)NETBSD32PTR64(SCARG(uap, tp)),
453 sizeof(ts32));
454 }
455
456 int
457 netbsd32_clock_settime(l, v, retval)
458 struct lwp *l;
459 void *v;
460 register_t *retval;
461 {
462 struct netbsd32_clock_settime_args /* {
463 syscallarg(netbsd32_clockid_t) clock_id;
464 syscallarg(const netbsd32_timespecp_t) tp;
465 } */ *uap = v;
466 struct netbsd32_timespec ts32;
467 clockid_t clock_id;
468 struct timespec ats;
469 int error;
470 struct proc *p = l->l_proc;
471
472 if ((error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER, &p->p_acflag)) != 0)
473 return (error);
474
475 clock_id = SCARG(uap, clock_id);
476 if (clock_id != CLOCK_REALTIME)
477 return (EINVAL);
478
479 if ((error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, tp)), &ts32,
480 sizeof(ts32))) != 0)
481 return (error);
482
483 netbsd32_to_timespec(&ts32, &ats);
484 return settime(p, &ats);
485 }
486
487 int
488 netbsd32_clock_getres(l, v, retval)
489 struct lwp *l;
490 void *v;
491 register_t *retval;
492 {
493 struct netbsd32_clock_getres_args /* {
494 syscallarg(netbsd32_clockid_t) clock_id;
495 syscallarg(netbsd32_timespecp_t) tp;
496 } */ *uap = v;
497 struct netbsd32_timespec ts32;
498 clockid_t clock_id;
499 struct timespec ts;
500 int error = 0;
501
502 clock_id = SCARG(uap, clock_id);
503 if (clock_id != CLOCK_REALTIME)
504 return (EINVAL);
505
506 if (SCARG(uap, tp)) {
507 ts.tv_sec = 0;
508 ts.tv_nsec = 1000000000 / hz;
509
510 netbsd32_from_timespec(&ts, &ts32);
511 error = copyout(&ts, (caddr_t)NETBSD32PTR64(SCARG(uap, tp)),
512 sizeof(ts));
513 }
514
515 return error;
516 }
517
518 int
519 netbsd32_nanosleep(l, v, retval)
520 struct lwp *l;
521 void *v;
522 register_t *retval;
523 {
524 struct netbsd32_nanosleep_args /* {
525 syscallarg(const netbsd32_timespecp_t) rqtp;
526 syscallarg(netbsd32_timespecp_t) rmtp;
527 } */ *uap = v;
528 static int nanowait;
529 struct netbsd32_timespec ts32;
530 struct timespec rqt;
531 struct timespec rmt;
532 struct timeval atv, utv, ctime;
533 int error, timo;
534
535 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, rqtp)), (caddr_t)&ts32,
536 sizeof(ts32));
537 if (error)
538 return (error);
539
540 netbsd32_to_timespec(&ts32, &rqt);
541 TIMESPEC_TO_TIMEVAL(&atv,&rqt);
542 if (itimerfix(&atv))
543 return (EINVAL);
544
545 getmicrotime(&ctime);
546 timeradd(&atv,&ctime,&atv);
547 timo = hzto(&atv);
548 /*
549 * Avoid inadvertantly sleeping forever
550 */
551 if (timo == 0)
552 timo = 1;
553
554 error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo);
555 if (error == ERESTART)
556 error = EINTR;
557 if (error == EWOULDBLOCK)
558 error = 0;
559
560 if (SCARG(uap, rmtp)) {
561 int error1;
562
563 getmicrotime(&utv);
564
565 timersub(&atv, &utv, &utv);
566 if (utv.tv_sec < 0)
567 timerclear(&utv);
568
569 TIMEVAL_TO_TIMESPEC(&utv,&rmt);
570 netbsd32_from_timespec(&rmt, &ts32);
571 error1 = copyout(&ts32,
572 NETBSD32PTR64(SCARG(uap,rmtp)), sizeof(ts32));
573 if (error1)
574 return (error1);
575 }
576
577 return error;
578 }
579
580 static int
581 netbsd32_timer_create_fetch(const void *src, void *dst, size_t size)
582 {
583 struct sigevent *evp = dst;
584 struct netbsd32_sigevent ev32;
585 int error;
586
587 error = copyin(src, &ev32, sizeof(ev32));
588 if (error)
589 return error;
590
591 netbsd32_to_sigevent(&ev32, evp);
592 return 0;
593 }
594
595 int
596 netbsd32_timer_create(struct lwp *l, void *v, register_t *retval)
597 {
598 struct netbsd32_timer_create_args /* {
599 syscallarg(netbsd32_clockid_t) clock_id;
600 syscallarg(netbsd32_sigeventp_t) evp;
601 syscallarg(netbsd32_timerp_t) timerid;
602 } */ *uap = v;
603
604 return timer_create1(NETBSD32PTR64(SCARG(uap, timerid)),
605 SCARG(uap, clock_id), NETBSD32PTR64(SCARG(uap, evp)),
606 netbsd32_timer_create_fetch, l->l_proc);
607 }
608
609 int
610 netbsd32_timer_delete(struct lwp *l, void *v, register_t *retval)
611 {
612 struct netbsd32_timer_delete_args /* {
613 syscallarg(netbsd32_timer_t) timerid;
614 } */ *uap = v;
615 struct sys_timer_delete_args ua;
616
617 NETBSD32TO64_UAP(timerid);
618 return sys_timer_delete(l, (void *)&ua, retval);
619 }
620
621 int
622 netbsd32_timer_settime(struct lwp *l, void *v, register_t *retval)
623 {
624 struct netbsd32_timer_settime_args /* {
625 syscallarg(netbsd32_timer_t) timerid;
626 syscallarg(int) flags;
627 syscallarg(const netbsd32_itimerspecp_t) value;
628 syscallarg(netbsd32_itimerspecp_t) ovalue;
629 } */ *uap = v;
630 int error;
631 struct itimerspec value, ovalue, *ovp = NULL;
632 struct netbsd32_itimerspec its32;
633
634 if ((error = copyin(NETBSD32PTR64(SCARG(uap, value)), &its32,
635 sizeof(its32))) != 0)
636 return (error);
637 netbsd32_to_timespec(&its32.it_interval, &value.it_interval);
638 netbsd32_to_timespec(&its32.it_value, &value.it_value);
639
640 if (SCARG(uap, ovalue))
641 ovp = &ovalue;
642
643 if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp,
644 SCARG(uap, flags), l->l_proc)) != 0)
645 return error;
646
647 if (ovp) {
648 netbsd32_from_timespec(&ovp->it_interval, &its32.it_interval);
649 netbsd32_from_timespec(&ovp->it_value, &its32.it_value);
650 return copyout(&its32, NETBSD32PTR64(SCARG(uap, ovalue)),
651 sizeof(its32));
652 }
653 return 0;
654 }
655
656 int
657 netbsd32_timer_gettime(struct lwp *l, void *v, register_t *retval)
658 {
659 struct netbsd32_timer_gettime_args /* {
660 syscallarg(netbsd32_timer_t) timerid;
661 syscallarg(netbsd32_itimerspecp_t) value;
662 } */ *uap = v;
663 int error;
664 struct itimerspec its;
665 struct netbsd32_itimerspec its32;
666
667 if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc,
668 &its)) != 0)
669 return error;
670
671 netbsd32_from_timespec(&its.it_interval, &its32.it_interval);
672 netbsd32_from_timespec(&its.it_value, &its32.it_value);
673
674 return copyout(&its32, (caddr_t)NETBSD32PTR64(SCARG(uap, value)),
675 sizeof(its32));
676 }
677
678 int
679 netbsd32_timer_getoverrun(struct lwp *l, void *v, register_t *retval)
680 {
681 struct netbsd32_timer_getoverrun_args /* {
682 syscallarg(netbsd32_timer_t) timerid;
683 } */ *uap = v;
684 struct sys_timer_getoverrun_args ua;
685
686 NETBSD32TO64_UAP(timerid);
687 return sys_timer_getoverrun(l, (void *)&ua, retval);
688 }
689