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