xref: /titanic_50/usr/src/uts/common/syscall/ntptime.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 1994,1996-2003 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate /*
7*7c478bd9Sstevel@tonic-gate  * Copyright (c) David L. Mills 1993, 1994
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, and distribute this software and its
10*7c478bd9Sstevel@tonic-gate  * documentation for any purpose and without fee is hereby granted, provided
11*7c478bd9Sstevel@tonic-gate  * that the above copyright notice appears in all copies and that both the
12*7c478bd9Sstevel@tonic-gate  * copyright notice and this permission notice appear in supporting
13*7c478bd9Sstevel@tonic-gate  * documentation, and that the name University of Delaware not be used in
14*7c478bd9Sstevel@tonic-gate  * advertising or publicity pertaining to distribution of the software
15*7c478bd9Sstevel@tonic-gate  * without specific, written prior permission.	The University of Delaware
16*7c478bd9Sstevel@tonic-gate  * makes no representations about the suitability this software for any
17*7c478bd9Sstevel@tonic-gate  * purpose.  It is provided "as is" without express or implied warranty.
18*7c478bd9Sstevel@tonic-gate  */
19*7c478bd9Sstevel@tonic-gate 
20*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
21*7c478bd9Sstevel@tonic-gate 
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Modification history kern_ntptime.c
24*7c478bd9Sstevel@tonic-gate  *
25*7c478bd9Sstevel@tonic-gate  * 24 Sep 94	David L. Mills
26*7c478bd9Sstevel@tonic-gate  *	Tightened code at exits.
27*7c478bd9Sstevel@tonic-gate  *
28*7c478bd9Sstevel@tonic-gate  * 24 Mar 94	David L. Mills
29*7c478bd9Sstevel@tonic-gate  *	Revised syscall interface to include new variables for PPS
30*7c478bd9Sstevel@tonic-gate  *	time discipline.
31*7c478bd9Sstevel@tonic-gate  *
32*7c478bd9Sstevel@tonic-gate  * 14 Feb 94	David L. Mills
33*7c478bd9Sstevel@tonic-gate  *	Added code for external clock
34*7c478bd9Sstevel@tonic-gate  *
35*7c478bd9Sstevel@tonic-gate  * 28 Nov 93	David L. Mills
36*7c478bd9Sstevel@tonic-gate  *	Revised frequency scaling to conform with adjusted parameters
37*7c478bd9Sstevel@tonic-gate  *
38*7c478bd9Sstevel@tonic-gate  * 17 Sep 93	David L. Mills
39*7c478bd9Sstevel@tonic-gate  *	Created file
40*7c478bd9Sstevel@tonic-gate  */
41*7c478bd9Sstevel@tonic-gate /*
42*7c478bd9Sstevel@tonic-gate  * ntp_gettime(), ntp_adjtime() - precision time interface
43*7c478bd9Sstevel@tonic-gate  *
44*7c478bd9Sstevel@tonic-gate  * These routines consitute the Network Time Protocol (NTP) interfaces
45*7c478bd9Sstevel@tonic-gate  * for user and daemon application programs. The ntp_gettime() routine
46*7c478bd9Sstevel@tonic-gate  * provides the time, maximum error (synch distance) and estimated error
47*7c478bd9Sstevel@tonic-gate  * (dispersion) to client user application programs. The ntp_adjtime()
48*7c478bd9Sstevel@tonic-gate  * routine is used by the NTP daemon to adjust the system clock to an
49*7c478bd9Sstevel@tonic-gate  * externally derived time. The time offset and related variables set by
50*7c478bd9Sstevel@tonic-gate  * this routine are used by clock() to adjust the phase and
51*7c478bd9Sstevel@tonic-gate  * frequency of the phase-lock loop which controls the system clock.
52*7c478bd9Sstevel@tonic-gate  */
53*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
54*7c478bd9Sstevel@tonic-gate #include <sys/user.h>
55*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
56*7c478bd9Sstevel@tonic-gate #include <sys/proc.h>
57*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
58*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
59*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
60*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
61*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
62*7c478bd9Sstevel@tonic-gate #include <sys/timer.h>
63*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
64*7c478bd9Sstevel@tonic-gate #include <sys/timex.h>
65*7c478bd9Sstevel@tonic-gate #include <sys/model.h>
66*7c478bd9Sstevel@tonic-gate #include <sys/policy.h>
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate /*
69*7c478bd9Sstevel@tonic-gate  * ntp_gettime() - NTP user application interface
70*7c478bd9Sstevel@tonic-gate  */
71*7c478bd9Sstevel@tonic-gate int
72*7c478bd9Sstevel@tonic-gate ntp_gettime(struct ntptimeval *tp)
73*7c478bd9Sstevel@tonic-gate {
74*7c478bd9Sstevel@tonic-gate 	timestruc_t tod;
75*7c478bd9Sstevel@tonic-gate 	struct ntptimeval ntv;
76*7c478bd9Sstevel@tonic-gate 	model_t datamodel = get_udatamodel();
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate 	gethrestime(&tod);
79*7c478bd9Sstevel@tonic-gate 	if (tod.tv_sec > TIME32_MAX)
80*7c478bd9Sstevel@tonic-gate 		return (set_errno(EOVERFLOW));
81*7c478bd9Sstevel@tonic-gate 	ntv.time.tv_sec = tod.tv_sec;
82*7c478bd9Sstevel@tonic-gate 	ntv.time.tv_usec = tod.tv_nsec / (NANOSEC / MICROSEC);
83*7c478bd9Sstevel@tonic-gate 	ntv.maxerror = time_maxerror;
84*7c478bd9Sstevel@tonic-gate 	ntv.esterror = time_esterror;
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate 	if (datamodel == DATAMODEL_NATIVE) {
87*7c478bd9Sstevel@tonic-gate 		if (copyout(&ntv, tp, sizeof (ntv)))
88*7c478bd9Sstevel@tonic-gate 			return (set_errno(EFAULT));
89*7c478bd9Sstevel@tonic-gate 	} else {
90*7c478bd9Sstevel@tonic-gate 		struct ntptimeval32 ntv32;
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate 		if (TIMEVAL_OVERFLOW(&ntv.time))
93*7c478bd9Sstevel@tonic-gate 			return (set_errno(EOVERFLOW));
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate 		TIMEVAL_TO_TIMEVAL32(&ntv32.time, &ntv.time);
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate 		ntv32.maxerror = ntv.maxerror;
98*7c478bd9Sstevel@tonic-gate 		ntv32.esterror = ntv.esterror;
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 		if (copyout(&ntv32, tp, sizeof (ntv32)))
101*7c478bd9Sstevel@tonic-gate 			return (set_errno(EFAULT));
102*7c478bd9Sstevel@tonic-gate 	}
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	/*
105*7c478bd9Sstevel@tonic-gate 	 * Status word error decode. If any of these conditions
106*7c478bd9Sstevel@tonic-gate 	 * occur, an error is returned, instead of the status
107*7c478bd9Sstevel@tonic-gate 	 * word. Most applications will care only about the fact
108*7c478bd9Sstevel@tonic-gate 	 * the system clock may not be trusted, not about the
109*7c478bd9Sstevel@tonic-gate 	 * details.
110*7c478bd9Sstevel@tonic-gate 	 *
111*7c478bd9Sstevel@tonic-gate 	 * Hardware or software error
112*7c478bd9Sstevel@tonic-gate 	 */
113*7c478bd9Sstevel@tonic-gate 	if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) ||
114*7c478bd9Sstevel@tonic-gate 	/*
115*7c478bd9Sstevel@tonic-gate 	 * PPS signal lost when either time or frequency
116*7c478bd9Sstevel@tonic-gate 	 * synchronization requested
117*7c478bd9Sstevel@tonic-gate 	 */
118*7c478bd9Sstevel@tonic-gate 	    (time_status & (STA_PPSFREQ | STA_PPSTIME) &&
119*7c478bd9Sstevel@tonic-gate 		!(time_status & STA_PPSSIGNAL)) ||
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate 	/*
122*7c478bd9Sstevel@tonic-gate 	 * PPS jitter exceeded when time synchronization
123*7c478bd9Sstevel@tonic-gate 	 * requested
124*7c478bd9Sstevel@tonic-gate 	 */
125*7c478bd9Sstevel@tonic-gate 	    (time_status & STA_PPSTIME && time_status & STA_PPSJITTER) ||
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate 	/*
128*7c478bd9Sstevel@tonic-gate 	 * PPS wander exceeded or calibration error when
129*7c478bd9Sstevel@tonic-gate 	 * frequency synchronization requested
130*7c478bd9Sstevel@tonic-gate 	 */
131*7c478bd9Sstevel@tonic-gate 	    (time_status & STA_PPSFREQ && time_status &
132*7c478bd9Sstevel@tonic-gate 		(STA_PPSWANDER | STA_PPSERROR)))
133*7c478bd9Sstevel@tonic-gate 		return (TIME_ERROR);
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate 	return (time_state);
136*7c478bd9Sstevel@tonic-gate }
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate /*
139*7c478bd9Sstevel@tonic-gate  * ntp_adjtime() - NTP daemon application interface
140*7c478bd9Sstevel@tonic-gate  */
141*7c478bd9Sstevel@tonic-gate int
142*7c478bd9Sstevel@tonic-gate ntp_adjtime(struct timex *tp)
143*7c478bd9Sstevel@tonic-gate {
144*7c478bd9Sstevel@tonic-gate 	struct timex ntv;
145*7c478bd9Sstevel@tonic-gate 	int modes;
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 	if (copyin(tp, &ntv, sizeof (ntv)))
148*7c478bd9Sstevel@tonic-gate 		return (set_errno(EFAULT));
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate 	/*
151*7c478bd9Sstevel@tonic-gate 	 * Update selected clock variables - only privileged users can
152*7c478bd9Sstevel@tonic-gate 	 * change anything. Note that there is no error checking here on
153*7c478bd9Sstevel@tonic-gate 	 * the assumption privileged users know what they're doing.
154*7c478bd9Sstevel@tonic-gate 	 */
155*7c478bd9Sstevel@tonic-gate 	modes = ntv.modes;
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 	if (modes != 0 && secpolicy_settime(CRED()) != 0)
158*7c478bd9Sstevel@tonic-gate 		return (set_errno(EPERM));
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 	if (ntv.constant < 0 || ntv.constant > 30)
161*7c478bd9Sstevel@tonic-gate 		return (set_errno(EINVAL));
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate 	mutex_enter(&tod_lock);
164*7c478bd9Sstevel@tonic-gate 	if (modes & MOD_FREQUENCY)
165*7c478bd9Sstevel@tonic-gate 		time_freq = ntv.freq - pps_freq;
166*7c478bd9Sstevel@tonic-gate 	if (modes & MOD_MAXERROR)
167*7c478bd9Sstevel@tonic-gate 		time_maxerror = ntv.maxerror;
168*7c478bd9Sstevel@tonic-gate 	if (modes & MOD_ESTERROR)
169*7c478bd9Sstevel@tonic-gate 		time_esterror = ntv.esterror;
170*7c478bd9Sstevel@tonic-gate 	if (modes & MOD_STATUS) {
171*7c478bd9Sstevel@tonic-gate 		time_status &= STA_RONLY;
172*7c478bd9Sstevel@tonic-gate 		time_status |= ntv.status & ~STA_RONLY;
173*7c478bd9Sstevel@tonic-gate 	}
174*7c478bd9Sstevel@tonic-gate 	if (modes & MOD_TIMECONST)
175*7c478bd9Sstevel@tonic-gate 		time_constant = ntv.constant;
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 	if (modes & MOD_OFFSET)
178*7c478bd9Sstevel@tonic-gate 		clock_update(ntv.offset);
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 	/*
181*7c478bd9Sstevel@tonic-gate 	 * Retrieve all clock variables
182*7c478bd9Sstevel@tonic-gate 	 */
183*7c478bd9Sstevel@tonic-gate 	ntv.offset = time_offset / SCALE_UPDATE;
184*7c478bd9Sstevel@tonic-gate 	ntv.freq = time_freq + pps_freq;
185*7c478bd9Sstevel@tonic-gate 	ntv.maxerror = time_maxerror;
186*7c478bd9Sstevel@tonic-gate 	ntv.esterror = time_esterror;
187*7c478bd9Sstevel@tonic-gate 	ntv.status = time_status;
188*7c478bd9Sstevel@tonic-gate 	ntv.constant = time_constant;
189*7c478bd9Sstevel@tonic-gate 	ntv.precision = time_precision;
190*7c478bd9Sstevel@tonic-gate 	ntv.tolerance = time_tolerance;
191*7c478bd9Sstevel@tonic-gate 	ntv.shift = pps_shift;
192*7c478bd9Sstevel@tonic-gate 	ntv.ppsfreq = pps_freq;
193*7c478bd9Sstevel@tonic-gate 	ntv.jitter = pps_jitter >> PPS_AVG;
194*7c478bd9Sstevel@tonic-gate 	ntv.stabil = pps_stabil;
195*7c478bd9Sstevel@tonic-gate 	ntv.calcnt = pps_calcnt;
196*7c478bd9Sstevel@tonic-gate 	ntv.errcnt = pps_errcnt;
197*7c478bd9Sstevel@tonic-gate 	ntv.jitcnt = pps_jitcnt;
198*7c478bd9Sstevel@tonic-gate 	ntv.stbcnt = pps_stbcnt;
199*7c478bd9Sstevel@tonic-gate 	mutex_exit(&tod_lock);
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate 	if (copyout(&ntv, tp, sizeof (ntv)))
202*7c478bd9Sstevel@tonic-gate 		return (set_errno(EFAULT));
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate 	/*
205*7c478bd9Sstevel@tonic-gate 	 * Status word error decode.  See comments in
206*7c478bd9Sstevel@tonic-gate 	 * ntp_gettime() routine.
207*7c478bd9Sstevel@tonic-gate 	 */
208*7c478bd9Sstevel@tonic-gate 	if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) ||
209*7c478bd9Sstevel@tonic-gate 	    (time_status & (STA_PPSFREQ | STA_PPSTIME) &&
210*7c478bd9Sstevel@tonic-gate 	    !(time_status & STA_PPSSIGNAL)) ||
211*7c478bd9Sstevel@tonic-gate 	    (time_status & STA_PPSTIME &&
212*7c478bd9Sstevel@tonic-gate 	    time_status & STA_PPSJITTER) ||
213*7c478bd9Sstevel@tonic-gate 	    (time_status & STA_PPSFREQ &&
214*7c478bd9Sstevel@tonic-gate 	    time_status & (STA_PPSWANDER | STA_PPSERROR)))
215*7c478bd9Sstevel@tonic-gate 		return (TIME_ERROR);
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 	return (time_state);
218*7c478bd9Sstevel@tonic-gate }
219