[BACK]Return to kern_ntptime.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Annotation of src/sys/kern/kern_ntptime.c, Revision 1.29.8.2

1.29.8.2! yamt        1: /*     $NetBSD$        */
        !             2: #include <sys/types.h>         /* XXX to get __HAVE_TIMECOUNTER, remove
        !             3:                           after all ports are converted. */
        !             4: #ifdef __HAVE_TIMECOUNTER
        !             5:
        !             6: /*-
        !             7:  ***********************************************************************
        !             8:  *                                                                    *
        !             9:  * Copyright (c) David L. Mills 1993-2001                             *
        !            10:  *                                                                    *
        !            11:  * Permission to use, copy, modify, and distribute this software and   *
        !            12:  * its documentation for any purpose and without fee is hereby        *
        !            13:  * granted, provided that the above copyright notice appears in all    *
        !            14:  * copies and that both the copyright notice and this permission       *
        !            15:  * notice appear in supporting documentation, and that the name               *
        !            16:  * University of Delaware not be used in advertising or publicity      *
        !            17:  * pertaining to distribution of the software without specific,               *
        !            18:  * written prior permission. The University of Delaware makes no       *
        !            19:  * representations about the suitability this software for any        *
        !            20:  * purpose. It is provided "as is" without express or implied         *
        !            21:  * warranty.                                                          *
        !            22:  *                                                                    *
        !            23:  **********************************************************************/
