netbsd32_time.c revision 1.25 1 /* $NetBSD: netbsd32_time.c,v 1.25 2007/03/04 06:01:27 christos 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.25 2007/03/04 06:01:27 christos 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((void *)&ntv32,
81 (void *)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((void *)&ntv32,
112 (void *)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((void *)NETBSD32PTR64(SCARG(uap, tp)),
137 (void *)&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_system(l->l_cred,
149 KAUTH_SYSTEM_TIME, KAUTH_REQ_SYSTEM_TIME_NTPADJTIME, NULL, NULL,
150 NULL)))
151 return (error);
152
153 ntp_adjtime1(&ntv);
154
155 netbsd32_from_timex(&ntv, &ntv32);
156 error = copyout((void *)&ntv32, (void *)NETBSD32PTR64(SCARG(uap, tp)),
157 sizeof(ntv32));
158 if (!error) {
159 *retval = ntp_timestatus();
160 }
161 return error;
162 }
163 #else /* !NTP */
164 int
165 netbsd32_ntp_gettime(l, v, retval)
166 struct lwp *l;
167 void *v;
168 register_t *retval;
169 {
170
171 return (ENOSYS);
172 }
173
174 #ifdef COMPAT_30
175 int
176 compat_30_netbsd32_ntp_gettime(l, v, retval)
177 struct lwp *l;
178 void *v;
179 register_t *retval;
180 {
181
182 return (ENOSYS);
183 }
184 #endif
185
186 int
187 netbsd32_ntp_adjtime(l, v, retval)
188 struct lwp *l;
189 void *v;
190 register_t *retval;
191 {
192
193 return (ENOSYS);
194 }
195 #endif /* NTP */
196
197 int
198 netbsd32_setitimer(l, v, retval)
199 struct lwp *l;
200 void *v;
201 register_t *retval;
202 {
203 struct netbsd32_setitimer_args /* {
204 syscallarg(int) which;
205 syscallarg(const netbsd32_itimervalp_t) itv;
206 syscallarg(netbsd32_itimervalp_t) oitv;
207 } */ *uap = v;
208 struct proc *p = l->l_proc;
209 struct netbsd32_itimerval s32it, *itv32;
210 int which = SCARG(uap, which);
211 struct netbsd32_getitimer_args getargs;
212 struct itimerval aitv;
213 int error;
214
215 if ((u_int)which > ITIMER_PROF)
216 return (EINVAL);
217 itv32 = (struct netbsd32_itimerval *)NETBSD32PTR64(SCARG(uap, itv));
218 if (itv32) {
219 if ((error = copyin(itv32, &s32it, sizeof(s32it))))
220 return (error);
221 netbsd32_to_itimerval(&s32it, &aitv);
222 }
223 if (SCARG(uap, oitv) != 0) {
224 SCARG(&getargs, which) = which;
225 SCARG(&getargs, itv) = SCARG(uap, oitv);
226 if ((error = netbsd32_getitimer(l, &getargs, retval)) != 0)
227 return (error);
228 }
229 if (itv32 == 0)
230 return 0;
231
232 return dosetitimer(p, which, &aitv);
233 }
234
235 int
236 netbsd32_getitimer(l, v, retval)
237 struct lwp *l;
238 void *v;
239 register_t *retval;
240 {
241 struct netbsd32_getitimer_args /* {
242 syscallarg(int) which;
243 syscallarg(netbsd32_itimervalp_t) itv;
244 } */ *uap = v;
245 struct proc *p = l->l_proc;
246 struct netbsd32_itimerval s32it;
247 struct itimerval aitv;
248 int error;
249
250 error = dogetitimer(p, SCARG(uap, which), &aitv);
251 if (error)
252 return error;
253
254 netbsd32_from_itimerval(&aitv, &s32it);
255 return (copyout(&s32it, (void *)NETBSD32PTR64(SCARG(uap, itv)),
256 sizeof(s32it)));
257 }
258
259 int
260 netbsd32_gettimeofday(l, v, retval)
261 struct lwp *l;
262 void *v;
263 register_t *retval;
264 {
265 struct netbsd32_gettimeofday_args /* {
266 syscallarg(netbsd32_timevalp_t) tp;
267 syscallarg(netbsd32_timezonep_t) tzp;
268 } */ *uap = v;
269 struct timeval atv;
270 struct netbsd32_timeval tv32;
271 int error = 0;
272 struct netbsd32_timezone tzfake;
273
274 if (SCARG(uap, tp)) {
275 microtime(&atv);
276 netbsd32_from_timeval(&atv, &tv32);
277 error = copyout(&tv32, (void *)NETBSD32PTR64(SCARG(uap, tp)),
278 sizeof(tv32));
279 if (error)
280 return (error);
281 }
282 if (SCARG(uap, tzp)) {
283 /*
284 * NetBSD has no kernel notion of time zone, so we just
285 * fake up a timezone struct and return it if demanded.
286 */
287 tzfake.tz_minuteswest = 0;
288 tzfake.tz_dsttime = 0;
289 error = copyout(&tzfake,
290 (void *)NETBSD32PTR64(SCARG(uap, tzp)), sizeof(tzfake));
291 }
292 return (error);
293 }
294
295 int
296 netbsd32_settimeofday(l, v, retval)
297 struct lwp *l;
298 void *v;
299 register_t *retval;
300 {
301 struct netbsd32_settimeofday_args /* {
302 syscallarg(const netbsd32_timevalp_t) tv;
303 syscallarg(const netbsd32_timezonep_t) tzp;
304 } */ *uap = v;
305 struct netbsd32_timeval atv32;
306 struct timeval atv;
307 struct timespec ats;
308 int error;
309 struct proc *p = l->l_proc;
310
311 /* Verify all parameters before changing time. */
312 if ((error = kauth_authorize_system(l->l_cred,
313 KAUTH_SYSTEM_TIME, KAUTH_REQ_SYSTEM_TIME_SYSTEM, NULL, NULL,
314 NULL)) != 0)
315 return error;
316
317 /*
318 * NetBSD has no kernel notion of time zone, and only an
319 * obsolete program would try to set it, so we log a warning.
320 */
321 if (SCARG(uap, tzp))
322 printf("pid %d attempted to set the "
323 "(obsolete) kernel time zone\n", p->p_pid);
324
325 if (SCARG(uap, tv) == 0)
326 return 0;
327
328 if ((error = copyin((void *)NETBSD32PTR64(SCARG(uap, tv)), &atv32,
329 sizeof(atv32))) != 0)
330 return error;
331
332 netbsd32_to_timeval(&atv32, &atv);
333 TIMEVAL_TO_TIMESPEC(&atv, &ats);
334 return settime(p, &ats);
335 }
336
337 int
338 netbsd32_adjtime(l, v, retval)
339 struct lwp *l;
340 void *v;
341 register_t *retval;
342 {
343 struct netbsd32_adjtime_args /* {
344 syscallarg(const netbsd32_timevalp_t) delta;
345 syscallarg(netbsd32_timevalp_t) olddelta;
346 } */ *uap = v;
347 struct netbsd32_timeval atv;
348 int error;
349
350 if ((error = kauth_authorize_system(l->l_cred,
351 KAUTH_SYSTEM_TIME, KAUTH_REQ_SYSTEM_TIME_ADJTIME, NULL, NULL,
352 NULL)) != 0)
353 return (error);
354
355 #ifdef __HAVE_TIMECOUNTER
356 {
357 extern int time_adjusted; /* in kern_ntptime.c */
358 extern int64_t time_adjtime; /* in kern_ntptime.c */
359 if (SCARG(uap, olddelta)) {
360 atv.tv_sec = time_adjtime / 1000000;
361 atv.tv_usec = time_adjtime % 1000000;
362 if (atv.tv_usec < 0) {
363 atv.tv_usec += 1000000;
364 atv.tv_sec--;
365 }
366 (void) copyout(&atv,
367 (void *)NETBSD32PTR64(SCARG(uap, olddelta)),
368 sizeof(atv));
369 if (error)
370 return (error);
371 }
372
373 if (SCARG(uap, delta)) {
374 error = copyin((void *)NETBSD32PTR64(SCARG(uap, delta)), &atv,
375 sizeof(struct timeval));
376 if (error)
377 return (error);
378
379 time_adjtime = (int64_t)atv.tv_sec * 1000000 +
380 atv.tv_usec;
381
382 if (time_adjtime)
383 /* We need to save the system time during shutdown */
384 time_adjusted |= 1;
385 }
386 }
387 #else /* !__HAVE_TIMECOUNTER */
388 {
389 int32_t ndelta, ntickdelta, odelta;
390 extern long bigadj, timedelta;
391 extern int tickdelta;
392 int s;
393 error = copyin((void *)NETBSD32PTR64(SCARG(uap, delta)), &atv,
394 sizeof(struct timeval));
395 if (error)
396 return (error);
397 /*
398 * Compute the total correction and the rate at which to apply it.
399 * Round the adjustment down to a whole multiple of the per-tick
400 * delta, so that after some number of incremental changes in
401 * hardclock(), tickdelta will become zero, lest the correction
402 * overshoot and start taking us away from the desired final time.
403 */
404 ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
405 if (ndelta > bigadj)
406 ntickdelta = 10 * tickadj;
407 else
408 ntickdelta = tickadj;
409 if (ndelta % ntickdelta)
410 ndelta = ndelta / ntickdelta * ntickdelta;
411
412 /*
413 * To make hardclock()'s job easier, make the per-tick delta negative
414 * if we want time to run slower; then hardclock can simply compute
415 * tick + tickdelta, and subtract tickdelta from timedelta.
416 */
417 if (ndelta < 0)
418 ntickdelta = -ntickdelta;
419 s = splclock();
420 odelta = timedelta;
421 timedelta = ndelta;
422 tickdelta = ntickdelta;
423 splx(s);
424
425 if (SCARG(uap, olddelta)) {
426 atv.tv_sec = odelta / 1000000;
427 atv.tv_usec = odelta % 1000000;
428 (void) copyout(&atv,
429 (void *)NETBSD32PTR64(SCARG(uap, olddelta)), sizeof(atv));
430 }
431 }
432 #endif /* !__HAVE_TIMECOUNTER */
433 return (0);
434 }
435
436 int
437 netbsd32_clock_gettime(l, v, retval)
438 struct lwp *l;
439 void *v;
440 register_t *retval;
441 {
442 struct netbsd32_clock_gettime_args /* {
443 syscallarg(netbsd32_clockid_t) clock_id;
444 syscallarg(netbsd32_timespecp_t) tp;
445 } */ *uap = v;
446 clockid_t clock_id;
447 struct timespec ats;
448 struct netbsd32_timespec ts32;
449
450 clock_id = SCARG(uap, clock_id);
451 if (clock_id != CLOCK_REALTIME)
452 return (EINVAL);
453
454 nanotime(&ats);
455 netbsd32_from_timespec(&ats, &ts32);
456
457 return copyout(&ts32, (void *)NETBSD32PTR64(SCARG(uap, tp)),
458 sizeof(ts32));
459 }
460
461 int
462 netbsd32_clock_settime(l, v, retval)
463 struct lwp *l;
464 void *v;
465 register_t *retval;
466 {
467 struct netbsd32_clock_settime_args /* {
468 syscallarg(netbsd32_clockid_t) clock_id;
469 syscallarg(const netbsd32_timespecp_t) tp;
470 } */ *uap = v;
471 struct netbsd32_timespec ts32;
472 clockid_t clock_id;
473 struct timespec ats;
474 int error;
475
476 if ((error = kauth_authorize_system(l->l_cred,
477 KAUTH_SYSTEM_TIME, KAUTH_REQ_SYSTEM_TIME_SYSTEM, NULL, NULL,
478 NULL)) != 0)
479 return (error);
480
481 clock_id = SCARG(uap, clock_id);
482 if (clock_id != CLOCK_REALTIME)
483 return (EINVAL);
484
485 if ((error = copyin((void *)NETBSD32PTR64(SCARG(uap, tp)), &ts32,
486 sizeof(ts32))) != 0)
487 return (error);
488
489 netbsd32_to_timespec(&ts32, &ats);
490 return settime(l->l_proc, &ats);
491 }
492
493 int
494 netbsd32_clock_getres(l, v, retval)
495 struct lwp *l;
496 void *v;
497 register_t *retval;
498 {
499 struct netbsd32_clock_getres_args /* {
500 syscallarg(netbsd32_clockid_t) clock_id;
501 syscallarg(netbsd32_timespecp_t) tp;
502 } */ *uap = v;
503 struct netbsd32_timespec ts32;
504 clockid_t clock_id;
505 struct timespec ts;
506 int error = 0;
507
508 clock_id = SCARG(uap, clock_id);
509 if (clock_id != CLOCK_REALTIME)
510 return (EINVAL);
511
512 if (SCARG(uap, tp)) {
513 ts.tv_sec = 0;
514 ts.tv_nsec = 1000000000 / hz;
515
516 netbsd32_from_timespec(&ts, &ts32);
517 error = copyout(&ts, (void *)NETBSD32PTR64(SCARG(uap, tp)),
518 sizeof(ts));
519 }
520
521 return error;
522 }
523
524 int
525 netbsd32_nanosleep(l, v, retval)
526 struct lwp *l;
527 void *v;
528 register_t *retval;
529 {
530 struct netbsd32_nanosleep_args /* {
531 syscallarg(const netbsd32_timespecp_t) rqtp;
532 syscallarg(netbsd32_timespecp_t) rmtp;
533 } */ *uap = v;
534 static int nanowait;
535 struct netbsd32_timespec ts32;
536 struct timespec rqt;
537 struct timespec rmt;
538 struct timeval atv, utv, ctime;
539 int error, timo;
540
541 error = copyin((void *)NETBSD32PTR64(SCARG(uap, rqtp)), (void *)&ts32,
542 sizeof(ts32));
543 if (error)
544 return (error);
545
546 netbsd32_to_timespec(&ts32, &rqt);
547 TIMESPEC_TO_TIMEVAL(&atv,&rqt);
548 if (itimerfix(&atv))
549 return (EINVAL);
550
551 getmicrotime(&ctime);
552 timeradd(&atv,&ctime,&atv);
553 timo = hzto(&atv);
554 /*
555 * Avoid inadvertantly sleeping forever
556 */
557 if (timo == 0)
558 timo = 1;
559
560 error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo);
561 if (error == ERESTART)
562 error = EINTR;
563 if (error == EWOULDBLOCK)
564 error = 0;
565
566 if (SCARG(uap, rmtp)) {
567 int error1;
568
569 getmicrotime(&utv);
570
571 timersub(&atv, &utv, &utv);
572 if (utv.tv_sec < 0)
573 timerclear(&utv);
574
575 TIMEVAL_TO_TIMESPEC(&utv,&rmt);
576 netbsd32_from_timespec(&rmt, &ts32);
577 error1 = copyout(&ts32,
578 NETBSD32PTR64(SCARG(uap,rmtp)), sizeof(ts32));
579 if (error1)
580 return (error1);
581 }
582
583 return error;
584 }
585
586 static int
587 netbsd32_timer_create_fetch(const void *src, void *dst, size_t size)
588 {
589 struct sigevent *evp = dst;
590 struct netbsd32_sigevent ev32;
591 int error;
592
593 error = copyin(src, &ev32, sizeof(ev32));
594 if (error)
595 return error;
596
597 netbsd32_to_sigevent(&ev32, evp);
598 return 0;
599 }
600
601 int
602 netbsd32_timer_create(struct lwp *l, void *v, register_t *retval)
603 {
604 struct netbsd32_timer_create_args /* {
605 syscallarg(netbsd32_clockid_t) clock_id;
606 syscallarg(netbsd32_sigeventp_t) evp;
607 syscallarg(netbsd32_timerp_t) timerid;
608 } */ *uap = v;
609
610 return timer_create1(NETBSD32PTR64(SCARG(uap, timerid)),
611 SCARG(uap, clock_id), NETBSD32PTR64(SCARG(uap, evp)),
612 netbsd32_timer_create_fetch, l);
613 }
614
615 int
616 netbsd32_timer_delete(struct lwp *l, void *v, register_t *retval)
617 {
618 struct netbsd32_timer_delete_args /* {
619 syscallarg(netbsd32_timer_t) timerid;
620 } */ *uap = v;
621 struct sys_timer_delete_args ua;
622
623 NETBSD32TO64_UAP(timerid);
624 return sys_timer_delete(l, (void *)&ua, retval);
625 }
626
627 int
628 netbsd32_timer_settime(struct lwp *l, void *v, register_t *retval)
629 {
630 struct netbsd32_timer_settime_args /* {
631 syscallarg(netbsd32_timer_t) timerid;
632 syscallarg(int) flags;
633 syscallarg(const netbsd32_itimerspecp_t) value;
634 syscallarg(netbsd32_itimerspecp_t) ovalue;
635 } */ *uap = v;
636 int error;
637 struct itimerspec value, ovalue, *ovp = NULL;
638 struct netbsd32_itimerspec its32;
639
640 if ((error = copyin(NETBSD32PTR64(SCARG(uap, value)), &its32,
641 sizeof(its32))) != 0)
642 return (error);
643 netbsd32_to_timespec(&its32.it_interval, &value.it_interval);
644 netbsd32_to_timespec(&its32.it_value, &value.it_value);
645
646 if (SCARG(uap, ovalue))
647 ovp = &ovalue;
648
649 if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp,
650 SCARG(uap, flags), l->l_proc)) != 0)
651 return error;
652
653 if (ovp) {
654 netbsd32_from_timespec(&ovp->it_interval, &its32.it_interval);
655 netbsd32_from_timespec(&ovp->it_value, &its32.it_value);
656 return copyout(&its32, NETBSD32PTR64(SCARG(uap, ovalue)),
657 sizeof(its32));
658 }
659 return 0;
660 }
661
662 int
663 netbsd32_timer_gettime(struct lwp *l, void *v, register_t *retval)
664 {
665 struct netbsd32_timer_gettime_args /* {
666 syscallarg(netbsd32_timer_t) timerid;
667 syscallarg(netbsd32_itimerspecp_t) value;
668 } */ *uap = v;
669 int error;
670 struct itimerspec its;
671 struct netbsd32_itimerspec its32;
672
673 if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc,
674 &its)) != 0)
675 return error;
676
677 netbsd32_from_timespec(&its.it_interval, &its32.it_interval);
678 netbsd32_from_timespec(&its.it_value, &its32.it_value);
679
680 return copyout(&its32, (void *)NETBSD32PTR64(SCARG(uap, value)),
681 sizeof(its32));
682 }
683
684 int
685 netbsd32_timer_getoverrun(struct lwp *l, void *v, register_t *retval)
686 {
687 struct netbsd32_timer_getoverrun_args /* {
688 syscallarg(netbsd32_timer_t) timerid;
689 } */ *uap = v;
690 struct sys_timer_getoverrun_args ua;
691
692 NETBSD32TO64_UAP(timerid);
693 return sys_timer_getoverrun(l, (void *)&ua, retval);
694 }
695