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