1.1       jonathan   24:
1.29.8.2! yamt       25: /*
        !            26:  * Adapted from the original sources for FreeBSD and timecounters by:
        !            27:  * Poul-Henning Kamp <phk@FreeBSD.org>.
        !            28:  *
        !            29:  * The 32bit version of the "LP" macros seems a bit past its "sell by"
        !            30:  * date so I have retained only the 64bit version and included it directly
        !            31:  * in this file.
        !            32:  *
        !            33:  * Only minor changes done to interface with the timecounters over in
        !            34:  * sys/kern/kern_clock.c.   Some of the comments below may be (even more)
        !            35:  * confusing and/or plain wrong in that context.
        !            36:  */
        !            37:
        !            38: #include <sys/cdefs.h>
        !            39: /* __FBSDID("$FreeBSD: src/sys/kern/kern_ntptime.c,v 1.59 2005/05/28 14:34:41 rwatson Exp $"); */
        !            40: __KERNEL_RCSID(0, "$NetBSD$");
        !            41:
        !            42: #include "opt_ntp.h"
        !            43: #include "opt_compat_netbsd.h"
        !            44:
        !            45: #include <sys/param.h>
        !            46: #include <sys/resourcevar.h>
        !            47: #include <sys/systm.h>
        !            48: #include <sys/kernel.h>
        !            49: #include <sys/proc.h>
        !            50: #include <sys/sysctl.h>
        !            51: #include <sys/timex.h>
        !            52: #ifdef COMPAT_30
        !            53: #include <compat/sys/timex.h>
        !            54: #endif
        !            55: #include <sys/vnode.h>
        !            56: #include <sys/kauth.h>
        !            57:
        !            58: #include <sys/mount.h>
        !            59: #include <sys/sa.h>
        !            60: #include <sys/syscallargs.h>
        !            61:
        !            62: #include <machine/cpu.h>
        !            63:
        !            64: /*
        !            65:  * Single-precision macros for 64-bit machines
        !            66:  */
        !            67: typedef int64_t l_fp;
        !            68: #define L_ADD(v, u)    ((v) += (u))
        !            69: #define L_SUB(v, u)    ((v) -= (u))
        !            70: #define L_ADDHI(v, a)  ((v) += (int64_t)(a) << 32)
        !            71: #define L_NEG(v)       ((v) = -(v))
        !            72: #define L_RSHIFT(v, n) \
        !            73:        do { \
        !            74:                if ((v) < 0) \
        !            75:                        (v) = -(-(v) >> (n)); \
        !            76:                else \
        !            77:                        (v) = (v) >> (n); \
        !            78:        } while (0)
        !            79: #define L_MPY(v, a)    ((v) *= (a))
        !            80: #define L_CLR(v)       ((v) = 0)
        !            81: #define L_ISNEG(v)     ((v) < 0)
        !            82: #define L_LINT(v, a)   ((v) = (int64_t)(a) << 32)
        !            83: #define L_GINT(v)      ((v) < 0 ? -(-(v) >> 32) : (v) >> 32)
        !            84:
        !            85: #ifdef NTP
        !            86: /*
        !            87:  * Generic NTP kernel interface
        !            88:  *
        !            89:  * These routines constitute the Network Time Protocol (NTP) interfaces
        !            90:  * for user and daemon application programs. The ntp_gettime() routine
        !            91:  * provides the time, maximum error (synch distance) and estimated error
        !            92:  * (dispersion) to client user application programs. The ntp_adjtime()
        !            93:  * routine is used by the NTP daemon to adjust the system clock to an
        !            94:  * externally derived time. The time offset and related variables set by
        !            95:  * this routine are used by other routines in this module to adjust the
        !            96:  * phase and frequency of the clock discipline loop which controls the
        !            97:  * system clock.
        !            98:  *
        !            99:  * When the kernel time is reckoned directly in nanoseconds (NTP_NANO
        !           100:  * defined), the time at each tick interrupt is derived directly from
        !           101:  * the kernel time variable. When the kernel time is reckoned in
        !           102:  * microseconds, (NTP_NANO undefined), the time is derived from the
        !           103:  * kernel time variable together with a variable representing the
        !           104:  * leftover nanoseconds at the last tick interrupt. In either case, the
        !           105:  * current nanosecond time is reckoned from these values plus an
        !           106:  * interpolated value derived by the clock routines in another
        !           107:  * architecture-specific module. The interpolation can use either a
        !           108:  * dedicated counter or a processor cycle counter (PCC) implemented in
        !           109:  * some architectures.
        !           110:  *
        !           111:  * Note that all routines must run at priority splclock or higher.
        !           112:  */
        !           113: /*
        !           114:  * Phase/frequency-lock loop (PLL/FLL) definitions
        !           115:  *
        !           116:  * The nanosecond clock discipline uses two variable types, time
        !           117:  * variables and frequency variables. Both types are represented as 64-
        !           118:  * bit fixed-point quantities with the decimal point between two 32-bit
        !           119:  * halves. On a 32-bit machine, each half is represented as a single
        !           120:  * word and mathematical operations are done using multiple-precision
        !           121:  * arithmetic. On a 64-bit machine, ordinary computer arithmetic is
        !           122:  * used.
        !           123:  *
        !           124:  * A time variable is a signed 64-bit fixed-point number in ns and
        !           125:  * fraction. It represents the remaining time offset to be amortized
        !           126:  * over succeeding tick interrupts. The maximum time offset is about
        !           127:  * 0.5 s and the resolution is about 2.3e-10 ns.
        !           128:  *
        !           129:  *                     1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
        !           130:  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        !           131:  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           132:  * |s s s|                      ns                                |
        !           133:  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           134:  * |                       fraction                               |
        !           135:  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           136:  *
        !           137:  * A frequency variable is a signed 64-bit fixed-point number in ns/s
        !           138:  * and fraction. It represents the ns and fraction to be added to the
        !           139:  * kernel time variable at each second. The maximum frequency offset is
        !           140:  * about +-500000 ns/s and the resolution is about 2.3e-10 ns/s.
        !           141:  *
        !           142:  *                     1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
        !           143:  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        !           144:  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           145:  * |s s s s s s s s s s s s s|           ns/s                     |
        !           146:  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           147:  * |                       fraction                               |
        !           148:  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        !           149:  */
        !           150: /*
        !           151:  * The following variables establish the state of the PLL/FLL and the
        !           152:  * residual time and frequency offset of the local clock.
        !           153:  */
        !           154: #define SHIFT_PLL      4               /* PLL loop gain (shift) */
        !           155: #define SHIFT_FLL      2               /* FLL loop gain (shift) */
        !           156:
        !           157: static int time_state = TIME_OK;       /* clock state */
        !           158: static int time_status = STA_UNSYNC;   /* clock status bits */
        !           159: static long time_tai;                  /* TAI offset (s) */
        !           160: static long time_monitor;              /* last time offset scaled (ns) */
        !           161: static long time_constant;             /* poll interval (shift) (s) */
        !           162: static long time_precision = 1;                /* clock precision (ns) */
        !           163: static long time_maxerror = MAXPHASE / 1000; /* maximum error (us) */
        !           164: static long time_esterror = MAXPHASE / 1000; /* estimated error (us) */
        !           165: static long time_reftime;              /* time at last adjustment (s) */
        !           166: static l_fp time_offset;               /* time offset (ns) */
        !           167: static l_fp time_freq;                 /* frequency offset (ns/s) */
        !           168: #endif /* NTP */
        !           169:
        !           170: static l_fp time_adj;                  /* tick adjust (ns/s) */
        !           171: int64_t time_adjtime;          /* correction from adjtime(2) (usec) */
        !           172:
        !           173: extern int time_adjusted;      /* ntp might have changed the system time */
        !           174:
        !           175: #ifdef NTP
        !           176: #ifdef PPS_SYNC
        !           177: /*
        !           178:  * The following variables are used when a pulse-per-second (PPS) signal
        !           179:  * is available and connected via a modem control lead. They establish
        !           180:  * the engineering parameters of the clock discipline loop when
        !           181:  * controlled by the PPS signal.
        !           182:  */
        !           183: #define PPS_FAVG       2               /* min freq avg interval (s) (shift) */
        !           184: #define PPS_FAVGDEF    8               /* default freq avg int (s) (shift) */
        !           185: #define PPS_FAVGMAX    15              /* max freq avg interval (s) (shift) */
        !           186: #define PPS_PAVG       4               /* phase avg interval (s) (shift) */
        !           187: #define PPS_VALID      120             /* PPS signal watchdog max (s) */
        !           188: #define PPS_MAXWANDER  100000          /* max PPS wander (ns/s) */
        !           189: #define PPS_POPCORN    2               /* popcorn spike threshold (shift) */
        !           190:
        !           191: static struct timespec pps_tf[3];      /* phase median filter */
        !           192: static l_fp pps_freq;                  /* scaled frequency offset (ns/s) */
        !           193: static long pps_fcount;                        /* frequency accumulator */
        !           194: static long pps_jitter;                        /* nominal jitter (ns) */
        !           195: static long pps_stabil;                        /* nominal stability (scaled ns/s) */
        !           196: static long pps_lastsec;               /* time at last calibration (s) */
        !           197: static int pps_valid;                  /* signal watchdog counter */
        !           198: static int pps_shift = PPS_FAVG;       /* interval duration (s) (shift) */
        !           199: static int pps_shiftmax = PPS_FAVGDEF; /* max interval duration (s) (shift) */
        !           200: static int pps_intcnt;                 /* wander counter */
        !           201:
        !           202: /*
        !           203:  * PPS signal quality monitors
        !           204:  */
        !           205: static long pps_calcnt;                        /* calibration intervals */
        !           206: static long pps_jitcnt;                        /* jitter limit exceeded */
        !           207: static long pps_stbcnt;                        /* stability limit exceeded */
        !           208: static long pps_errcnt;                        /* calibration errors */
        !           209: #endif /* PPS_SYNC */
        !           210: /*
        !           211:  * End of phase/frequency-lock loop (PLL/FLL) definitions
        !           212:  */
        !           213:
        !           214: static void hardupdate(long offset);
        !           215:
        !           216: /*
        !           217:  * ntp_gettime() - NTP user application interface
        !           218:  */
        !           219: void
        !           220: ntp_gettime(ntv)
        !           221:        struct ntptimeval *ntv;
        !           222: {
        !           223:        nanotime(&ntv->time);
        !           224:        ntv->maxerror = time_maxerror;
        !           225:        ntv->esterror = time_esterror;
        !           226:        ntv->tai = time_tai;
        !           227:        ntv->time_state = time_state;
        !           228: }
        !           229:
        !           230: /* ARGSUSED */
        !           231: /*
        !           232:  * ntp_adjtime() - NTP daemon application interface
        !           233:  */
        !           234: int
        !           235: sys_ntp_adjtime(l, v, retval)
        !           236:        struct lwp *l;
        !           237:        void *v;
        !           238:        register_t *retval;
        !           239: {
        !           240:        struct sys_ntp_adjtime_args /* {
        !           241:                syscallarg(struct timex *) tp;
        !           242:        } */ *uap = v;
        !           243:        struct proc *p = l->l_proc;
        !           244:        struct timex ntv;
        !           245:        int error = 0;
        !           246:
        !           247:        if ((error = copyin((caddr_t)SCARG(uap, tp), (caddr_t)&ntv,
        !           248:                        sizeof(ntv))) != 0)
        !           249:                return (error);
        !           250:
        !           251:        if (ntv.modes != 0 && (error = kauth_authorize_generic(p->p_cred,
        !           252:                                KAUTH_GENERIC_ISSUSER, &p->p_acflag)) != 0)
        !           253:                return (error);
        !           254:
        !           255:        ntp_adjtime1(&ntv);
        !           256:
        !           257:        error = copyout((caddr_t)&ntv, (caddr_t)SCARG(uap, tp), sizeof(ntv));
        !           258:        if (!error) {
        !           259:                *retval = ntp_timestatus();
        !           260:        }
        !           261:        return error;
        !           262: }
        !           263:
        !           264: void
        !           265: ntp_adjtime1(ntv)
        !           266:        struct timex *ntv;
        !           267: {
        !           268:        long freq;
        !           269:        int modes;
        !           270:        int s;
        !           271:
        !           272:        /*
        !           273:         * Update selected clock variables - only the superuser can
        !           274:         * change anything. Note that there is no error checking here on
        !           275:         * the assumption the superuser should know what it is doing.
        !           276:         * Note that either the time constant or TAI offset are loaded
        !           277:         * from the ntv.constant member, depending on the mode bits. If
        !           278:         * the STA_PLL bit in the status word is cleared, the state and
        !           279:         * status words are reset to the initial values at boot.
        !           280:         */
        !           281:        modes = ntv->modes;
        !           282:        if (modes != 0)
        !           283:                /* We need to save the system time during shutdown */
        !           284:                time_adjusted |= 2;
        !           285:        s = splclock();
        !           286:        if (modes & MOD_MAXERROR)
        !           287:                time_maxerror = ntv->maxerror;
        !           288:        if (modes & MOD_ESTERROR)
        !           289:                time_esterror = ntv->esterror;
        !           290:        if (modes & MOD_STATUS) {
        !           291:                if (time_status & STA_PLL && !(ntv->status & STA_PLL)) {
        !           292:                        time_state = TIME_OK;
        !           293:                        time_status = STA_UNSYNC;
        !           294: #ifdef PPS_SYNC
        !           295:                        pps_shift = PPS_FAVG;
        !           296: #endif /* PPS_SYNC */
        !           297:                }
        !           298:                time_status &= STA_RONLY;
        !           299:                time_status |= ntv->status & ~STA_RONLY;
        !           300:        }
        !           301:        if (modes & MOD_TIMECONST) {
        !           302:                if (ntv->constant < 0)
        !           303:                        time_constant = 0;
        !           304:                else if (ntv->constant > MAXTC)
        !           305:                        time_constant = MAXTC;
        !           306:                else
        !           307:                        time_constant = ntv->constant;
        !           308:        }
        !           309:        if (modes & MOD_TAI) {
        !           310:                if (ntv->constant > 0)  /* XXX zero & negative numbers ? */
        !           311:                        time_tai = ntv->constant;
        !           312:        }
        !           313: #ifdef PPS_SYNC
        !           314:        if (modes & MOD_PPSMAX) {
        !           315:                if (ntv->shift < PPS_FAVG)
        !           316:                        pps_shiftmax = PPS_FAVG;
        !           317:                else if (ntv->shift > PPS_FAVGMAX)
        !           318:                        pps_shiftmax = PPS_FAVGMAX;
        !           319:                else
        !           320:                        pps_shiftmax = ntv->shift;
        !           321:        }
        !           322: #endif /* PPS_SYNC */
        !           323:        if (modes & MOD_NANO)
        !           324:                time_status |= STA_NANO;
        !           325:        if (modes & MOD_MICRO)
        !           326:                time_status &= ~STA_NANO;
        !           327:        if (modes & MOD_CLKB)
        !           328:                time_status |= STA_CLK;
        !           329:        if (modes & MOD_CLKA)
        !           330:                time_status &= ~STA_CLK;
        !           331:        if (modes & MOD_FREQUENCY) {
        !           332:                freq = (ntv->freq * 1000LL) >> 16;
        !           333:                if (freq > MAXFREQ)
        !           334:                        L_LINT(time_freq, MAXFREQ);
        !           335:                else if (freq < -MAXFREQ)
        !           336:                        L_LINT(time_freq, -MAXFREQ);
        !           337:                else {
        !           338:                        /*
        !           339:                         * ntv.freq is [PPM * 2^16] = [us/s * 2^16]
        !           340:                         * time_freq is [ns/s * 2^32]
        !           341:                         */
        !           342:                        time_freq = ntv->freq * 1000LL * 65536LL;
        !           343:                }
        !           344: #ifdef PPS_SYNC
        !           345:                pps_freq = time_freq;
        !           346: #endif /* PPS_SYNC */
        !           347:        }
        !           348:        if (modes & MOD_OFFSET) {
        !           349:                if (time_status & STA_NANO)
        !           350:                        hardupdate(ntv->offset);
        !           351:                else
        !           352:                        hardupdate(ntv->offset * 1000);
        !           353:        }
        !           354:
        !           355:        /*
        !           356:         * Retrieve all clock variables. Note that the TAI offset is
        !           357:         * returned only by ntp_gettime();
        !           358:         */
        !           359:        if (time_status & STA_NANO)
        !           360:                ntv->offset = L_GINT(time_offset);
        !           361:        else
        !           362:                ntv->offset = L_GINT(time_offset) / 1000; /* XXX rounding ? */
        !           363:        ntv->freq = L_GINT((time_freq / 1000LL) << 16);
        !           364:        ntv->maxerror = time_maxerror;
        !           365:        ntv->esterror = time_esterror;
        !           366:        ntv->status = time_status;
        !           367:        ntv->constant = time_constant;
        !           368:        if (time_status & STA_NANO)
        !           369:                ntv->precision = time_precision;
        !           370:        else
        !           371:                ntv->precision = time_precision / 1000;
        !           372:        ntv->tolerance = MAXFREQ * SCALE_PPM;
        !           373: #ifdef PPS_SYNC
        !           374:        ntv->shift = pps_shift;
        !           375:        ntv->ppsfreq = L_GINT((pps_freq / 1000LL) << 16);
        !           376:        if (time_status & STA_NANO)
        !           377:                ntv->jitter = pps_jitter;
        !           378:        else
        !           379:                ntv->jitter = pps_jitter / 1000;
        !           380:        ntv->stabil = pps_stabil;
        !           381:        ntv->calcnt = pps_calcnt;
        !           382:        ntv->errcnt = pps_errcnt;
        !           383:        ntv->jitcnt = pps_jitcnt;
        !           384:        ntv->stbcnt = pps_stbcnt;
        !           385: #endif /* PPS_SYNC */
        !           386:        splx(s);
        !           387: }
        !           388: #endif /* NTP */
        !           389:
        !           390: /*
        !           391:  * second_overflow() - called after ntp_tick_adjust()
        !           392:  *
        !           393:  * This routine is ordinarily called immediately following the above
        !           394:  * routine ntp_tick_adjust(). While these two routines are normally
        !           395:  * combined, they are separated here only for the purposes of
        !           396:  * simulation.
        !           397:  */
        !           398: void
        !           399: ntp_update_second(int64_t *adjustment, time_t *newsec)
        !           400: {
        !           401:        int tickrate;
        !           402:        l_fp ftemp;             /* 32/64-bit temporary */
        !           403:
        !           404: #ifdef NTP
        !           405:
        !           406:        /*
        !           407:         * On rollover of the second both the nanosecond and microsecond
        !           408:         * clocks are updated and the state machine cranked as
        !           409:         * necessary. The phase adjustment to be used for the next
        !           410:         * second is calculated and the maximum error is increased by
        !           411:         * the tolerance.
        !           412:         */
        !           413:        time_maxerror += MAXFREQ / 1000;
        !           414:
        !           415:        /*
        !           416:         * Leap second processing. If in leap-insert state at
        !           417:         * the end of the day, the system clock is set back one
        !           418:         * second; if in leap-delete state, the system clock is
        !           419:         * set ahead one second. The nano_time() routine or
        !           420:         * external clock driver will insure that reported time
        !           421:         * is always monotonic.
        !           422:         */
        !           423:        switch (time_state) {
        !           424:
        !           425:                /*
        !           426:                 * No warning.
        !           427:                 */
        !           428:                case TIME_OK:
        !           429:                if (time_status & STA_INS)
        !           430:                        time_state = TIME_INS;
        !           431:                else if (time_status & STA_DEL)
        !           432:                        time_state = TIME_DEL;
        !           433:                break;
        !           434:
        !           435:                /*
        !           436:                 * Insert second 23:59:60 following second
        !           437:                 * 23:59:59.
        !           438:                 */
        !           439:                case TIME_INS:
        !           440:                if (!(time_status & STA_INS))
        !           441:                        time_state = TIME_OK;
        !           442:                else if ((*newsec) % 86400 == 0) {
        !           443:                        (*newsec)--;
        !           444:                        time_state = TIME_OOP;
        !           445:                        time_tai++;
        !           446:                }
        !           447:                break;
        !           448:
        !           449:                /*
        !           450:                 * Delete second 23:59:59.
        !           451:                 */
        !           452:                case TIME_DEL:
        !           453:                if (!(time_status & STA_DEL))
        !           454:                        time_state = TIME_OK;
        !           455:                else if (((*newsec) + 1) % 86400 == 0) {
        !           456:                        (*newsec)++;
        !           457:                        time_tai--;
        !           458:                        time_state = TIME_WAIT;
        !           459:                }
        !           460:                break;
        !           461:
        !           462:                /*
        !           463:                 * Insert second in progress.
        !           464:                 */
        !           465:                case TIME_OOP:
        !           466:                        time_state = TIME_WAIT;
        !           467:                break;
        !           468:
        !           469:                /*
        !           470:                 * Wait for status bits to clear.
        !           471:                 */
        !           472:                case TIME_WAIT:
        !           473:                if (!(time_status & (STA_INS | STA_DEL)))
        !           474:                        time_state = TIME_OK;
        !           475:        }
        !           476:
        !           477:        /*
        !           478:         * Compute the total time adjustment for the next second
        !           479:         * in ns. The offset is reduced by a factor depending on
        !           480:         * whether the PPS signal is operating. Note that the
        !           481:         * value is in effect scaled by the clock frequency,
        !           482:         * since the adjustment is added at each tick interrupt.
        !           483:         */
        !           484:        ftemp = time_offset;
        !           485: #ifdef PPS_SYNC
        !           486:        /* XXX even if PPS signal dies we should finish adjustment ? */
        !           487:        if (time_status & STA_PPSTIME && time_status &
        !           488:            STA_PPSSIGNAL)
        !           489:                L_RSHIFT(ftemp, pps_shift);
        !           490:        else
        !           491:                L_RSHIFT(ftemp, SHIFT_PLL + time_constant);
        !           492: #else
        !           493:                L_RSHIFT(ftemp, SHIFT_PLL + time_constant);
        !           494: #endif /* PPS_SYNC */
        !           495:        time_adj = ftemp;
        !           496:        L_SUB(time_offset, ftemp);
        !           497:        L_ADD(time_adj, time_freq);
        !           498:
        !           499: #ifdef PPS_SYNC
        !           500:        if (pps_valid > 0)
        !           501:                pps_valid--;
        !           502:        else
        !           503:                time_status &= ~STA_PPSSIGNAL;
        !           504: #endif /* PPS_SYNC */
        !           505:
        !           506: #endif /* NTP */
        !           507:
        !           508:        /*
        !           509:         * Apply any correction from adjtime(2).  If more than one second
        !           510:         * off we slew at a rate of 5ms/s (5000 PPM) else 500us/s (500PPM)
        !           511:         * until the last second is slewed the final < 500 usecs.
        !           512:         */
        !           513:        if (time_adjtime != 0) {
        !           514:                if (time_adjtime > 1000000)
        !           515:                        tickrate = 5000;
        !           516:                else if (time_adjtime < -1000000)
        !           517:                        tickrate = -5000;
        !           518:                else if (time_adjtime > 500)
        !           519:                        tickrate = 500;
        !           520:                else if (time_adjtime < -500)
        !           521:                        tickrate = -500;
        !           522:                else
        !           523:                        tickrate = time_adjtime;
        !           524:                time_adjtime -= tickrate;
        !           525:                L_LINT(ftemp, tickrate * 1000);
        !           526:                L_ADD(time_adj, ftemp);
        !           527:        }
        !           528:        *adjustment = time_adj;
        !           529: }
        !           530:
        !           531: /*
        !           532:  * ntp_init() - initialize variables and structures
        !           533:  *
        !           534:  * This routine must be called after the kernel variables hz and tick
        !           535:  * are set or changed and before the next tick interrupt. In this
        !           536:  * particular implementation, these values are assumed set elsewhere in
        !           537:  * the kernel. The design allows the clock frequency and tick interval
        !           538:  * to be changed while the system is running. So, this routine should
        !           539:  * probably be integrated with the code that does that.
        !           540:  */
        !           541: void
        !           542: ntp_init(void)
        !           543: {
        !           544:
        !           545:        /*
        !           546:         * The following variables are initialized only at startup. Only
        !           547:         * those structures not cleared by the compiler need to be
        !           548:         * initialized, and these only in the simulator. In the actual
        !           549:         * kernel, any nonzero values here will quickly evaporate.
        !           550:         */
        !           551:        L_CLR(time_adj);
        !           552: #ifdef NTP
        !           553:        L_CLR(time_offset);
        !           554:        L_CLR(time_freq);
        !           555: #ifdef PPS_SYNC
        !           556:        pps_tf[0].tv_sec = pps_tf[0].tv_nsec = 0;
        !           557:        pps_tf[1].tv_sec = pps_tf[1].tv_nsec = 0;
        !           558:        pps_tf[2].tv_sec = pps_tf[2].tv_nsec = 0;
        !           559:        pps_fcount = 0;
        !           560:        L_CLR(pps_freq);
        !           561: #endif /* PPS_SYNC */
        !           562: #endif
        !           563: }
        !           564:
        !           565: #ifdef NTP
        !           566: /*
        !           567:  * hardupdate() - local clock update
        !           568:  *
        !           569:  * This routine is called by ntp_adjtime() to update the local clock
        !           570:  * phase and frequency. The implementation is of an adaptive-parameter,
        !           571:  * hybrid phase/frequency-lock loop (PLL/FLL). The routine computes new
        !           572:  * time and frequency offset estimates for each call. If the kernel PPS
        !           573:  * discipline code is configured (PPS_SYNC), the PPS signal itself
        !           574:  * determines the new time offset, instead of the calling argument.
        !           575:  * Presumably, calls to ntp_adjtime() occur only when the caller
        !           576:  * believes the local clock is valid within some bound (+-128 ms with
        !           577:  * NTP). If the caller's time is far different than the PPS time, an
        !           578:  * argument will ensue, and it's not clear who will lose.
        !           579:  *
        !           580:  * For uncompensated quartz crystal oscillators and nominal update
        !           581:  * intervals less than 256 s, operation should be in phase-lock mode,
        !           582:  * where the loop is disciplined to phase. For update intervals greater
        !           583:  * than 1024 s, operation should be in frequency-lock mode, where the
        !           584:  * loop is disciplined to frequency. Between 256 s and 1024 s, the mode
        !           585:  * is selected by the STA_MODE status bit.
        !           586:  *
        !           587:  * Note: splclock() is in effect.
        !           588:  */
        !           589: void
        !           590: hardupdate(long offset)
        !           591: {
        !           592:        long mtemp;
        !           593:        l_fp ftemp;
        !           594:
        !           595:        /*
        !           596:         * Select how the phase is to be controlled and from which
        !           597:         * source. If the PPS signal is present and enabled to
        !           598:         * discipline the time, the PPS offset is used; otherwise, the
        !           599:         * argument offset is used.
        !           600:         */
        !           601:        if (!(time_status & STA_PLL))
        !           602:                return;
        !           603:        if (!(time_status & STA_PPSTIME && time_status &
        !           604:            STA_PPSSIGNAL)) {
        !           605:                if (offset > MAXPHASE)
        !           606:                        time_monitor = MAXPHASE;
        !           607:                else if (offset < -MAXPHASE)
        !           608:                        time_monitor = -MAXPHASE;
        !           609:                else
        !           610:                        time_monitor = offset;
        !           611:                L_LINT(time_offset, time_monitor);
        !           612:        }
        !           613:
        !           614:        /*
        !           615:         * Select how the frequency is to be controlled and in which
        !           616:         * mode (PLL or FLL). If the PPS signal is present and enabled
        !           617:         * to discipline the frequency, the PPS frequency is used;
        !           618:         * otherwise, the argument offset is used to compute it.
        !           619:         */
        !           620:        if (time_status & STA_PPSFREQ && time_status & STA_PPSSIGNAL) {
        !           621:                time_reftime = time_second;
        !           622:                return;
        !           623:        }
        !           624:        if (time_status & STA_FREQHOLD || time_reftime == 0)
        !           625:                time_reftime = time_second;
        !           626:        mtemp = time_second - time_reftime;
        !           627:        L_LINT(ftemp, time_monitor);
        !           628:        L_RSHIFT(ftemp, (SHIFT_PLL + 2 + time_constant) << 1);
        !           629:        L_MPY(ftemp, mtemp);
        !           630:        L_ADD(time_freq, ftemp);
        !           631:        time_status &= ~STA_MODE;
        !           632:        if (mtemp >= MINSEC && (time_status & STA_FLL || mtemp >
        !           633:            MAXSEC)) {
        !           634:                L_LINT(ftemp, (time_monitor << 4) / mtemp);
        !           635:                L_RSHIFT(ftemp, SHIFT_FLL + 4);
        !           636:                L_ADD(time_freq, ftemp);
        !           637:                time_status |= STA_MODE;
        !           638:        }
        !           639:        time_reftime = time_second;
        !           640:        if (L_GINT(time_freq) > MAXFREQ)
        !           641:                L_LINT(time_freq, MAXFREQ);
        !           642:        else if (L_GINT(time_freq) < -MAXFREQ)
        !           643:                L_LINT(time_freq, -MAXFREQ);
        !           644: }
        !           645:
        !           646: #ifdef PPS_SYNC
        !           647: /*
        !           648:  * hardpps() - discipline CPU clock oscillator to external PPS signal
        !           649:  *
        !           650:  * This routine is called at each PPS interrupt in order to discipline
        !           651:  * the CPU clock oscillator to the PPS signal. It measures the PPS phase
        !           652:  * and leaves it in a handy spot for the hardclock() routine. It
        !           653:  * integrates successive PPS phase differences and calculates the
        !           654:  * frequency offset. This is used in hardclock() to discipline the CPU
        !           655:  * clock oscillator so that intrinsic frequency error is cancelled out.
        !           656:  * The code requires the caller to capture the time and hardware counter
        !           657:  * value at the on-time PPS signal transition.
        !           658:  *
        !           659:  * Note that, on some Unix systems, this routine runs at an interrupt
        !           660:  * priority level higher than the timer interrupt routine hardclock().
        !           661:  * Therefore, the variables used are distinct from the hardclock()
        !           662:  * variables, except for certain exceptions: The PPS frequency pps_freq
        !           663:  * and phase pps_offset variables are determined by this routine and
        !           664:  * updated atomically. The time_tolerance variable can be considered a
        !           665:  * constant, since it is infrequently changed, and then only when the
        !           666:  * PPS signal is disabled. The watchdog counter pps_valid is updated
        !           667:  * once per second by hardclock() and is atomically cleared in this
        !           668:  * routine.
        !           669:  */
        !           670: void
        !           671: hardpps(struct timespec *tsp,          /* time at PPS */
        !           672:        long nsec                       /* hardware counter at PPS */)
        !           673: {
        !           674:        long u_sec, u_nsec, v_nsec; /* temps */
        !           675:        l_fp ftemp;
        !           676:
        !           677:        /*
        !           678:         * The signal is first processed by a range gate and frequency
        !           679:         * discriminator. The range gate rejects noise spikes outside
        !           680:         * the range +-500 us. The frequency discriminator rejects input
        !           681:         * signals with apparent frequency outside the range 1 +-500
        !           682:         * PPM. If two hits occur in the same second, we ignore the
        !           683:         * later hit; if not and a hit occurs outside the range gate,
        !           684:         * keep the later hit for later comparison, but do not process
        !           685:         * it.
        !           686:         */
        !           687:        time_status |= STA_PPSSIGNAL | STA_PPSJITTER;
        !           688:        time_status &= ~(STA_PPSWANDER | STA_PPSERROR);
        !           689:        pps_valid = PPS_VALID;
        !           690:        u_sec = tsp->tv_sec;
        !           691:        u_nsec = tsp->tv_nsec;
        !           692:        if (u_nsec >= (NANOSECOND >> 1)) {
        !           693:                u_nsec -= NANOSECOND;
        !           694:                u_sec++;
        !           695:        }
        !           696:        v_nsec = u_nsec - pps_tf[0].tv_nsec;
        !           697:        if (u_sec == pps_tf[0].tv_sec && v_nsec < NANOSECOND -
        !           698:            MAXFREQ)
        !           699:                return;
        !           700:        pps_tf[2] = pps_tf[1];
        !           701:        pps_tf[1] = pps_tf[0];
        !           702:        pps_tf[0].tv_sec = u_sec;
        !           703:        pps_tf[0].tv_nsec = u_nsec;
        !           704:
        !           705:        /*
        !           706:         * Compute the difference between the current and previous
        !           707:         * counter values. If the difference exceeds 0.5 s, assume it
        !           708:         * has wrapped around, so correct 1.0 s. If the result exceeds
        !           709:         * the tick interval, the sample point has crossed a tick
        !           710:         * boundary during the last second, so correct the tick. Very
        !           711:         * intricate.
        !           712:         */
        !           713:        u_nsec = nsec;
        !           714:        if (u_nsec > (NANOSECOND >> 1))
        !           715:                u_nsec -= NANOSECOND;
        !           716:        else if (u_nsec < -(NANOSECOND >> 1))
        !           717:                u_nsec += NANOSECOND;
        !           718:        pps_fcount += u_nsec;
        !           719:        if (v_nsec > MAXFREQ || v_nsec < -MAXFREQ)
        !           720:                return;
        !           721:        time_status &= ~STA_PPSJITTER;
        !           722:
        !           723:        /*
        !           724:         * A three-stage median filter is used to help denoise the PPS
        !           725:         * time. The median sample becomes the time offset estimate; the
        !           726:         * difference between the other two samples becomes the time
        !           727:         * dispersion (jitter) estimate.
        !           728:         */
        !           729:        if (pps_tf[0].tv_nsec > pps_tf[1].tv_nsec) {
        !           730:                if (pps_tf[1].tv_nsec > pps_tf[2].tv_nsec) {
        !           731:                        v_nsec = pps_tf[1].tv_nsec;     /* 0 1 2 */
        !           732:                        u_nsec = pps_tf[0].tv_nsec - pps_tf[2].tv_nsec;
        !           733:                } else if (pps_tf[2].tv_nsec > pps_tf[0].tv_nsec) {
        !           734:                        v_nsec = pps_tf[0].tv_nsec;     /* 2 0 1 */
        !           735:                        u_nsec = pps_tf[2].tv_nsec - pps_tf[1].tv_nsec;
        !           736:                } else {
        !           737:                        v_nsec = pps_tf[2].tv_nsec;     /* 0 2 1 */
        !           738:                        u_nsec = pps_tf[0].tv_nsec - pps_tf[1].tv_nsec;
        !           739:                }
        !           740:        } else {
        !           741:                if (pps_tf[1].tv_nsec < pps_tf[2].tv_nsec) {
        !           742:                        v_nsec = pps_tf[1].tv_nsec;     /* 2 1 0 */
        !           743:                        u_nsec = pps_tf[2].tv_nsec - pps_tf[0].tv_nsec;
        !           744:                } else if (pps_tf[2].tv_nsec < pps_tf[0].tv_nsec) {
        !           745:                        v_nsec = pps_tf[0].tv_nsec;     /* 1 0 2 */
        !           746:                        u_nsec = pps_tf[1].tv_nsec - pps_tf[2].tv_nsec;
        !           747:                } else {
        !           748:                        v_nsec = pps_tf[2].tv_nsec;     /* 1 2 0 */
        !           749:                        u_nsec = pps_tf[1].tv_nsec - pps_tf[0].tv_nsec;
        !           750:                }
        !           751:        }
        !           752:
        !           753:        /*
        !           754:         * Nominal jitter is due to PPS signal noise and interrupt
        !           755:         * latency. If it exceeds the popcorn threshold, the sample is
        !           756:         * discarded. otherwise, if so enabled, the time offset is
        !           757:         * updated. We can tolerate a modest loss of data here without
        !           758:         * much degrading time accuracy.
        !           759:         */
        !           760:        if (u_nsec > (pps_jitter << PPS_POPCORN)) {
        !           761:                time_status |= STA_PPSJITTER;
        !           762:                pps_jitcnt++;
        !           763:        } else if (time_status & STA_PPSTIME) {
        !           764:                time_monitor = -v_nsec;
        !           765:                L_LINT(time_offset, time_monitor);
        !           766:        }
        !           767:        pps_jitter += (u_nsec - pps_jitter) >> PPS_FAVG;
        !           768:        u_sec = pps_tf[0].tv_sec - pps_lastsec;
        !           769:        if (u_sec < (1 << pps_shift))
        !           770:                return;
        !           771:
        !           772:        /*
        !           773:         * At the end of the calibration interval the difference between
        !           774:         * the first and last counter values becomes the scaled
        !           775:         * frequency. It will later be divided by the length of the
        !           776:         * interval to determine the frequency update. If the frequency
        !           777:         * exceeds a sanity threshold, or if the actual calibration
        !           778:         * interval is not equal to the expected length, the data are
        !           779:         * discarded. We can tolerate a modest loss of data here without
        !           780:         * much degrading frequency accuracy.
        !           781:         */
        !           782:        pps_calcnt++;
        !           783:        v_nsec = -pps_fcount;
        !           784:        pps_lastsec = pps_tf[0].tv_sec;
        !           785:        pps_fcount = 0;
        !           786:        u_nsec = MAXFREQ << pps_shift;
        !           787:        if (v_nsec > u_nsec || v_nsec < -u_nsec || u_sec != (1 <<
        !           788:            pps_shift)) {
        !           789:                time_status |= STA_PPSERROR;
        !           790:                pps_errcnt++;
        !           791:                return;
        !           792:        }
        !           793:
        !           794:        /*
        !           795:         * Here the raw frequency offset and wander (stability) is
        !           796:         * calculated. If the wander is less than the wander threshold
        !           797:         * for four consecutive averaging intervals, the interval is
        !           798:         * doubled; if it is greater than the threshold for four
        !           799:         * consecutive intervals, the interval is halved. The scaled
        !           800:         * frequency offset is converted to frequency offset. The
        !           801:         * stability metric is calculated as the average of recent
        !           802:         * frequency changes, but is used only for performance
        !           803:         * monitoring.
        !           804:         */
        !           805:        L_LINT(ftemp, v_nsec);
        !           806:        L_RSHIFT(ftemp, pps_shift);
        !           807:        L_SUB(ftemp, pps_freq);
        !           808:        u_nsec = L_GINT(ftemp);
        !           809:        if (u_nsec > PPS_MAXWANDER) {
        !           810:                L_LINT(ftemp, PPS_MAXWANDER);
        !           811:                pps_intcnt--;
        !           812:                time_status |= STA_PPSWANDER;
        !           813:                pps_stbcnt++;
        !           814:        } else if (u_nsec < -PPS_MAXWANDER) {
        !           815:                L_LINT(ftemp, -PPS_MAXWANDER);
        !           816:                pps_intcnt--;
        !           817:                time_status |= STA_PPSWANDER;
        !           818:                pps_stbcnt++;
        !           819:        } else {
        !           820:                pps_intcnt++;
        !           821:        }
        !           822:        if (pps_intcnt >= 4) {
        !           823:                pps_intcnt = 4;
        !           824:                if (pps_shift < pps_shiftmax) {
        !           825:                        pps_shift++;
        !           826:                        pps_intcnt = 0;
        !           827:                }
        !           828:        } else if (pps_intcnt <= -4 || pps_shift > pps_shiftmax) {
        !           829:                pps_intcnt = -4;
        !           830:                if (pps_shift > PPS_FAVG) {
        !           831:                        pps_shift--;
        !           832:                        pps_intcnt = 0;
        !           833:                }
        !           834:        }
        !           835:        if (u_nsec < 0)
        !           836:                u_nsec = -u_nsec;
        !           837:        pps_stabil += (u_nsec * SCALE_PPM - pps_stabil) >> PPS_FAVG;
        !           838:
        !           839:        /*
        !           840:         * The PPS frequency is recalculated and clamped to the maximum
        !           841:         * MAXFREQ. If enabled, the system clock frequency is updated as
        !           842:         * well.
        !           843:         */
        !           844:        L_ADD(pps_freq, ftemp);
        !           845:        u_nsec = L_GINT(pps_freq);
        !           846:        if (u_nsec > MAXFREQ)
        !           847:                L_LINT(pps_freq, MAXFREQ);
        !           848:        else if (u_nsec < -MAXFREQ)
        !           849:                L_LINT(pps_freq, -MAXFREQ);
        !           850:        if (time_status & STA_PPSFREQ)
        !           851:                time_freq = pps_freq;
        !           852: }
        !           853: #endif /* PPS_SYNC */
        !           854: #endif /* NTP */
        !           855: #else /* !__HAVE_TIMECOUNTER */
