netbsd32_time.c revision 1.13 1 /* $NetBSD: netbsd32_time.c,v 1.13 2005/10/23 00:09:14 cube 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.13 2005/10/23 00:09:14 cube Exp $");
33
34 #if defined(_KERNEL_OPT)
35 #include "opt_ntp.h"
36 #endif
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/mount.h>
41 #include <sys/time.h>
42 #include <sys/timex.h>
43 #include <sys/timevar.h>
44 #include <sys/proc.h>
45 #include <sys/pool.h>
46 #include <sys/resourcevar.h>
47 #include <sys/dirent.h>
48
49 #include <compat/netbsd32/netbsd32.h>
50 #include <compat/netbsd32/netbsd32_syscallargs.h>
51 #include <compat/netbsd32/netbsd32_conv.h>
52
53 #ifdef NTP
54 int
55 netbsd32_ntp_gettime(l, v, retval)
56 struct lwp *l;
57 void *v;
58 register_t *retval;
59 {
60 struct netbsd32_ntp_gettime_args /* {
61 syscallarg(netbsd32_ntptimevalp_t) ntvp;
62 } */ *uap = v;
63 struct netbsd32_ntptimeval ntv32;
64 struct timeval atv;
65 struct ntptimeval ntv;
66 int error = 0;
67 int s;
68
69 /* The following are NTP variables */
70 extern long time_maxerror;
71 extern long time_esterror;
72 extern int time_status;
73 extern int time_state; /* clock state */
74 extern int time_status; /* clock status bits */
75
76 if (SCARG(uap, ntvp)) {
77 s = splclock();
78 #ifdef EXT_CLOCK
79 /*
80 * The microtime() external clock routine returns a
81 * status code. If less than zero, we declare an error
82 * in the clock status word and return the kernel
83 * (software) time variable. While there are other
84 * places that call microtime(), this is the only place
85 * that matters from an application point of view.
86 */
87 if (microtime(&atv) < 0) {
88 time_status |= STA_CLOCKERR;
89 ntv.time = time;
90 } else
91 time_status &= ~STA_CLOCKERR;
92 #else /* EXT_CLOCK */
93 microtime(&atv);
94 #endif /* EXT_CLOCK */
95 ntv.time = atv;
96 ntv.maxerror = time_maxerror;
97 ntv.esterror = time_esterror;
98 (void) splx(s);
99
100 netbsd32_from_timeval(&ntv.time, &ntv32.time);
101 ntv32.maxerror = (netbsd32_long)ntv.maxerror;
102 ntv32.esterror = (netbsd32_long)ntv.esterror;
103 error = copyout((caddr_t)&ntv32,
104 (caddr_t)NETBSD32PTR64(SCARG(uap, ntvp)), sizeof(ntv32));
105 }
106 if (!error) {
107
108 /*
109 * Status word error decode. If any of these conditions
110 * occur, an error is returned, instead of the status
111 * word. Most applications will care only about the fact
112 * the system clock may not be trusted, not about the
113 * details.
114 *
115 * Hardware or software error
116 */
117 if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) ||
118
119 /*
120 * PPS signal lost when either time or frequency
121 * synchronization requested
122 */
123 (time_status & (STA_PPSFREQ | STA_PPSTIME) &&
124 !(time_status & STA_PPSSIGNAL)) ||
125
126 /*
127 * PPS jitter exceeded when time synchronization
128 * requested
129 */
130 (time_status & STA_PPSTIME &&
131 time_status & STA_PPSJITTER) ||
132
133 /*
134 * PPS wander exceeded or calibration error when
135 * frequency synchronization requested
136 */
137 (time_status & STA_PPSFREQ &&
138 time_status & (STA_PPSWANDER | STA_PPSERROR)))
139 *retval = TIME_ERROR;
140 else
141 *retval = time_state;
142 }
143 return (error);
144 }
145
146 int
147 netbsd32_ntp_adjtime(l, v, retval)
148 struct lwp *l;
149 void *v;
150 register_t *retval;
151 {
152 struct netbsd32_ntp_adjtime_args /* {
153 syscallarg(netbsd32_timexp_t) tp;
154 } */ *uap = v;
155 struct netbsd32_timex ntv32;
156 struct timex ntv;
157 int error = 0;
158 int modes;
159 int s;
160 struct proc *p = l->l_proc;
161 extern long time_freq; /* frequency offset (scaled ppm) */
162 extern long time_maxerror;
163 extern long time_esterror;
164 extern int time_state; /* clock state */
165 extern int time_status; /* clock status bits */
166 extern long time_constant; /* pll time constant */
167 extern long time_offset; /* time offset (us) */
168 extern long time_tolerance; /* frequency tolerance (scaled ppm) */
169 extern long time_precision; /* clock precision (us) */
170
171 if ((error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, tp)),
172 (caddr_t)&ntv32, sizeof(ntv32))))
173 return (error);
174 netbsd32_to_timex(&ntv32, &ntv);
175
176 /*
177 * Update selected clock variables - only the superuser can
178 * change anything. Note that there is no error checking here on
179 * the assumption the superuser should know what it is doing.
180 */
181 modes = ntv.modes;
182 if (modes != 0 && (error = suser(p->p_ucred, &p->p_acflag)))
183 return (error);
184
185 s = splclock();
186 if (modes & MOD_FREQUENCY)
187 #ifdef PPS_SYNC
188 time_freq = ntv.freq - pps_freq;
189 #else /* PPS_SYNC */
190 time_freq = ntv.freq;
191 #endif /* PPS_SYNC */
192 if (modes & MOD_MAXERROR)
193 time_maxerror = ntv.maxerror;
194 if (modes & MOD_ESTERROR)
195 time_esterror = ntv.esterror;
196 if (modes & MOD_STATUS) {
197 time_status &= STA_RONLY;
198 time_status |= ntv.status & ~STA_RONLY;
199 }
200 if (modes & MOD_TIMECONST)
201 time_constant = ntv.constant;
202 if (modes & MOD_OFFSET)
203 hardupdate(ntv.offset);
204
205 /*
206 * Retrieve all clock variables
207 */
208 if (time_offset < 0)
209 ntv.offset = -(-time_offset >> SHIFT_UPDATE);
210 else
211 ntv.offset = time_offset >> SHIFT_UPDATE;
212 #ifdef PPS_SYNC
213 ntv.freq = time_freq + pps_freq;
214 #else /* PPS_SYNC */
215 ntv.freq = time_freq;
216 #endif /* PPS_SYNC */
217 ntv.maxerror = time_maxerror;
218 ntv.esterror = time_esterror;
219 ntv.status = time_status;
220 ntv.constant = time_constant;
221 ntv.precision = time_precision;
222 ntv.tolerance = time_tolerance;
223 #ifdef PPS_SYNC
224 ntv.shift = pps_shift;
225 ntv.ppsfreq = pps_freq;
226 ntv.jitter = pps_jitter >> PPS_AVG;
227 ntv.stabil = pps_stabil;
228 ntv.calcnt = pps_calcnt;
229 ntv.errcnt = pps_errcnt;
230 ntv.jitcnt = pps_jitcnt;
231 ntv.stbcnt = pps_stbcnt;
232 #endif /* PPS_SYNC */
233 (void)splx(s);
234
235 netbsd32_from_timex(&ntv, &ntv32);
236 error = copyout((caddr_t)&ntv32, (caddr_t)NETBSD32PTR64(SCARG(uap, tp)),
237 sizeof(ntv32));
238 if (!error) {
239
240 /*
241 * Status word error decode. See comments in
242 * ntp_gettime() routine.
243 */
244 if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) ||
245 (time_status & (STA_PPSFREQ | STA_PPSTIME) &&
246 !(time_status & STA_PPSSIGNAL)) ||
247 (time_status & STA_PPSTIME &&
248 time_status & STA_PPSJITTER) ||
249 (time_status & STA_PPSFREQ &&
250 time_status & (STA_PPSWANDER | STA_PPSERROR)))
251 *retval = TIME_ERROR;
252 else
253 *retval = time_state;
254 }
255 return error;
256 }
257 #else
258 int
259 netbsd32_ntp_gettime(l, v, retval)
260 struct lwp *l;
261 void *v;
262 register_t *retval;
263 {
264
265 return (ENOSYS);
266 }
267
268 int
269 netbsd32_ntp_adjtime(l, v, retval)
270 struct lwp *l;
271 void *v;
272 register_t *retval;
273 {
274
275 return (ENOSYS);
276 }
277 #endif
278
279 int
280 netbsd32_setitimer(l, v, retval)
281 struct lwp *l;
282 void *v;
283 register_t *retval;
284 {
285 struct netbsd32_setitimer_args /* {
286 syscallarg(int) which;
287 syscallarg(const netbsd32_itimervalp_t) itv;
288 syscallarg(netbsd32_itimervalp_t) oitv;
289 } */ *uap = v;
290 struct proc *p = l->l_proc;
291 struct netbsd32_itimerval s32it, *itv32;
292 int which = SCARG(uap, which);
293 struct netbsd32_getitimer_args getargs;
294 struct itimerval aitv;
295 int error;
296
297 if ((u_int)which > ITIMER_PROF)
298 return (EINVAL);
299 itv32 = (struct netbsd32_itimerval *)NETBSD32PTR64(SCARG(uap, itv));
300 if (itv32) {
301 if ((error = copyin(itv32, &s32it, sizeof(s32it))))
302 return (error);
303 netbsd32_to_itimerval(&s32it, &aitv);
304 }
305 if (SCARG(uap, oitv) != 0) {
306 SCARG(&getargs, which) = which;
307 SCARG(&getargs, itv) = SCARG(uap, oitv);
308 if ((error = netbsd32_getitimer(l, &getargs, retval)) != 0)
309 return (error);
310 }
311 if (itv32 == 0)
312 return 0;
313
314 return dosetitimer(p, which, &aitv);
315 }
316
317 int
318 netbsd32_getitimer(l, v, retval)
319 struct lwp *l;
320 void *v;
321 register_t *retval;
322 {
323 struct netbsd32_getitimer_args /* {
324 syscallarg(int) which;
325 syscallarg(netbsd32_itimervalp_t) itv;
326 } */ *uap = v;
327 struct proc *p = l->l_proc;
328 struct netbsd32_itimerval s32it;
329 struct itimerval aitv;
330 int error;
331
332 error = dogetitimer(p, SCARG(uap, which), &aitv);
333 if (error)
334 return error;
335
336 netbsd32_from_itimerval(&aitv, &s32it);
337 return (copyout(&s32it, (caddr_t)NETBSD32PTR64(SCARG(uap, itv)),
338 sizeof(s32it)));
339 }
340
341 int
342 netbsd32_gettimeofday(l, v, retval)
343 struct lwp *l;
344 void *v;
345 register_t *retval;
346 {
347 struct netbsd32_gettimeofday_args /* {
348 syscallarg(netbsd32_timevalp_t) tp;
349 syscallarg(netbsd32_timezonep_t) tzp;
350 } */ *uap = v;
351 struct timeval atv;
352 struct netbsd32_timeval tv32;
353 int error = 0;
354 struct netbsd32_timezone tzfake;
355
356 if (SCARG(uap, tp)) {
357 microtime(&atv);
358 netbsd32_from_timeval(&atv, &tv32);
359 error = copyout(&tv32, (caddr_t)NETBSD32PTR64(SCARG(uap, tp)),
360 sizeof(tv32));
361 if (error)
362 return (error);
363 }
364 if (SCARG(uap, tzp)) {
365 /*
366 * NetBSD has no kernel notion of time zone, so we just
367 * fake up a timezone struct and return it if demanded.
368 */
369 tzfake.tz_minuteswest = 0;
370 tzfake.tz_dsttime = 0;
371 error = copyout(&tzfake,
372 (caddr_t)NETBSD32PTR64(SCARG(uap, tzp)), sizeof(tzfake));
373 }
374 return (error);
375 }
376
377 int
378 netbsd32_settimeofday(l, v, retval)
379 struct lwp *l;
380 void *v;
381 register_t *retval;
382 {
383 struct netbsd32_settimeofday_args /* {
384 syscallarg(const netbsd32_timevalp_t) tv;
385 syscallarg(const netbsd32_timezonep_t) tzp;
386 } */ *uap = v;
387 struct netbsd32_timeval atv32;
388 struct timeval atv;
389 int error;
390 struct proc *p = l->l_proc;
391
392 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
393 return (error);
394 /* Verify all parameters before changing time. */
395 if (SCARG(uap, tv) &&
396 (error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, tv)), &atv32,
397 sizeof(atv32))))
398 return (error);
399 netbsd32_to_timeval(&atv32, &atv);
400 if (SCARG(uap, tv))
401 if ((error = settime(&atv)))
402 return (error);
403 /* don't bother copying the tz in, we don't use it. */
404 /*
405 * NetBSD has no kernel notion of time zone, and only an
406 * obsolete program would try to set it, so we log a warning.
407 */
408 if (SCARG(uap, tzp))
409 printf("pid %d attempted to set the "
410 "(obsolete) kernel time zone\n", p->p_pid);
411 return (0);
412 }
413
414 int
415 netbsd32_adjtime(l, v, retval)
416 struct lwp *l;
417 void *v;
418 register_t *retval;
419 {
420 struct netbsd32_adjtime_args /* {
421 syscallarg(const netbsd32_timevalp_t) delta;
422 syscallarg(netbsd32_timevalp_t) olddelta;
423 } */ *uap = v;
424 struct netbsd32_timeval atv;
425 int32_t ndelta, ntickdelta, odelta;
426 int s, error;
427 struct proc *p = l->l_proc;
428 extern long bigadj, timedelta;
429 extern int tickdelta;
430
431 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
432 return (error);
433
434 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, delta)), &atv,
435 sizeof(struct timeval));
436 if (error)
437 return (error);
438 /*
439 * Compute the total correction and the rate at which to apply it.
440 * Round the adjustment down to a whole multiple of the per-tick
441 * delta, so that after some number of incremental changes in
442 * hardclock(), tickdelta will become zero, lest the correction
443 * overshoot and start taking us away from the desired final time.
444 */
445 ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
446 if (ndelta > bigadj)
447 ntickdelta = 10 * tickadj;
448 else
449 ntickdelta = tickadj;
450 if (ndelta % ntickdelta)
451 ndelta = ndelta / ntickdelta * ntickdelta;
452
453 /*
454 * To make hardclock()'s job easier, make the per-tick delta negative
455 * if we want time to run slower; then hardclock can simply compute
456 * tick + tickdelta, and subtract tickdelta from timedelta.
457 */
458 if (ndelta < 0)
459 ntickdelta = -ntickdelta;
460 s = splclock();
461 odelta = timedelta;
462 timedelta = ndelta;
463 tickdelta = ntickdelta;
464 splx(s);
465
466 if (SCARG(uap, olddelta)) {
467 atv.tv_sec = odelta / 1000000;
468 atv.tv_usec = odelta % 1000000;
469 (void) copyout(&atv,
470 (caddr_t)NETBSD32PTR64(SCARG(uap, olddelta)), sizeof(atv));
471 }
472 return (0);
473 }
474
475 int
476 netbsd32_clock_gettime(l, v, retval)
477 struct lwp *l;
478 void *v;
479 register_t *retval;
480 {
481 struct netbsd32_clock_gettime_args /* {
482 syscallarg(netbsd32_clockid_t) clock_id;
483 syscallarg(netbsd32_timespecp_t) tp;
484 } */ *uap = v;
485 clockid_t clock_id;
486 struct timeval atv;
487 struct timespec ats;
488 struct netbsd32_timespec ts32;
489
490 clock_id = SCARG(uap, clock_id);
491 if (clock_id != CLOCK_REALTIME)
492 return (EINVAL);
493
494 microtime(&atv);
495 TIMEVAL_TO_TIMESPEC(&atv,&ats);
496 netbsd32_from_timespec(&ats, &ts32);
497
498 return copyout(&ts32, (caddr_t)NETBSD32PTR64(SCARG(uap, tp)),
499 sizeof(ts32));
500 }
501
502 int
503 netbsd32_clock_settime(l, v, retval)
504 struct lwp *l;
505 void *v;
506 register_t *retval;
507 {
508 struct netbsd32_clock_settime_args /* {
509 syscallarg(netbsd32_clockid_t) clock_id;
510 syscallarg(const netbsd32_timespecp_t) tp;
511 } */ *uap = v;
512 struct netbsd32_timespec ts32;
513 clockid_t clock_id;
514 struct timeval atv;
515 struct timespec ats;
516 int error;
517 struct proc *p = l->l_proc;
518
519 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
520 return (error);
521
522 clock_id = SCARG(uap, clock_id);
523 if (clock_id != CLOCK_REALTIME)
524 return (EINVAL);
525
526 if ((error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, tp)), &ts32,
527 sizeof(ts32))) != 0)
528 return (error);
529
530 netbsd32_to_timespec(&ts32, &ats);
531 TIMESPEC_TO_TIMEVAL(&atv,&ats);
532 if ((error = settime(&atv)))
533 return (error);
534
535 return 0;
536 }
537
538 int
539 netbsd32_clock_getres(l, v, retval)
540 struct lwp *l;
541 void *v;
542 register_t *retval;
543 {
544 struct netbsd32_clock_getres_args /* {
545 syscallarg(netbsd32_clockid_t) clock_id;
546 syscallarg(netbsd32_timespecp_t) tp;
547 } */ *uap = v;
548 struct netbsd32_timespec ts32;
549 clockid_t clock_id;
550 struct timespec ts;
551 int error = 0;
552
553 clock_id = SCARG(uap, clock_id);
554 if (clock_id != CLOCK_REALTIME)
555 return (EINVAL);
556
557 if (SCARG(uap, tp)) {
558 ts.tv_sec = 0;
559 ts.tv_nsec = 1000000000 / hz;
560
561 netbsd32_from_timespec(&ts, &ts32);
562 error = copyout(&ts, (caddr_t)NETBSD32PTR64(SCARG(uap, tp)),
563 sizeof(ts));
564 }
565
566 return error;
567 }
568
569 int
570 netbsd32_nanosleep(l, v, retval)
571 struct lwp *l;
572 void *v;
573 register_t *retval;
574 {
575 struct netbsd32_nanosleep_args /* {
576 syscallarg(const netbsd32_timespecp_t) rqtp;
577 syscallarg(netbsd32_timespecp_t) rmtp;
578 } */ *uap = v;
579 static int nanowait;
580 struct netbsd32_timespec ts32;
581 struct timespec rqt;
582 struct timespec rmt;
583 struct timeval atv, utv;
584 int error, s, timo;
585
586 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, rqtp)), (caddr_t)&ts32,
587 sizeof(ts32));
588 if (error)
589 return (error);
590
591 netbsd32_to_timespec(&ts32, &rqt);
592 TIMESPEC_TO_TIMEVAL(&atv,&rqt);
593 if (itimerfix(&atv))
594 return (EINVAL);
595
596 s = splclock();
597 timeradd(&atv,&time,&atv);
598 timo = hzto(&atv);
599 /*
600 * Avoid inadvertantly sleeping forever
601 */
602 if (timo == 0)
603 timo = 1;
604 splx(s);
605
606 error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo);
607 if (error == ERESTART)
608 error = EINTR;
609 if (error == EWOULDBLOCK)
610 error = 0;
611
612 if (SCARG(uap, rmtp)) {
613 int error1;
614
615 s = splclock();
616 utv = time;
617 splx(s);
618
619 timersub(&atv, &utv, &utv);
620 if (utv.tv_sec < 0)
621 timerclear(&utv);
622
623 TIMEVAL_TO_TIMESPEC(&utv,&rmt);
624 netbsd32_from_timespec(&rmt, &ts32);
625 error1 = copyout(&ts32,
626 NETBSD32PTR64(SCARG(uap,rmtp)), sizeof(ts32));
627 if (error1)
628 return (error1);
629 }
630
631 return error;
632 }
633
634 static int
635 netbsd32_timer_create_fetch(const void *src, void *dst, size_t size)
636 {
637 struct sigevent *evp = dst;
638 struct netbsd32_sigevent ev32;
639 int error;
640
641 error = copyin(src, &ev32, sizeof(ev32));
642 if (error)
643 return error;
644
645 netbsd32_to_sigevent(&ev32, evp);
646 return 0;
647 }
648
649 int
650 netbsd32_timer_create(struct lwp *l, void *v, register_t *retval)
651 {
652 struct netbsd32_timer_create_args /* {
653 syscallarg(netbsd32_clockid_t) clock_id;
654 syscallarg(netbsd32_sigeventp_t) evp;
655 syscallarg(netbsd32_timerp_t) timerid;
656 } */ *uap = v;
657
658 return timer_create1(NETBSD32PTR64(SCARG(uap, timerid)),
659 SCARG(uap, clock_id), NETBSD32PTR64(SCARG(uap, evp)),
660 netbsd32_timer_create_fetch, l->l_proc);
661 }
662
663 int
664 netbsd32_timer_delete(struct lwp *l, void *v, register_t *retval)
665 {
666 struct netbsd32_timer_delete_args /* {
667 syscallarg(netbsd32_timer_t) timerid;
668 } */ *uap = v;
669 struct sys_timer_delete_args ua;
670
671 NETBSD32TO64_UAP(timerid);
672 return sys_timer_delete(l, (void *)&ua, retval);
673 }
674
675 int
676 netbsd32_timer_settime(struct lwp *l, void *v, register_t *retval)
677 {
678 struct netbsd32_timer_settime_args /* {
679 syscallarg(netbsd32_timer_t) timerid;
680 syscallarg(int) flags;
681 syscallarg(const netbsd32_itimerspecp_t) value;
682 syscallarg(netbsd32_itimerspecp_t) ovalue;
683 } */ *uap = v;
684 int error;
685 struct itimerspec value, ovalue, *ovp = NULL;
686 struct netbsd32_itimerspec its32;
687
688 if ((error = copyin(NETBSD32PTR64(SCARG(uap, value)), &its32,
689 sizeof(its32))) != 0)
690 return (error);
691 netbsd32_to_timespec(&its32.it_interval, &value.it_interval);
692 netbsd32_to_timespec(&its32.it_value, &value.it_value);
693
694 if (SCARG(uap, ovalue))
695 ovp = &ovalue;
696
697 if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp,
698 SCARG(uap, flags), l->l_proc)) != 0)
699 return error;
700
701 if (ovp) {
702 netbsd32_from_timespec(&ovp->it_interval, &its32.it_interval);
703 netbsd32_from_timespec(&ovp->it_value, &its32.it_value);
704 return copyout(&its32, NETBSD32PTR64(SCARG(uap, ovalue)),
705 sizeof(its32));
706 }
707 return 0;
708 }
709
710 int
711 netbsd32_timer_gettime(struct lwp *l, void *v, register_t *retval)
712 {
713 struct netbsd32_timer_gettime_args /* {
714 syscallarg(netbsd32_timer_t) timerid;
715 syscallarg(netbsd32_itimerspecp_t) value;
716 } */ *uap = v;
717 int error;
718 struct itimerspec its;
719 struct netbsd32_itimerspec its32;
720
721 if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc,
722 &its)) != 0)
723 return error;
724
725 netbsd32_from_timespec(&its.it_interval, &its32.it_interval);
726 netbsd32_from_timespec(&its.it_value, &its32.it_value);
727
728 return copyout(&its32, (caddr_t)NETBSD32PTR64(SCARG(uap, value)),
729 sizeof(its32));
730 }
731
732 int
733 netbsd32_timer_getoverrun(struct lwp *l, void *v, register_t *retval)
734 {
735 struct netbsd32_timer_getoverrun_args /* {
736 syscallarg(netbsd32_timer_t) timerid;
737 } */ *uap = v;
738 struct sys_timer_getoverrun_args ua;
739
740 NETBSD32TO64_UAP(timerid);
741 return sys_timer_getoverrun(l, (void *)&ua, retval);
742 }
743