10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 23*1389Sdmick * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <sys/types.h> 300Sstevel@tonic-gate #include <sys/param.h> 310Sstevel@tonic-gate #include <sys/systm.h> 320Sstevel@tonic-gate #include <sys/disp.h> 330Sstevel@tonic-gate #include <sys/var.h> 340Sstevel@tonic-gate #include <sys/cmn_err.h> 350Sstevel@tonic-gate #include <sys/debug.h> 360Sstevel@tonic-gate #include <sys/x86_archext.h> 370Sstevel@tonic-gate #include <sys/archsystm.h> 380Sstevel@tonic-gate #include <sys/cpuvar.h> 390Sstevel@tonic-gate #include <sys/psm_defs.h> 400Sstevel@tonic-gate #include <sys/clock.h> 410Sstevel@tonic-gate #include <sys/atomic.h> 420Sstevel@tonic-gate #include <sys/lockstat.h> 430Sstevel@tonic-gate #include <sys/smp_impldefs.h> 440Sstevel@tonic-gate #include <sys/dtrace.h> 450Sstevel@tonic-gate #include <sys/time.h> 460Sstevel@tonic-gate 470Sstevel@tonic-gate /* 480Sstevel@tonic-gate * Using the Pentium's TSC register for gethrtime() 490Sstevel@tonic-gate * ------------------------------------------------ 500Sstevel@tonic-gate * 510Sstevel@tonic-gate * The Pentium family, like many chip architectures, has a high-resolution 520Sstevel@tonic-gate * timestamp counter ("TSC") which increments once per CPU cycle. The contents 530Sstevel@tonic-gate * of the timestamp counter are read with the RDTSC instruction. 540Sstevel@tonic-gate * 550Sstevel@tonic-gate * As with its UltraSPARC equivalent (the %tick register), TSC's cycle count 560Sstevel@tonic-gate * must be translated into nanoseconds in order to implement gethrtime(). 570Sstevel@tonic-gate * We avoid inducing floating point operations in this conversion by 580Sstevel@tonic-gate * implementing the same nsec_scale algorithm as that found in the sun4u 590Sstevel@tonic-gate * platform code. The sun4u NATIVE_TIME_TO_NSEC_SCALE block comment contains 600Sstevel@tonic-gate * a detailed description of the algorithm; the comment is not reproduced 610Sstevel@tonic-gate * here. This implementation differs only in its value for NSEC_SHIFT: 620Sstevel@tonic-gate * we implement an NSEC_SHIFT of 5 (instead of sun4u's 4) to allow for 630Sstevel@tonic-gate * 60 MHz Pentiums. 640Sstevel@tonic-gate * 650Sstevel@tonic-gate * While TSC and %tick are both cycle counting registers, TSC's functionality 660Sstevel@tonic-gate * falls short in several critical ways: 670Sstevel@tonic-gate * 680Sstevel@tonic-gate * (a) TSCs on different CPUs are not guaranteed to be in sync. While in 690Sstevel@tonic-gate * practice they often _are_ in sync, this isn't guaranteed by the 700Sstevel@tonic-gate * architecture. 710Sstevel@tonic-gate * 720Sstevel@tonic-gate * (b) The TSC cannot be reliably set to an arbitrary value. The architecture 730Sstevel@tonic-gate * only supports writing the low 32-bits of TSC, making it impractical 740Sstevel@tonic-gate * to rewrite. 750Sstevel@tonic-gate * 760Sstevel@tonic-gate * (c) The architecture doesn't have the capacity to interrupt based on 770Sstevel@tonic-gate * arbitrary values of TSC; there is no TICK_CMPR equivalent. 780Sstevel@tonic-gate * 790Sstevel@tonic-gate * Together, (a) and (b) imply that software must track the skew between 800Sstevel@tonic-gate * TSCs and account for it (it is assumed that while there may exist skew, 810Sstevel@tonic-gate * there does not exist drift). To determine the skew between CPUs, we 820Sstevel@tonic-gate * have newly onlined CPUs call tsc_sync_slave(), while the CPU performing 830Sstevel@tonic-gate * the online operation calls tsc_sync_master(). Once both CPUs are ready, 840Sstevel@tonic-gate * the master sets a shared flag, and each reads its TSC register. To reduce 850Sstevel@tonic-gate * bias, we then wait until both CPUs are ready again, but this time the 860Sstevel@tonic-gate * slave sets the shared flag, and each reads its TSC register again. The 870Sstevel@tonic-gate * master compares the average of the two sample values, and, if observable 880Sstevel@tonic-gate * skew is found, changes the gethrtimef function pointer to point to a 890Sstevel@tonic-gate * gethrtime() implementation which will take the discovered skew into 900Sstevel@tonic-gate * consideration. 910Sstevel@tonic-gate * 920Sstevel@tonic-gate * In the absence of time-of-day clock adjustments, gethrtime() must stay in 930Sstevel@tonic-gate * sync with gettimeofday(). This is problematic; given (c), the software 940Sstevel@tonic-gate * cannot drive its time-of-day source from TSC, and yet they must somehow be 950Sstevel@tonic-gate * kept in sync. We implement this by having a routine, tsc_tick(), which 960Sstevel@tonic-gate * is called once per second from the interrupt which drives time-of-day. 970Sstevel@tonic-gate * tsc_tick() recalculates nsec_scale based on the number of the CPU cycles 980Sstevel@tonic-gate * since boot versus the number of seconds since boot. This algorithm 990Sstevel@tonic-gate * becomes more accurate over time and converges quickly; the error in 1000Sstevel@tonic-gate * nsec_scale is typically under 1 ppm less than 10 seconds after boot, and 1010Sstevel@tonic-gate * is less than 100 ppb 1 minute after boot. 1020Sstevel@tonic-gate * 1030Sstevel@tonic-gate * Note that the hrtime base for gethrtime, tsc_hrtime_base, is modified 1040Sstevel@tonic-gate * atomically with nsec_scale under CLOCK_LOCK. This assures that time 1050Sstevel@tonic-gate * monotonically increases. 1060Sstevel@tonic-gate */ 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate #define NSEC_SHIFT 5 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate static uint_t nsec_scale; 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate /* 1130Sstevel@tonic-gate * These two variables used to be grouped together inside of a structure that 1140Sstevel@tonic-gate * lived on a single cache line. A regression (bug ID 4623398) caused the 1150Sstevel@tonic-gate * compiler to emit code that "optimized" away the while-loops below. The 1160Sstevel@tonic-gate * result was that no synchronization between the onlining and onlined CPUs 1170Sstevel@tonic-gate * took place. 1180Sstevel@tonic-gate */ 1190Sstevel@tonic-gate static volatile int tsc_ready; 1200Sstevel@tonic-gate static volatile int tsc_sync_go; 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate /* 1230Sstevel@tonic-gate * Used as indices into the tsc_sync_snaps[] array. 1240Sstevel@tonic-gate */ 1250Sstevel@tonic-gate #define TSC_MASTER 0 1260Sstevel@tonic-gate #define TSC_SLAVE 1 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate /* 1290Sstevel@tonic-gate * Used in the tsc_master_sync()/tsc_slave_sync() rendezvous. 1300Sstevel@tonic-gate */ 1310Sstevel@tonic-gate #define TSC_SYNC_STOP 1 1320Sstevel@tonic-gate #define TSC_SYNC_GO 2 1330Sstevel@tonic-gate #define TSC_SYNC_AGAIN 3 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate /* 1360Sstevel@tonic-gate * XX64 Is the faster way to do this with a 64-bit ABI? 1370Sstevel@tonic-gate */ 1380Sstevel@tonic-gate #define TSC_CONVERT_AND_ADD(tsc, hrt, scale) { \ 1390Sstevel@tonic-gate unsigned int *_l = (unsigned int *)&(tsc); \ 1400Sstevel@tonic-gate (hrt) += mul32(_l[1], scale) << NSEC_SHIFT; \ 1410Sstevel@tonic-gate (hrt) += mul32(_l[0], scale) >> (32 - NSEC_SHIFT); \ 1420Sstevel@tonic-gate } 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate #define TSC_CONVERT(tsc, hrt, scale) { \ 1450Sstevel@tonic-gate unsigned int *_l = (unsigned int *)&(tsc); \ 1460Sstevel@tonic-gate (hrt) = mul32(_l[1], scale) << NSEC_SHIFT; \ 1470Sstevel@tonic-gate (hrt) += mul32(_l[0], scale) >> (32 - NSEC_SHIFT); \ 1480Sstevel@tonic-gate } 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate static int tsc_max_delta; 1530Sstevel@tonic-gate static hrtime_t tsc_sync_snaps[2]; 1540Sstevel@tonic-gate static hrtime_t tsc_sync_delta[NCPU]; 1550Sstevel@tonic-gate static hrtime_t tsc_sync_tick_delta[NCPU]; 1560Sstevel@tonic-gate static hrtime_t tsc_last = 0; 1570Sstevel@tonic-gate static hrtime_t tsc_last_jumped = 0; 1580Sstevel@tonic-gate static hrtime_t tsc_hrtime_base = 0; 1590Sstevel@tonic-gate static int tsc_jumped = 0; 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate static hrtime_t shadow_tsc_hrtime_base; 1620Sstevel@tonic-gate static hrtime_t shadow_tsc_last; 1630Sstevel@tonic-gate static uint_t shadow_nsec_scale; 1640Sstevel@tonic-gate static uint32_t shadow_hres_lock; 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate /* 1670Sstevel@tonic-gate * Called by the master after the sync operation is complete. If the 1680Sstevel@tonic-gate * slave is discovered to lag, gethrtimef will be changed to point to 1690Sstevel@tonic-gate * tsc_gethrtime_delta(). 1700Sstevel@tonic-gate */ 1710Sstevel@tonic-gate static void 1720Sstevel@tonic-gate tsc_digest(processorid_t target) 1730Sstevel@tonic-gate { 1740Sstevel@tonic-gate hrtime_t tdelta, hdelta = 0; 1750Sstevel@tonic-gate int max = tsc_max_delta; 1760Sstevel@tonic-gate processorid_t source = CPU->cpu_id; 1770Sstevel@tonic-gate int update; 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate update = tsc_sync_delta[source] != 0 || 1800Sstevel@tonic-gate gethrtimef == tsc_gethrtime_delta; 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate /* 1830Sstevel@tonic-gate * We divide by 2 since each of the data points is the sum of two TSC 1840Sstevel@tonic-gate * reads; this takes the average of the two. 1850Sstevel@tonic-gate */ 1860Sstevel@tonic-gate tdelta = (tsc_sync_snaps[TSC_SLAVE] - tsc_sync_snaps[TSC_MASTER]) / 2; 1870Sstevel@tonic-gate if ((tdelta > max) || ((tdelta >= 0) && update)) { 1880Sstevel@tonic-gate TSC_CONVERT_AND_ADD(tdelta, hdelta, nsec_scale); 1890Sstevel@tonic-gate tsc_sync_delta[target] = tsc_sync_delta[source] - hdelta; 1900Sstevel@tonic-gate tsc_sync_tick_delta[target] = -tdelta; 1910Sstevel@tonic-gate gethrtimef = tsc_gethrtime_delta; 1920Sstevel@tonic-gate gethrtimeunscaledf = tsc_gethrtimeunscaled_delta; 1930Sstevel@tonic-gate return; 1940Sstevel@tonic-gate } 1950Sstevel@tonic-gate 1960Sstevel@tonic-gate tdelta = -tdelta; 1970Sstevel@tonic-gate if ((tdelta > max) || update) { 1980Sstevel@tonic-gate TSC_CONVERT_AND_ADD(tdelta, hdelta, nsec_scale); 1990Sstevel@tonic-gate tsc_sync_delta[target] = tsc_sync_delta[source] + hdelta; 2000Sstevel@tonic-gate tsc_sync_tick_delta[target] = tdelta; 2010Sstevel@tonic-gate gethrtimef = tsc_gethrtime_delta; 2020Sstevel@tonic-gate gethrtimeunscaledf = tsc_gethrtimeunscaled_delta; 2030Sstevel@tonic-gate } 2040Sstevel@tonic-gate 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate /* 2080Sstevel@tonic-gate * Called by a CPU which has just performed an online operation on another 2090Sstevel@tonic-gate * CPU. It is expected that the newly onlined CPU will call tsc_sync_slave(). 2100Sstevel@tonic-gate */ 2110Sstevel@tonic-gate void 2120Sstevel@tonic-gate tsc_sync_master(processorid_t slave) 2130Sstevel@tonic-gate { 2140Sstevel@tonic-gate int flags; 2150Sstevel@tonic-gate hrtime_t hrt; 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate ASSERT(tsc_sync_go != TSC_SYNC_GO); 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate flags = clear_int_flag(); 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate /* 2220Sstevel@tonic-gate * Wait for the slave CPU to arrive. 2230Sstevel@tonic-gate */ 2240Sstevel@tonic-gate while (tsc_ready != TSC_SYNC_GO) 2250Sstevel@tonic-gate continue; 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate /* 2280Sstevel@tonic-gate * Tell the slave CPU to begin reading its TSC; read our own. 2290Sstevel@tonic-gate */ 2300Sstevel@tonic-gate tsc_sync_go = TSC_SYNC_GO; 2310Sstevel@tonic-gate hrt = tsc_read(); 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate /* 2340Sstevel@tonic-gate * Tell the slave that we're ready, and wait for the slave to tell us 2350Sstevel@tonic-gate * to read our TSC again. 2360Sstevel@tonic-gate */ 2370Sstevel@tonic-gate tsc_ready = TSC_SYNC_AGAIN; 2380Sstevel@tonic-gate while (tsc_sync_go != TSC_SYNC_AGAIN) 2390Sstevel@tonic-gate continue; 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate hrt += tsc_read(); 2420Sstevel@tonic-gate tsc_sync_snaps[TSC_MASTER] = hrt; 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate /* 2450Sstevel@tonic-gate * Wait for the slave to finish reading its TSC. 2460Sstevel@tonic-gate */ 2470Sstevel@tonic-gate while (tsc_ready != TSC_SYNC_STOP) 2480Sstevel@tonic-gate continue; 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate /* 2510Sstevel@tonic-gate * At this point, both CPUs have performed their tsc_read() calls. 2520Sstevel@tonic-gate * We'll digest it now before letting the slave CPU return. 2530Sstevel@tonic-gate */ 2540Sstevel@tonic-gate tsc_digest(slave); 2550Sstevel@tonic-gate tsc_sync_go = TSC_SYNC_STOP; 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate restore_int_flag(flags); 2580Sstevel@tonic-gate } 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate /* 2610Sstevel@tonic-gate * Called by a CPU which has just been onlined. It is expected that the CPU 2620Sstevel@tonic-gate * performing the online operation will call tsc_sync_master(). 2630Sstevel@tonic-gate */ 2640Sstevel@tonic-gate void 2650Sstevel@tonic-gate tsc_sync_slave(void) 2660Sstevel@tonic-gate { 2670Sstevel@tonic-gate int flags; 2680Sstevel@tonic-gate hrtime_t hrt; 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate ASSERT(tsc_sync_go != TSC_SYNC_GO); 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate flags = clear_int_flag(); 2730Sstevel@tonic-gate 274*1389Sdmick /* to test tsc_gethrtime_delta, add wrmsr(REG_TSC, 0) here */ 275*1389Sdmick 2760Sstevel@tonic-gate /* 2770Sstevel@tonic-gate * Tell the master CPU that we're ready, and wait for the master to 2780Sstevel@tonic-gate * tell us to begin reading our TSC. 2790Sstevel@tonic-gate */ 2800Sstevel@tonic-gate tsc_ready = TSC_SYNC_GO; 2810Sstevel@tonic-gate while (tsc_sync_go != TSC_SYNC_GO) 2820Sstevel@tonic-gate continue; 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate hrt = tsc_read(); 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate /* 2870Sstevel@tonic-gate * Wait for the master CPU to be ready to read its TSC again. 2880Sstevel@tonic-gate */ 2890Sstevel@tonic-gate while (tsc_ready != TSC_SYNC_AGAIN) 2900Sstevel@tonic-gate continue; 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate /* 2930Sstevel@tonic-gate * Tell the master CPU to read its TSC again; read ours again. 2940Sstevel@tonic-gate */ 2950Sstevel@tonic-gate tsc_sync_go = TSC_SYNC_AGAIN; 2960Sstevel@tonic-gate 2970Sstevel@tonic-gate hrt += tsc_read(); 2980Sstevel@tonic-gate tsc_sync_snaps[TSC_SLAVE] = hrt; 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate /* 3010Sstevel@tonic-gate * Tell the master that we're done, and wait to be dismissed. 3020Sstevel@tonic-gate */ 3030Sstevel@tonic-gate tsc_ready = TSC_SYNC_STOP; 3040Sstevel@tonic-gate while (tsc_sync_go != TSC_SYNC_STOP) 3050Sstevel@tonic-gate continue; 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate restore_int_flag(flags); 3080Sstevel@tonic-gate } 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate void 3110Sstevel@tonic-gate tsc_hrtimeinit(uint64_t cpu_freq_hz) 3120Sstevel@tonic-gate { 3130Sstevel@tonic-gate longlong_t tsc; 3140Sstevel@tonic-gate int flags; 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate /* 3170Sstevel@tonic-gate * cpu_freq_hz is the measured cpu frequency in hertz 3180Sstevel@tonic-gate */ 3190Sstevel@tonic-gate 3200Sstevel@tonic-gate /* 3210Sstevel@tonic-gate * We can't accommodate CPUs slower than 31.25 MHz. 3220Sstevel@tonic-gate */ 3230Sstevel@tonic-gate ASSERT(cpu_freq_hz > NANOSEC / (1 << NSEC_SHIFT)); 3240Sstevel@tonic-gate nsec_scale = 3250Sstevel@tonic-gate (uint_t) 3260Sstevel@tonic-gate (((uint64_t)NANOSEC << (32 - NSEC_SHIFT)) / cpu_freq_hz); 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate flags = clear_int_flag(); 3290Sstevel@tonic-gate tsc = tsc_read(); 3300Sstevel@tonic-gate (void) tsc_gethrtime(); 3310Sstevel@tonic-gate tsc_max_delta = tsc_read() - tsc; 3320Sstevel@tonic-gate restore_int_flag(flags); 3330Sstevel@tonic-gate } 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate /* 336*1389Sdmick * Called once per second on some CPU from the cyclic subsystem's 337*1389Sdmick * CY_HIGH_LEVEL interrupt. (no longer CPU0-only) 3380Sstevel@tonic-gate */ 3390Sstevel@tonic-gate void 3400Sstevel@tonic-gate tsc_tick(void) 3410Sstevel@tonic-gate { 3420Sstevel@tonic-gate hrtime_t now, delta; 3430Sstevel@tonic-gate ushort_t spl; 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate /* 3460Sstevel@tonic-gate * Before we set the new variables, we set the shadow values. This 3470Sstevel@tonic-gate * allows for lock free operation in dtrace_gethrtime(). 3480Sstevel@tonic-gate */ 3490Sstevel@tonic-gate lock_set_spl((lock_t *)&shadow_hres_lock + HRES_LOCK_OFFSET, 3500Sstevel@tonic-gate ipltospl(CBE_HIGH_PIL), &spl); 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate shadow_tsc_hrtime_base = tsc_hrtime_base; 3530Sstevel@tonic-gate shadow_tsc_last = tsc_last; 3540Sstevel@tonic-gate shadow_nsec_scale = nsec_scale; 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate shadow_hres_lock++; 3570Sstevel@tonic-gate splx(spl); 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate CLOCK_LOCK(&spl); 3600Sstevel@tonic-gate 3610Sstevel@tonic-gate now = tsc_read(); 3620Sstevel@tonic-gate 363*1389Sdmick if (gethrtimef == tsc_gethrtime_delta) 364*1389Sdmick now += tsc_sync_tick_delta[CPU->cpu_id]; 365*1389Sdmick 3660Sstevel@tonic-gate if (now < tsc_last) { 3670Sstevel@tonic-gate /* 3680Sstevel@tonic-gate * The TSC has just jumped into the past. We assume that 3690Sstevel@tonic-gate * this is due to a suspend/resume cycle, and we're going 3700Sstevel@tonic-gate * to use the _current_ value of TSC as the delta. This 3710Sstevel@tonic-gate * will keep tsc_hrtime_base correct. We're also going to 3720Sstevel@tonic-gate * assume that rate of tsc does not change after a suspend 3730Sstevel@tonic-gate * resume (i.e nsec_scale remains the same). 3740Sstevel@tonic-gate */ 3750Sstevel@tonic-gate delta = now; 3760Sstevel@tonic-gate tsc_last_jumped += tsc_last; 3770Sstevel@tonic-gate tsc_jumped = 1; 3780Sstevel@tonic-gate } else { 3790Sstevel@tonic-gate /* 3800Sstevel@tonic-gate * Determine the number of TSC ticks since the last clock 3810Sstevel@tonic-gate * tick, and add that to the hrtime base. 3820Sstevel@tonic-gate */ 3830Sstevel@tonic-gate delta = now - tsc_last; 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate TSC_CONVERT_AND_ADD(delta, tsc_hrtime_base, nsec_scale); 3870Sstevel@tonic-gate tsc_last = now; 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate CLOCK_UNLOCK(spl); 3900Sstevel@tonic-gate } 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate hrtime_t 3930Sstevel@tonic-gate tsc_gethrtime(void) 3940Sstevel@tonic-gate { 3950Sstevel@tonic-gate uint32_t old_hres_lock; 3960Sstevel@tonic-gate hrtime_t tsc, hrt; 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate do { 3990Sstevel@tonic-gate old_hres_lock = hres_lock; 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate if ((tsc = tsc_read()) >= tsc_last) { 4020Sstevel@tonic-gate /* 4030Sstevel@tonic-gate * It would seem to be obvious that this is true 4040Sstevel@tonic-gate * (that is, the past is less than the present), 4050Sstevel@tonic-gate * but it isn't true in the presence of suspend/resume 4060Sstevel@tonic-gate * cycles. If we manage to call gethrtime() 4070Sstevel@tonic-gate * after a resume, but before the first call to 4080Sstevel@tonic-gate * tsc_tick(), we will see the jump. In this case, 4090Sstevel@tonic-gate * we will simply use the value in TSC as the delta. 4100Sstevel@tonic-gate */ 4110Sstevel@tonic-gate tsc -= tsc_last; 4120Sstevel@tonic-gate } else if (tsc >= tsc_last - 2*tsc_max_delta) { 4130Sstevel@tonic-gate /* 4140Sstevel@tonic-gate * There is a chance that tsc_tick() has just run on 4150Sstevel@tonic-gate * another CPU, and we have drifted just enough so that 4160Sstevel@tonic-gate * we appear behind tsc_last. In this case, force the 4170Sstevel@tonic-gate * delta to be zero. 4180Sstevel@tonic-gate */ 4190Sstevel@tonic-gate tsc = 0; 4200Sstevel@tonic-gate } 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate hrt = tsc_hrtime_base; 4230Sstevel@tonic-gate 4240Sstevel@tonic-gate TSC_CONVERT_AND_ADD(tsc, hrt, nsec_scale); 4250Sstevel@tonic-gate } while ((old_hres_lock & ~1) != hres_lock); 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate return (hrt); 4280Sstevel@tonic-gate } 4290Sstevel@tonic-gate 4300Sstevel@tonic-gate /* 4310Sstevel@tonic-gate * This is similar to the above, but it cannot actually spin on hres_lock. 4320Sstevel@tonic-gate * As a result, it caches all of the variables it needs; if the variables 4330Sstevel@tonic-gate * don't change, it's done. 4340Sstevel@tonic-gate */ 4350Sstevel@tonic-gate hrtime_t 4360Sstevel@tonic-gate dtrace_gethrtime(void) 4370Sstevel@tonic-gate { 4380Sstevel@tonic-gate uint32_t old_hres_lock; 4390Sstevel@tonic-gate hrtime_t tsc, hrt; 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate do { 4420Sstevel@tonic-gate old_hres_lock = hres_lock; 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate /* 4450Sstevel@tonic-gate * See the comments in tsc_gethrtime(), above. 4460Sstevel@tonic-gate */ 4470Sstevel@tonic-gate if ((tsc = tsc_read()) >= tsc_last) 4480Sstevel@tonic-gate tsc -= tsc_last; 4490Sstevel@tonic-gate else if (tsc >= tsc_last - 2*tsc_max_delta) 4500Sstevel@tonic-gate tsc = 0; 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate hrt = tsc_hrtime_base; 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate TSC_CONVERT_AND_ADD(tsc, hrt, nsec_scale); 4550Sstevel@tonic-gate 4560Sstevel@tonic-gate if ((old_hres_lock & ~1) == hres_lock) 4570Sstevel@tonic-gate break; 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate /* 4600Sstevel@tonic-gate * If we're here, the clock lock is locked -- or it has been 4610Sstevel@tonic-gate * unlocked and locked since we looked. This may be due to 4620Sstevel@tonic-gate * tsc_tick() running on another CPU -- or it may be because 4630Sstevel@tonic-gate * some code path has ended up in dtrace_probe() with 4640Sstevel@tonic-gate * CLOCK_LOCK held. We'll try to determine that we're in 4650Sstevel@tonic-gate * the former case by taking another lap if the lock has 4660Sstevel@tonic-gate * changed since when we first looked at it. 4670Sstevel@tonic-gate */ 4680Sstevel@tonic-gate if (old_hres_lock != hres_lock) 4690Sstevel@tonic-gate continue; 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate /* 4720Sstevel@tonic-gate * So the lock was and is locked. We'll use the old data 4730Sstevel@tonic-gate * instead. 4740Sstevel@tonic-gate */ 4750Sstevel@tonic-gate old_hres_lock = shadow_hres_lock; 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate /* 4780Sstevel@tonic-gate * See the comments in tsc_gethrtime(), above. 4790Sstevel@tonic-gate */ 4800Sstevel@tonic-gate if ((tsc = tsc_read()) >= shadow_tsc_last) 4810Sstevel@tonic-gate tsc -= shadow_tsc_last; 482*1389Sdmick else if (tsc >= shadow_tsc_last - 2 * tsc_max_delta) 4830Sstevel@tonic-gate tsc = 0; 4840Sstevel@tonic-gate 4850Sstevel@tonic-gate hrt = shadow_tsc_hrtime_base; 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate TSC_CONVERT_AND_ADD(tsc, hrt, shadow_nsec_scale); 4880Sstevel@tonic-gate } while ((old_hres_lock & ~1) != shadow_hres_lock); 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate return (hrt); 4910Sstevel@tonic-gate } 4920Sstevel@tonic-gate 4930Sstevel@tonic-gate hrtime_t 4940Sstevel@tonic-gate tsc_gethrtime_delta(void) 4950Sstevel@tonic-gate { 496*1389Sdmick uint32_t old_hres_lock; 497*1389Sdmick hrtime_t tsc, hrt; 4980Sstevel@tonic-gate int flags; 4990Sstevel@tonic-gate 500*1389Sdmick do { 501*1389Sdmick old_hres_lock = hres_lock; 502*1389Sdmick 503*1389Sdmick /* 504*1389Sdmick * We need to disable interrupts here to assure that we 505*1389Sdmick * don't migrate between the call to tsc_read() and 506*1389Sdmick * adding the CPU's TSC tick delta. Note that disabling 507*1389Sdmick * and reenabling preemption is forbidden here because 508*1389Sdmick * we may be in the middle of a fast trap. In the amd64 509*1389Sdmick * kernel we cannot tolerate preemption during a fast 510*1389Sdmick * trap. See _update_sregs(). 511*1389Sdmick */ 5120Sstevel@tonic-gate 513*1389Sdmick flags = clear_int_flag(); 514*1389Sdmick tsc = tsc_read() + tsc_sync_tick_delta[CPU->cpu_id]; 515*1389Sdmick restore_int_flag(flags); 516*1389Sdmick 517*1389Sdmick /* See comments in tsc_gethrtime() above */ 518*1389Sdmick 519*1389Sdmick if (tsc >= tsc_last) { 520*1389Sdmick tsc -= tsc_last; 521*1389Sdmick } else if (tsc >= tsc_last - 2 * tsc_max_delta) { 522*1389Sdmick tsc = 0; 523*1389Sdmick } 524*1389Sdmick 525*1389Sdmick hrt = tsc_hrtime_base; 526*1389Sdmick 527*1389Sdmick TSC_CONVERT_AND_ADD(tsc, hrt, nsec_scale); 528*1389Sdmick } while ((old_hres_lock & ~1) != hres_lock); 5290Sstevel@tonic-gate 5300Sstevel@tonic-gate return (hrt); 5310Sstevel@tonic-gate } 5320Sstevel@tonic-gate 5330Sstevel@tonic-gate extern uint64_t cpu_freq_hz; 5340Sstevel@tonic-gate extern int tsc_gethrtime_enable; 5350Sstevel@tonic-gate 5360Sstevel@tonic-gate /* 5370Sstevel@tonic-gate * The following converts nanoseconds of highres-time to ticks 5380Sstevel@tonic-gate */ 5390Sstevel@tonic-gate 5400Sstevel@tonic-gate static uint64_t 5410Sstevel@tonic-gate hrtime2tick(hrtime_t ts) 5420Sstevel@tonic-gate { 5430Sstevel@tonic-gate hrtime_t q = ts / NANOSEC; 5440Sstevel@tonic-gate hrtime_t r = ts - (q * NANOSEC); 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate return (q * cpu_freq_hz + ((r * cpu_freq_hz) / NANOSEC)); 5470Sstevel@tonic-gate } 5480Sstevel@tonic-gate 5490Sstevel@tonic-gate /* 5500Sstevel@tonic-gate * This is used to convert scaled high-res time from nanoseconds to 5510Sstevel@tonic-gate * unscaled hardware ticks. (Read from hardware timestamp counter) 5520Sstevel@tonic-gate */ 5530Sstevel@tonic-gate 5540Sstevel@tonic-gate uint64_t 5550Sstevel@tonic-gate unscalehrtime(hrtime_t ts) 5560Sstevel@tonic-gate { 5570Sstevel@tonic-gate if (tsc_gethrtime_enable) { 5580Sstevel@tonic-gate uint64_t unscale = 0; 5590Sstevel@tonic-gate hrtime_t rescale; 5600Sstevel@tonic-gate hrtime_t diff = ts; 5610Sstevel@tonic-gate 5620Sstevel@tonic-gate while (diff > (nsec_per_tick)) { 5630Sstevel@tonic-gate unscale += hrtime2tick(diff); 5640Sstevel@tonic-gate rescale = unscale; 5650Sstevel@tonic-gate scalehrtime(&rescale); 5660Sstevel@tonic-gate diff = ts - rescale; 5670Sstevel@tonic-gate } 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate return (unscale); 5700Sstevel@tonic-gate } 5710Sstevel@tonic-gate return (0); 5720Sstevel@tonic-gate } 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate 5750Sstevel@tonic-gate hrtime_t 5760Sstevel@tonic-gate tsc_gethrtimeunscaled(void) 5770Sstevel@tonic-gate { 5780Sstevel@tonic-gate uint32_t old_hres_lock; 5790Sstevel@tonic-gate hrtime_t tsc; 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate do { 5820Sstevel@tonic-gate old_hres_lock = hres_lock; 5830Sstevel@tonic-gate 5840Sstevel@tonic-gate if ((tsc = tsc_read()) < tsc_last) { 5850Sstevel@tonic-gate /* 5860Sstevel@tonic-gate * see comments in tsc_gethrtime 5870Sstevel@tonic-gate */ 5880Sstevel@tonic-gate tsc += tsc_last_jumped; 5890Sstevel@tonic-gate } 5900Sstevel@tonic-gate 5910Sstevel@tonic-gate } while ((old_hres_lock & ~1) != hres_lock); 5920Sstevel@tonic-gate 5930Sstevel@tonic-gate return (tsc); 5940Sstevel@tonic-gate } 5950Sstevel@tonic-gate 5960Sstevel@tonic-gate 5970Sstevel@tonic-gate /* Convert a tsc timestamp to nanoseconds */ 5980Sstevel@tonic-gate void 5990Sstevel@tonic-gate tsc_scalehrtime(hrtime_t *tsc) 6000Sstevel@tonic-gate { 6010Sstevel@tonic-gate hrtime_t hrt; 6020Sstevel@tonic-gate hrtime_t mytsc; 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate if (tsc == NULL) 6050Sstevel@tonic-gate return; 6060Sstevel@tonic-gate mytsc = *tsc; 6070Sstevel@tonic-gate 6080Sstevel@tonic-gate TSC_CONVERT(mytsc, hrt, nsec_scale); 6090Sstevel@tonic-gate *tsc = hrt; 6100Sstevel@tonic-gate } 6110Sstevel@tonic-gate 6120Sstevel@tonic-gate hrtime_t 6130Sstevel@tonic-gate tsc_gethrtimeunscaled_delta(void) 6140Sstevel@tonic-gate { 6150Sstevel@tonic-gate hrtime_t hrt; 6160Sstevel@tonic-gate int flags; 6170Sstevel@tonic-gate 6180Sstevel@tonic-gate /* 6190Sstevel@tonic-gate * Similarly to tsc_gethrtime_delta, we need to disable preemption 6200Sstevel@tonic-gate * to prevent migration between the call to tsc_gethrtimeunscaled 6210Sstevel@tonic-gate * and adding the CPU's hrtime delta. Note that disabling and 6220Sstevel@tonic-gate * reenabling preemption is forbidden here because we may be in the 6230Sstevel@tonic-gate * middle of a fast trap. In the amd64 kernel we cannot tolerate 6240Sstevel@tonic-gate * preemption during a fast trap. See _update_sregs(). 6250Sstevel@tonic-gate */ 6260Sstevel@tonic-gate 6270Sstevel@tonic-gate flags = clear_int_flag(); 6280Sstevel@tonic-gate hrt = tsc_gethrtimeunscaled() + tsc_sync_tick_delta[CPU->cpu_id]; 6290Sstevel@tonic-gate restore_int_flag(flags); 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate return (hrt); 6320Sstevel@tonic-gate } 633