1.1       jonathan  856: /******************************************************************************
                    857:  *                                                                            *
                    858:  * Copyright (c) David L. Mills 1993, 1994                                    *
                    859:  *                                                                            *
                    860:  * Permission to use, copy, modify, and distribute this software and its      *
                    861:  * documentation for any purpose and without fee is hereby granted, provided  *
                    862:  * that the above copyright notice appears in all copies and that both the    *
                    863:  * copyright notice and this permission notice appear in supporting           *
                    864:  * documentation, and that the name University of Delaware not be used in     *
                    865:  * advertising or publicity pertaining to distribution of the software        *
                    866:  * without specific, written prior permission.  The University of Delaware    *
                    867:  * makes no representations about the suitability this software for any       *
                    868:  * purpose.  It is provided "as is" without express or implied warranty.      *
                    869:  *                                                                            *
                    870:  ******************************************************************************/
                    871:
                    872: /*
                    873:  * Modification history kern_ntptime.c
                    874:  *
                    875:  * 24 Sep 94   David L. Mills
                    876:  *     Tightened code at exits.
                    877:  *
                    878:  * 24 Mar 94   David L. Mills
                    879:  *     Revised syscall interface to include new variables for PPS
                    880:  *     time discipline.
                    881:  *
                    882:  * 14 Feb 94   David L. Mills
                    883:  *     Added code for external clock
                    884:  *
                    885:  * 28 Nov 93   David L. Mills
                    886:  *     Revised frequency scaling to conform with adjusted parameters
                    887:  *
                    888:  * 17 Sep 93   David L. Mills
                    889:  *     Created file
                    890:  */
                    891: /*
                    892:  * ntp_gettime(), ntp_adjtime() - precision time interface for SunOS
                    893:  * V4.1.1 and V4.1.3
                    894:  *
                    895:  * These routines consitute the Network Time Protocol (NTP) interfaces
                    896:  * for user and daemon application programs. The ntp_gettime() routine
                    897:  * provides the time, maximum error (synch distance) and estimated error
                    898:  * (dispersion) to client user application programs. The ntp_adjtime()
                    899:  * routine is used by the NTP daemon to adjust the system clock to an
                    900:  * externally derived time. The time offset and related variables set by
                    901:  * this routine are used by hardclock() to adjust the phase and
                    902:  * frequency of the phase-lock loop which controls the system clock.
                    903:  */
