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 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 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