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