1.16      lukem     904:
                    905: #include <sys/cdefs.h>
1.29.8.2! yamt      906: __KERNEL_RCSID(0, "$NetBSD: kern_ntptime.c,v 1.29.8.1 2006/05/24 10:58:41 yamt Exp $");
1.16      lukem     907:
1.6       jonathan  908: #include "opt_ntp.h"
1.29.8.2! yamt      909: #include "opt_compat_netbsd.h"
1.6       jonathan  910:
1.1       jonathan  911: #include <sys/param.h>
                    912: #include <sys/resourcevar.h>
                    913: #include <sys/systm.h>
                    914: #include <sys/kernel.h>
                    915: #include <sys/proc.h>
1.18      simonb    916: #include <sys/sysctl.h>
1.1       jonathan  917: #include <sys/timex.h>
1.29.8.2! yamt      918: #ifdef COMPAT_30
        !           919: #include <compat/sys/timex.h>
        !           920: #endif
1.1       jonathan  921: #include <sys/vnode.h>
1.29.8.1  yamt      922: #include <sys/kauth.h>
1.1       jonathan  923:
                    924: #include <sys/mount.h>
1.22      thorpej   925: #include <sys/sa.h>
1.1       jonathan  926: #include <sys/syscallargs.h>
                    927:
                    928: #include <machine/cpu.h>
