1 /* $NetBSD: netbsd32_time.c,v 1.35 2009/01/11 02:45:49 christos Exp $ */
4 * Copyright (c) 1998, 2001 Matthew R. Green
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: netbsd32_time.c,v 1.35 2009/01/11 02:45:49 christos Exp $");
32 #if defined(_KERNEL_OPT)
34 #include "opt_compat_netbsd.h"
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/mount.h>
41 #include <sys/timex.h>
42 #include <sys/timevar.h>
43 #include <sys/timetc.h>
46 #include <sys/resourcevar.h>
47 #include <sys/dirent.h>
48 #include <sys/kauth.h>
50 #include <compat/netbsd32/netbsd32.h>
51 #include <compat/netbsd32/netbsd32_syscallargs.h>
52 #include <compat/netbsd32/netbsd32_conv.h>
57 netbsd32___ntp_gettime50(struct lwp
*l
,
58 const struct netbsd32___ntp_gettime50_args
*uap
, register_t
*retval
)
61 syscallarg(netbsd32_ntptimevalp_t) ntvp;
63 struct netbsd32_ntptimeval ntv32
;
64 struct ntptimeval ntv
;
67 if (SCARG_P32(uap
, ntvp
)) {
70 ntv32
.time
.tv_sec
= ntv
.time
.tv_sec
;
71 ntv32
.time
.tv_nsec
= ntv
.time
.tv_nsec
;
72 ntv32
.maxerror
= (netbsd32_long
)ntv
.maxerror
;
73 ntv32
.esterror
= (netbsd32_long
)ntv
.esterror
;
74 ntv32
.tai
= (netbsd32_long
)ntv
.tai
;
75 ntv32
.time_state
= ntv
.time_state
;
76 error
= copyout(&ntv32
, SCARG_P32(uap
, ntvp
), sizeof(ntv32
));
79 *retval
= ntp_timestatus();
87 compat_50_netbsd32_ntp_gettime(struct lwp
*l
,
88 const struct compat_50_netbsd32_ntp_gettime_args
*uap
, register_t
*retval
)
91 syscallarg(netbsd32_ntptimeval50p_t) ntvp;
93 struct netbsd32_ntptimeval50 ntv32
;
94 struct ntptimeval ntv
;
97 if (SCARG_P32(uap
, ntvp
)) {
100 ntv32
.time
.tv_sec
= (int32_t)ntv
.time
.tv_sec
;
101 ntv32
.time
.tv_nsec
= ntv
.time
.tv_nsec
;
102 ntv32
.maxerror
= (netbsd32_long
)ntv
.maxerror
;
103 ntv32
.esterror
= (netbsd32_long
)ntv
.esterror
;
104 ntv32
.tai
= (netbsd32_long
)ntv
.tai
;
105 ntv32
.time_state
= ntv
.time_state
;
106 error
= copyout(&ntv32
, SCARG_P32(uap
, ntvp
), sizeof(ntv32
));
109 *retval
= ntp_timestatus();
118 compat_30_netbsd32_ntp_gettime(struct lwp
*l
, const struct compat_30_netbsd32_ntp_gettime_args
*uap
, register_t
*retval
)
121 syscallarg(netbsd32_ntptimevalp_t) ntvp;
123 struct netbsd32_ntptimeval30 ntv32
;
124 struct ntptimeval ntv
;
127 if (SCARG_P32(uap
, ntvp
)) {
130 ntv32
.time
.tv_sec
= ntv
.time
.tv_sec
;
131 ntv32
.time
.tv_usec
= ntv
.time
.tv_nsec
/ 1000;
132 ntv32
.maxerror
= (netbsd32_long
)ntv
.maxerror
;
133 ntv32
.esterror
= (netbsd32_long
)ntv
.esterror
;
134 error
= copyout(&ntv32
, SCARG_P32(uap
, ntvp
), sizeof(ntv32
));
137 *retval
= ntp_timestatus();
145 netbsd32_ntp_adjtime(struct lwp
*l
, const struct netbsd32_ntp_adjtime_args
*uap
, register_t
*retval
)
148 syscallarg(netbsd32_timexp_t) tp;
150 struct netbsd32_timex ntv32
;
155 if ((error
= copyin(SCARG_P32(uap
, tp
), &ntv32
, sizeof(ntv32
))))
158 netbsd32_to_timex(&ntv32
, &ntv
);
161 * Update selected clock variables - only the superuser can
162 * change anything. Note that there is no error checking here on
163 * the assumption the superuser should know what it is doing.
166 if (modes
!= 0 && (error
= kauth_authorize_system(l
->l_cred
,
167 KAUTH_SYSTEM_TIME
, KAUTH_REQ_SYSTEM_TIME_NTPADJTIME
, NULL
, NULL
,
173 netbsd32_from_timex(&ntv
, &ntv32
);
174 error
= copyout(&ntv32
, SCARG_P32(uap
, tp
), sizeof(ntv32
));
176 *retval
= ntp_timestatus();
183 netbsd32___setitimer50(struct lwp
*l
, const struct netbsd32___setitimer50_args
*uap
, register_t
*retval
)
186 syscallarg(int) which;
187 syscallarg(const netbsd32_itimervalp_t) itv;
188 syscallarg(netbsd32_itimervalp_t) oitv;
190 struct proc
*p
= l
->l_proc
;
191 struct netbsd32_itimerval s32it
, *itv32
;
192 int which
= SCARG(uap
, which
);
193 struct netbsd32___getitimer50_args getargs
;
194 struct itimerval aitv
;
197 if ((u_int
)which
> ITIMER_PROF
)
199 itv32
= SCARG_P32(uap
, itv
);
201 if ((error
= copyin(itv32
, &s32it
, sizeof(s32it
))))
203 netbsd32_to_itimerval(&s32it
, &aitv
);
205 if (SCARG_P32(uap
, oitv
) != 0) {
206 SCARG(&getargs
, which
) = which
;
207 SCARG(&getargs
, itv
) = SCARG(uap
, oitv
);
208 if ((error
= netbsd32___getitimer50(l
, &getargs
, retval
)) != 0)
214 return dosetitimer(p
, which
, &aitv
);
218 netbsd32___getitimer50(struct lwp
*l
, const struct netbsd32___getitimer50_args
*uap
, register_t
*retval
)
221 syscallarg(int) which;
222 syscallarg(netbsd32_itimervalp_t) itv;
224 struct proc
*p
= l
->l_proc
;
225 struct netbsd32_itimerval s32it
;
226 struct itimerval aitv
;
229 error
= dogetitimer(p
, SCARG(uap
, which
), &aitv
);
233 netbsd32_from_itimerval(&aitv
, &s32it
);
234 return copyout(&s32it
, SCARG_P32(uap
, itv
), sizeof(s32it
));
238 netbsd32___gettimeofday50(struct lwp
*l
, const struct netbsd32___gettimeofday50_args
*uap
, register_t
*retval
)
241 syscallarg(netbsd32_timevalp_t) tp;
242 syscallarg(netbsd32_timezonep_t) tzp;
245 struct netbsd32_timeval tv32
;
247 struct netbsd32_timezone tzfake
;
249 if (SCARG_P32(uap
, tp
)) {
251 netbsd32_from_timeval(&atv
, &tv32
);
252 error
= copyout(&tv32
, SCARG_P32(uap
, tp
), sizeof(tv32
));
256 if (SCARG_P32(uap
, tzp
)) {
258 * NetBSD has no kernel notion of time zone, so we just
259 * fake up a timezone struct and return it if demanded.
261 tzfake
.tz_minuteswest
= 0;
262 tzfake
.tz_dsttime
= 0;
263 error
= copyout(&tzfake
, SCARG_P32(uap
, tzp
), sizeof(tzfake
));
269 netbsd32___settimeofday50(struct lwp
*l
, const struct netbsd32___settimeofday50_args
*uap
, register_t
*retval
)
272 syscallarg(const netbsd32_timevalp_t) tv;
273 syscallarg(const netbsd32_timezonep_t) tzp;
275 struct netbsd32_timeval atv32
;
279 struct proc
*p
= l
->l_proc
;
281 /* Verify all parameters before changing time. */
284 * NetBSD has no kernel notion of time zone, and only an
285 * obsolete program would try to set it, so we log a warning.
287 if (SCARG_P32(uap
, tzp
))
288 printf("pid %d attempted to set the "
289 "(obsolete) kernel time zone\n", p
->p_pid
);
291 if (SCARG_P32(uap
, tv
) == 0)
294 if ((error
= copyin(SCARG_P32(uap
, tv
), &atv32
, sizeof(atv32
))) != 0)
297 netbsd32_to_timeval(&atv32
, &atv
);
298 TIMEVAL_TO_TIMESPEC(&atv
, &ats
);
299 return settime(p
, &ats
);
303 netbsd32___adjtime50(struct lwp
*l
, const struct netbsd32___adjtime50_args
*uap
, register_t
*retval
)
306 syscallarg(const netbsd32_timevalp_t) delta;
307 syscallarg(netbsd32_timevalp_t) olddelta;
309 struct netbsd32_timeval atv
;
312 extern int time_adjusted
; /* in kern_ntptime.c */
313 extern int64_t time_adjtime
; /* in kern_ntptime.c */
315 if ((error
= kauth_authorize_system(l
->l_cred
,
316 KAUTH_SYSTEM_TIME
, KAUTH_REQ_SYSTEM_TIME_ADJTIME
, NULL
, NULL
,
320 if (SCARG_P32(uap
, olddelta
)) {
321 atv
.tv_sec
= time_adjtime
/ 1000000;
322 atv
.tv_usec
= time_adjtime
% 1000000;
323 if (atv
.tv_usec
< 0) {
324 atv
.tv_usec
+= 1000000;
328 SCARG_P32(uap
, olddelta
),
334 if (SCARG_P32(uap
, delta
)) {
335 error
= copyin(SCARG_P32(uap
, delta
), &atv
,
336 sizeof(struct timeval
));
340 time_adjtime
= (int64_t)atv
.tv_sec
* 1000000 + atv
.tv_usec
;
343 /* We need to save the system time during shutdown */
351 netbsd32___clock_gettime50(struct lwp
*l
, const struct netbsd32___clock_gettime50_args
*uap
, register_t
*retval
)
354 syscallarg(netbsd32_clockid_t) clock_id;
355 syscallarg(netbsd32_timespecp_t) tp;
359 struct netbsd32_timespec ts32
;
361 clock_id
= SCARG(uap
, clock_id
);
362 if (clock_id
!= CLOCK_REALTIME
)
366 netbsd32_from_timespec(&ats
, &ts32
);
368 return copyout(&ts32
, SCARG_P32(uap
, tp
), sizeof(ts32
));
372 netbsd32___clock_settime50(struct lwp
*l
, const struct netbsd32___clock_settime50_args
*uap
, register_t
*retval
)
375 syscallarg(netbsd32_clockid_t) clock_id;
376 syscallarg(const netbsd32_timespecp_t) tp;
378 struct netbsd32_timespec ts32
;
383 clock_id
= SCARG(uap
, clock_id
);
384 if (clock_id
!= CLOCK_REALTIME
)
387 if ((error
= copyin(SCARG_P32(uap
, tp
), &ts32
, sizeof(ts32
))) != 0)
390 netbsd32_to_timespec(&ts32
, &ats
);
391 return settime(l
->l_proc
, &ats
);
395 netbsd32___clock_getres50(struct lwp
*l
, const struct netbsd32___clock_getres50_args
*uap
, register_t
*retval
)
398 syscallarg(netbsd32_clockid_t) clock_id;
399 syscallarg(netbsd32_timespecp_t) tp;
401 struct netbsd32_timespec ts32
;
406 clock_id
= SCARG(uap
, clock_id
);
407 if (clock_id
!= CLOCK_REALTIME
)
410 if (SCARG_P32(uap
, tp
)) {
412 ts
.tv_nsec
= 1000000000 / hz
;
414 netbsd32_from_timespec(&ts
, &ts32
);
415 error
= copyout(&ts
, SCARG_P32(uap
, tp
), sizeof(ts
));
422 netbsd32___nanosleep50(struct lwp
*l
, const struct netbsd32___nanosleep50_args
*uap
, register_t
*retval
)
425 syscallarg(const netbsd32_timespecp_t) rqtp;
426 syscallarg(netbsd32_timespecp_t) rmtp;
429 struct netbsd32_timespec ts32
;
430 struct timespec rqt
, ctime
, rmt
;
433 error
= copyin(SCARG_P32(uap
, rqtp
), &ts32
, sizeof(ts32
));
437 netbsd32_to_timespec(&ts32
, &rqt
);
438 if (itimespecfix(&rqt
))
442 timespecadd(&rqt
, &ctime
, &rqt
);
445 * Avoid inadvertantly sleeping forever
450 error
= tsleep(&nanowait
, PWAIT
| PCATCH
, "nanosleep", timo
);
451 if (error
== ERESTART
)
453 if (error
== EWOULDBLOCK
)
456 if (SCARG_P32(uap
, rmtp
)) {
461 timespecsub(&rqt
, &rmt
, &rmt
);
465 netbsd32_from_timespec(&rmt
, &ts32
);
466 error1
= copyout(&ts32
, SCARG_P32(uap
,rmtp
), sizeof(ts32
));
475 netbsd32_timer_create_fetch(const void *src
, void *dst
, size_t size
)
477 struct sigevent
*evp
= dst
;
478 struct netbsd32_sigevent ev32
;
481 error
= copyin(src
, &ev32
, sizeof(ev32
));
485 netbsd32_to_sigevent(&ev32
, evp
);
490 netbsd32_timer_create(struct lwp
*l
, const struct netbsd32_timer_create_args
*uap
, register_t
*retval
)
493 syscallarg(netbsd32_clockid_t) clock_id;
494 syscallarg(netbsd32_sigeventp_t) evp;
495 syscallarg(netbsd32_timerp_t) timerid;
498 return timer_create1(SCARG_P32(uap
, timerid
),
499 SCARG(uap
, clock_id
), SCARG_P32(uap
, evp
),
500 netbsd32_timer_create_fetch
, l
);
504 netbsd32_timer_delete(struct lwp
*l
, const struct netbsd32_timer_delete_args
*uap
, register_t
*retval
)
507 syscallarg(netbsd32_timer_t) timerid;
509 struct sys_timer_delete_args ua
;
511 NETBSD32TO64_UAP(timerid
);
512 return sys_timer_delete(l
, (void *)&ua
, retval
);
516 netbsd32___timer_settime50(struct lwp
*l
, const struct netbsd32___timer_settime50_args
*uap
, register_t
*retval
)
519 syscallarg(netbsd32_timer_t) timerid;
520 syscallarg(int) flags;
521 syscallarg(const netbsd32_itimerspecp_t) value;
522 syscallarg(netbsd32_itimerspecp_t) ovalue;
525 struct itimerspec value
, ovalue
, *ovp
= NULL
;
526 struct netbsd32_itimerspec its32
;
528 if ((error
= copyin(SCARG_P32(uap
, value
), &its32
, sizeof(its32
))) != 0)
530 netbsd32_to_timespec(&its32
.it_interval
, &value
.it_interval
);
531 netbsd32_to_timespec(&its32
.it_value
, &value
.it_value
);
533 if (SCARG_P32(uap
, ovalue
))
536 if ((error
= dotimer_settime(SCARG(uap
, timerid
), &value
, ovp
,
537 SCARG(uap
, flags
), l
->l_proc
)) != 0)
541 netbsd32_from_timespec(&ovp
->it_interval
, &its32
.it_interval
);
542 netbsd32_from_timespec(&ovp
->it_value
, &its32
.it_value
);
543 return copyout(&its32
, SCARG_P32(uap
, ovalue
), sizeof(its32
));
549 netbsd32___timer_gettime50(struct lwp
*l
, const struct netbsd32___timer_gettime50_args
*uap
, register_t
*retval
)
552 syscallarg(netbsd32_timer_t) timerid;
553 syscallarg(netbsd32_itimerspecp_t) value;
556 struct itimerspec its
;
557 struct netbsd32_itimerspec its32
;
559 if ((error
= dotimer_gettime(SCARG(uap
, timerid
), l
->l_proc
,
563 netbsd32_from_timespec(&its
.it_interval
, &its32
.it_interval
);
564 netbsd32_from_timespec(&its
.it_value
, &its32
.it_value
);
566 return copyout(&its32
, SCARG_P32(uap
, value
), sizeof(its32
));
570 netbsd32_timer_getoverrun(struct lwp
*l
, const struct netbsd32_timer_getoverrun_args
*uap
, register_t
*retval
)
573 syscallarg(netbsd32_timer_t) timerid;
575 struct sys_timer_getoverrun_args ua
;
577 NETBSD32TO64_UAP(timerid
);
578 return sys_timer_getoverrun(l
, (void *)&ua
, retval
);