1.2       christos  929:
1.4       thorpej   930: #ifdef NTP
1.1       jonathan  931: /*
                    932:  * The following variables are used by the hardclock() routine in the
1.28      perry     933:  * kern_clock.c module and are described in that module.
1.1       jonathan  934:  */
                    935: extern int time_state;         /* clock state */
                    936: extern int time_status;                /* clock status bits */
                    937: extern long time_offset;       /* time adjustment (us) */
                    938: extern long time_freq;         /* frequency offset (scaled ppm) */
                    939: extern long time_maxerror;     /* maximum error (us) */
                    940: extern long time_esterror;     /* estimated error (us) */
                    941: extern long time_constant;     /* pll time constant */
                    942: extern long time_precision;    /* clock precision (us) */
                    943: extern long time_tolerance;    /* frequency tolerance (scaled ppm) */
1.24      drochner  944: extern int time_adjusted;      /* ntp might have changed the system time */
1.1       jonathan  945:
                    946: #ifdef PPS_SYNC
                    947: /*
                    948:  * The following variables are used only if the PPS signal discipline
                    949:  * is configured in the kernel.
                    950:  */
                    951: extern int pps_shift;          /* interval duration (s) (shift) */
                    952: extern long pps_freq;          /* pps frequency offset (scaled ppm) */
                    953: extern long pps_jitter;                /* pps jitter (us) */
                    954: extern long pps_stabil;                /* pps stability (scaled ppm) */
                    955: extern long pps_jitcnt;                /* jitter limit exceeded */
                    956: extern long pps_calcnt;                /* calibration intervals */
                    957: extern long pps_errcnt;                /* calibration errors */
                    958: extern long pps_stbcnt;                /* stability limit exceeded */
                    959: #endif /* PPS_SYNC */
                    960:
                    961: /*ARGSUSED*/
                    962: /*
                    963:  * ntp_gettime() - NTP user application interface
                    964:  */
1.29.8.2! yamt      965: void
        !           966: ntp_gettime(ntvp)
        !           967:        struct ntptimeval *ntvp;
1.1       jonathan  968: {
                    969:        struct timeval atv;
                    970:        int s;
                    971:
1.29.8.2! yamt      972:        memset(ntvp, 0, sizeof(struct ntptimeval));
        !           973:
        !           974:        s = splclock();
1.1       jonathan  975: #ifdef EXT_CLOCK
1.29.8.2! yamt      976:        /*
        !           977:         * The microtime() external clock routine returns a
        !           978:         * status code. If less than zero, we declare an error
        !           979:         * in the clock status word and return the kernel
        !           980:         * (software) time variable. While there are other
        !           981:         * places that call microtime(), this is the only place
        !           982:         * that matters from an application point of view.
        !           983:         */
        !           984:        if (microtime(&atv) < 0) {
        !           985:                time_status |= STA_CLOCKERR;
        !           986:                ntvp->time = time;
        !           987:        } else
        !           988:                time_status &= ~STA_CLOCKERR;
1.1       jonathan  989: #else /* EXT_CLOCK */
1.29.8.2! yamt      990:        microtime(&atv);
1.1       jonathan  991: #endif /* EXT_CLOCK */
1.29.8.2! yamt      992:        ntvp->maxerror = time_maxerror;
        !           993:        ntvp->esterror = time_esterror;
        !           994:        (void) splx(s);
        !           995:        TIMEVAL_TO_TIMESPEC(&atv, &ntvp->time);
1.1       jonathan  996: }
1.29.8.2! yamt      997:
1.1       jonathan  998:
                    999: /* ARGSUSED */
                   1000: /*
                   1001:  * ntp_adjtime() - NTP daemon application interface
                   1002:  */
                   1003: int
1.22      thorpej  1004: sys_ntp_adjtime(l, v, retval)
                   1005:        struct lwp *l;
1.1       jonathan 1006:        void *v;
                   1007:        register_t *retval;
                   1008: {
1.3       thorpej  1009:        struct sys_ntp_adjtime_args /* {
1.1       jonathan 1010:                syscallarg(struct timex *) tp;
                   1011:        } */ *uap = v;
1.22      thorpej  1012:        struct proc *p = l->l_proc;
1.1       jonathan 1013:        struct timex ntv;
                   1014:        int error = 0;
                   1015:
                   1016:        if ((error = copyin((caddr_t)SCARG(uap, tp), (caddr_t)&ntv,
1.14      manu     1017:                        sizeof(ntv))) != 0)
                   1018:                return (error);
                   1019:
1.29.8.1  yamt     1020:        if (ntv.modes != 0 && (error = kauth_authorize_generic(p->p_cred,
                   1021:                                KAUTH_GENERIC_ISSUSER, &p->p_acflag)) != 0)
1.1       jonathan 1022:                return (error);
                   1023:
1.29.8.2! yamt     1024:        ntp_adjtime1(&ntv);
        !          1025:
        !          1026:        error = copyout((caddr_t)&ntv, (caddr_t)SCARG(uap, tp), sizeof(ntv));
        !          1027:
        !          1028:        if (error == 0) {
        !          1029:                *retval = ntp_timestatus();
        !          1030:        }
        !          1031:
        !          1032:        return error;
1.14      manu     1033: }
                   1034:
1.29.8.2! yamt     1035: void
        !          1036: ntp_adjtime1(ntv)
1.14      manu     1037:        struct timex *ntv;
                   1038: {
                   1039:        int modes;
                   1040:        int s;
                   1041:
1.1       jonathan 1042:        /*
1.28      perry    1043:         * Update selected clock variables. Note that there is no error
                   1044:         * checking here on the assumption the superuser should know
1.14      manu     1045:         * what it is doing.
1.1       jonathan 1046:         */
1.15      jmc      1047:        modes = ntv->modes;
1.23      dsl      1048:        if (modes != 0)
                   1049:                /* We need to save the system time during shutdown */
                   1050:                time_adjusted |= 2;
1.1       jonathan 1051:        s = splclock();
                   1052:        if (modes & MOD_FREQUENCY)
                   1053: #ifdef PPS_SYNC
1.15      jmc      1054:                time_freq = ntv->freq - pps_freq;
1.1       jonathan 1055: #else /* PPS_SYNC */
1.15      jmc      1056:                time_freq = ntv->freq;
1.1       jonathan 1057: #endif /* PPS_SYNC */
                   1058:        if (modes & MOD_MAXERROR)
1.15      jmc      1059:                time_maxerror = ntv->maxerror;
1.1       jonathan 1060:        if (modes & MOD_ESTERROR)
1.15      jmc      1061:                time_esterror = ntv->esterror;
1.1       jonathan 1062:        if (modes & MOD_STATUS) {
                   1063:                time_status &= STA_RONLY;
1.15      jmc      1064:                time_status |= ntv->status & ~STA_RONLY;
1.1       jonathan 1065:        }
                   1066:        if (modes & MOD_TIMECONST)
1.15      jmc      1067:                time_constant = ntv->constant;
1.1       jonathan 1068:        if (modes & MOD_OFFSET)
1.15      jmc      1069:                hardupdate(ntv->offset);
1.1       jonathan 1070:
                   1071:        /*
                   1072:         * Retrieve all clock variables
                   1073:         */
                   1074:        if (time_offset < 0)
1.15      jmc      1075:                ntv->offset = -(-time_offset >> SHIFT_UPDATE);
1.1       jonathan 1076:        else
1.15      jmc      1077:                ntv->offset = time_offset >> SHIFT_UPDATE;
1.1       jonathan 1078: #ifdef PPS_SYNC
1.15      jmc      1079:        ntv->freq = time_freq + pps_freq;
1.1       jonathan 1080: #else /* PPS_SYNC */
1.15      jmc      1081:        ntv->freq = time_freq;
1.1       jonathan 1082: #endif /* PPS_SYNC */
1.15      jmc      1083:        ntv->maxerror = time_maxerror;
                   1084:        ntv->esterror = time_esterror;
                   1085:        ntv->status = time_status;
                   1086:        ntv->constant = time_constant;
                   1087:        ntv->precision = time_precision;
                   1088:        ntv->tolerance = time_tolerance;
1.1       jonathan 1089: #ifdef PPS_SYNC
1.15      jmc      1090:        ntv->shift = pps_shift;
                   1091:        ntv->ppsfreq = pps_freq;
                   1092:        ntv->jitter = pps_jitter >> PPS_AVG;
                   1093:        ntv->stabil = pps_stabil;
                   1094:        ntv->calcnt = pps_calcnt;
                   1095:        ntv->errcnt = pps_errcnt;
                   1096:        ntv->jitcnt = pps_jitcnt;
                   1097:        ntv->stbcnt = pps_stbcnt;
1.1       jonathan 1098: #endif /* PPS_SYNC */
                   1099:        (void)splx(s);
                   1100: }
1.29.8.2! yamt     1101: #endif /* NTP */
        !          1102: #endif /* !__HAVE_TIMECOUNTER */
1.1       jonathan 1103:
1.29.8.2! yamt     1104: #ifdef NTP
        !          1105: int
        !          1106: ntp_timestatus()
1.1       jonathan 1107: {
                   1108:        /*
                   1109:         * Status word error decode. If any of these conditions
                   1110:         * occur, an error is returned, instead of the status
                   1111:         * word. Most applications will care only about the fact
                   1112:         * the system clock may not be trusted, not about the
                   1113:         * details.
                   1114:         *
                   1115:         * Hardware or software error
                   1116:         */
                   1117:        if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) ||
                   1118:
                   1119:        /*
                   1120:         * PPS signal lost when either time or frequency
                   1121:         * synchronization requested
                   1122:         */
1.29.8.2! yamt     1123:            (time_status & (STA_PPSFREQ | STA_PPSTIME) &&
        !          1124:             !(time_status & STA_PPSSIGNAL)) ||
1.1       jonathan 1125:
                   1126:        /*
                   1127:         * PPS jitter exceeded when time synchronization
                   1128:         * requested
                   1129:         */
1.29.8.2! yamt     1130:            (time_status & STA_PPSTIME &&
        !          1131:             time_status & STA_PPSJITTER) ||
1.1       jonathan 1132:
                   1133:        /*
                   1134:         * PPS wander exceeded or calibration error when
                   1135:         * frequency synchronization requested
                   1136:         */
1.29.8.2! yamt     1137:            (time_status & STA_PPSFREQ &&
        !          1138:             time_status & (STA_PPSWANDER | STA_PPSERROR)))
        !          1139:                return (TIME_ERROR);
1.1       jonathan 1140:        else
1.29.8.2! yamt     1141:                return (time_state);
        !          1142: }
        !          1143:
        !          1144: /*ARGSUSED*/
        !          1145: /*
        !          1146:  * ntp_gettime() - NTP user application interface
        !          1147:  */
        !          1148: int
        !          1149: sys___ntp_gettime30(l, v, retval)
        !          1150:        struct lwp *l;
        !          1151:        void *v;
        !          1152:        register_t *retval;
        !          1153: {
        !          1154:        struct sys___ntp_gettime30_args /* {
        !          1155:                syscallarg(struct ntptimeval *) ntvp;
        !          1156:        } */ *uap = v;
        !          1157:        struct ntptimeval ntv;
        !          1158:        int error = 0;
        !          1159:
        !          1160:        if (SCARG(uap, ntvp)) {
        !          1161:                ntp_gettime(&ntv);
        !          1162:
        !          1163:                error = copyout((caddr_t)&ntv, (caddr_t)SCARG(uap, ntvp),
        !          1164:                                sizeof(ntv));
        !          1165:        }
        !          1166:        if (!error) {
        !          1167:                *retval = ntp_timestatus();
        !          1168:        }
        !          1169:        return(error);
        !          1170: }
        !          1171:
        !          1172: #ifdef COMPAT_30
        !          1173: int
        !          1174: compat_30_sys_ntp_gettime(l, v, retval)
        !          1175:        struct lwp *l;
        !          1176:        void *v;
        !          1177:        register_t *retval;
        !          1178: {
        !          1179:        struct compat_30_sys_ntp_gettime_args /* {
        !          1180:                syscallarg(struct ntptimeval30 *) ontvp;
        !          1181:        } */ *uap = v;
        !          1182:        struct ntptimeval ntv;
        !          1183:        struct ntptimeval30 ontv;
        !          1184:        int error = 0;
        !          1185:
        !          1186:        if (SCARG(uap, ntvp)) {
        !          1187:                ntp_gettime(&ntv);
        !          1188:                TIMESPEC_TO_TIMEVAL(&ontv.time, &ntv.time);
        !          1189:                ontv.maxerror = ntv.maxerror;
        !          1190:                ontv.esterror = ntv.esterror;
        !          1191:
        !          1192:                error = copyout((caddr_t)&ontv, (caddr_t)SCARG(uap, ntvp),
        !          1193:                                sizeof(ontv));
        !          1194:        }
        !          1195:        if (!error)
        !          1196:                *retval = ntp_timestatus();
        !          1197:
        !          1198:        return (error);
        !          1199: }
        !          1200: #endif
        !          1201:
        !          1202: /*
        !          1203:  * return information about kernel precision timekeeping
        !          1204:  */
        !          1205: static int
        !          1206: sysctl_kern_ntptime(SYSCTLFN_ARGS)
        !          1207: {
        !          1208:        struct sysctlnode node;
        !          1209:        struct ntptimeval ntv;
        !          1210:
        !          1211:        ntp_gettime(&ntv);
1.25      atatat   1212:
                   1213:        node = *rnode;
                   1214:        node.sysctl_data = &ntv;
                   1215:        node.sysctl_size = sizeof(ntv);
                   1216:        return (sysctl_lookup(SYSCTLFN_CALL(&node)));
                   1217: }
                   1218:
                   1219: SYSCTL_SETUP(sysctl_kern_ntptime_setup, "sysctl kern.ntptime node setup")
                   1220: {
                   1221:
1.26      atatat   1222:        sysctl_createv(clog, 0, NULL, NULL,
                   1223:                       CTLFLAG_PERMANENT,
1.25      atatat   1224:                       CTLTYPE_NODE, "kern", NULL,
                   1225:                       NULL, 0, NULL, 0,
                   1226:                       CTL_KERN, CTL_EOL);
                   1227:
1.26      atatat   1228:        sysctl_createv(clog, 0, NULL, NULL,
                   1229:                       CTLFLAG_PERMANENT,
1.27      atatat   1230:                       CTLTYPE_STRUCT, "ntptime",
                   1231:                       SYSCTL_DESCR("Kernel clock values for NTP"),
1.25      atatat   1232:                       sysctl_kern_ntptime, 0, NULL,
                   1233:                       sizeof(struct ntptimeval),
                   1234:                       CTL_KERN, KERN_NTPTIME, CTL_EOL);
1.1       jonathan 1235: }
1.4       thorpej  1236: #else /* !NTP */
1.13      bjh21    1237: /* For some reason, raising SIGSYS (as sys_nosys would) is problematic. */
                   1238:
1.4       thorpej  1239: int
1.29.8.2! yamt     1240: sys___ntp_gettime30(l, v, retval)
1.22      thorpej  1241:        struct lwp *l;
1.4       thorpej  1242:        void *v;
                   1243:        register_t *retval;
                   1244: {
1.19      simonb   1245:
1.4       thorpej  1246:        return(ENOSYS);
                   1247: }
1.29.8.2! yamt     1248:
        !          1249: #ifdef COMPAT_30
        !          1250: int
        !          1251: compat_30_sys_ntp_gettime(l, v, retval)
        !          1252:        struct lwp *l;
        !          1253:        void *v;
        !          1254:        register_t *retval;
        !          1255: {
        !          1256:
        !          1257:        return(ENOSYS);
        !          1258: }
        !          1259: #endif
1.13      bjh21    1260: #endif /* !NTP */

CVSweb <webmaster@jp.NetBSD.org>