tsc.c revision 222869
14Srgrimes/*- 2110379Sphk * Copyright (c) 1998-2003 Poul-Henning Kamp 34Srgrimes * All rights reserved. 44Srgrimes * 54Srgrimes * Redistribution and use in source and binary forms, with or without 64Srgrimes * modification, are permitted provided that the following conditions 74Srgrimes * are met: 84Srgrimes * 1. Redistributions of source code must retain the above copyright 94Srgrimes * notice, this list of conditions and the following disclaimer. 104Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 114Srgrimes * notice, this list of conditions and the following disclaimer in the 124Srgrimes * documentation and/or other materials provided with the distribution. 134Srgrimes * 14110379Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 154Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 164Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17110379Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 184Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 194Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 204Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 214Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 224Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 234Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 244Srgrimes * SUCH DAMAGE. 254Srgrimes */ 264Srgrimes 27115683Sobrien#include <sys/cdefs.h> 28115683Sobrien__FBSDID("$FreeBSD: head/sys/x86/x86/tsc.c 222869 2011-06-08 20:08:06Z jkim $"); 29115683Sobrien 3016299Spst#include "opt_clock.h" 3113228Swollman 322056Swollman#include <sys/param.h> 33167905Snjl#include <sys/bus.h> 34167905Snjl#include <sys/cpu.h> 35221214Sjkim#include <sys/limits.h> 36167905Snjl#include <sys/malloc.h> 372056Swollman#include <sys/systm.h> 38113348Sdes#include <sys/sysctl.h> 392056Swollman#include <sys/time.h> 4058377Sphk#include <sys/timetc.h> 412056Swollman#include <sys/kernel.h> 4285835Siwasaki#include <sys/power.h> 43113348Sdes#include <sys/smp.h> 444180Sbde#include <machine/clock.h> 45216272Sjkim#include <machine/cputypes.h> 4632054Sphk#include <machine/md_var.h> 4732054Sphk#include <machine/specialreg.h> 4815508Sbde 49167905Snjl#include "cpufreq_if.h" 50167905Snjl 51216163Sjkimuint64_t tsc_freq; 52184102Sjkimint tsc_is_invariant; 53220579Sjkimint tsc_perf_stat; 54220579Sjkim 55167905Snjlstatic eventhandler_tag tsc_levels_tag, tsc_pre_tag, tsc_post_tag; 561390Ssos 57184102SjkimSYSCTL_INT(_kern_timecounter, OID_AUTO, invariant_tsc, CTLFLAG_RDTUN, 58184108Sjkim &tsc_is_invariant, 0, "Indicates whether the TSC is P-state invariant"); 59184108SjkimTUNABLE_INT("kern.timecounter.invariant_tsc", &tsc_is_invariant); 60184102Sjkim 61113348Sdes#ifdef SMP 62113348Sdesstatic int smp_tsc; 63121307SsilbySYSCTL_INT(_kern_timecounter, OID_AUTO, smp_tsc, CTLFLAG_RDTUN, &smp_tsc, 0, 64113348Sdes "Indicates whether the TSC is safe to use in SMP mode"); 65113348SdesTUNABLE_INT("kern.timecounter.smp_tsc", &smp_tsc); 66113348Sdes#endif 67113348Sdes 68219473Sjkimstatic int tsc_disabled; 69219473SjkimSYSCTL_INT(_machdep, OID_AUTO, disable_tsc, CTLFLAG_RDTUN, &tsc_disabled, 0, 70219473Sjkim "Disable x86 Time Stamp Counter"); 71219473SjkimTUNABLE_INT("machdep.disable_tsc", &tsc_disabled); 72219473Sjkim 73220577Sjkimstatic int tsc_skip_calibration; 74220577SjkimSYSCTL_INT(_machdep, OID_AUTO, disable_tsc_calibration, CTLFLAG_RDTUN, 75220577Sjkim &tsc_skip_calibration, 0, "Disable TSC frequency calibration"); 76220577SjkimTUNABLE_INT("machdep.disable_tsc_calibration", &tsc_skip_calibration); 77220577Sjkim 78167905Snjlstatic void tsc_freq_changed(void *arg, const struct cf_level *level, 79167905Snjl int status); 80167905Snjlstatic void tsc_freq_changing(void *arg, const struct cf_level *level, 81167905Snjl int *status); 82222866Sjkimstatic unsigned tsc_get_timecount(struct timecounter *tc); 83222866Sjkimstatic unsigned tsc_get_timecount_lowres(struct timecounter *tc); 84167905Snjlstatic void tsc_levels_changed(void *arg, int unit); 8517353Sbde 8640610Sphkstatic struct timecounter tsc_timecounter = { 8733690Sphk tsc_get_timecount, /* get_timecount */ 8836741Sphk 0, /* no poll_pps */ 89167905Snjl ~0u, /* counter_mask */ 9033690Sphk 0, /* frequency */ 91167905Snjl "TSC", /* name */ 92118987Sphk 800, /* quality (adjusted in code) */ 9333690Sphk}; 9433690Sphk 95221214Sjkim#define VMW_HVMAGIC 0x564d5868 96221214Sjkim#define VMW_HVPORT 0x5658 97221214Sjkim#define VMW_HVCMD_GETVERSION 10 98221214Sjkim#define VMW_HVCMD_GETHZ 45 99221214Sjkim 100221214Sjkimstatic __inline void 101221214Sjkimvmware_hvcall(u_int cmd, u_int *p) 102221214Sjkim{ 103221214Sjkim 104221331Sjkim __asm __volatile("inl %w3, %0" 105221214Sjkim : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) 106221214Sjkim : "0" (VMW_HVMAGIC), "1" (UINT_MAX), "2" (cmd), "3" (VMW_HVPORT) 107221214Sjkim : "memory"); 108221214Sjkim} 109221214Sjkim 110221214Sjkimstatic int 111221214Sjkimtsc_freq_vmware(void) 112221214Sjkim{ 113221214Sjkim char hv_sig[13]; 114221214Sjkim u_int regs[4]; 115221214Sjkim char *p; 116221214Sjkim u_int hv_high; 117221214Sjkim int i; 118221214Sjkim 119221214Sjkim /* 120221214Sjkim * [RFC] CPUID usage for interaction between Hypervisors and Linux. 121221214Sjkim * http://lkml.org/lkml/2008/10/1/246 122221214Sjkim * 123221214Sjkim * KB1009458: Mechanisms to determine if software is running in 124221214Sjkim * a VMware virtual machine 125221214Sjkim * http://kb.vmware.com/kb/1009458 126221214Sjkim */ 127221214Sjkim hv_high = 0; 128221214Sjkim if ((cpu_feature2 & CPUID2_HV) != 0) { 129221214Sjkim do_cpuid(0x40000000, regs); 130221214Sjkim hv_high = regs[0]; 131221214Sjkim for (i = 1, p = hv_sig; i < 4; i++, p += sizeof(regs) / 4) 132221214Sjkim memcpy(p, ®s[i], sizeof(regs[i])); 133221214Sjkim *p = '\0'; 134221214Sjkim if (bootverbose) { 135221214Sjkim /* 136221214Sjkim * HV vendor ID string 137221214Sjkim * ------------+-------------- 138221214Sjkim * KVM "KVMKVMKVM" 139221214Sjkim * Microsoft "Microsoft Hv" 140221214Sjkim * VMware "VMwareVMware" 141221214Sjkim * Xen "XenVMMXenVMM" 142221214Sjkim */ 143221214Sjkim printf("Hypervisor: Origin = \"%s\"\n", hv_sig); 144221214Sjkim } 145221214Sjkim if (strncmp(hv_sig, "VMwareVMware", 12) != 0) 146221214Sjkim return (0); 147221214Sjkim } else { 148221214Sjkim p = getenv("smbios.system.serial"); 149221214Sjkim if (p == NULL) 150221214Sjkim return (0); 151221214Sjkim if (strncmp(p, "VMware-", 7) != 0 && 152221214Sjkim strncmp(p, "VMW", 3) != 0) { 153221214Sjkim freeenv(p); 154221214Sjkim return (0); 155221214Sjkim } 156221214Sjkim freeenv(p); 157221214Sjkim vmware_hvcall(VMW_HVCMD_GETVERSION, regs); 158221214Sjkim if (regs[1] != VMW_HVMAGIC) 159221214Sjkim return (0); 160221214Sjkim } 161221214Sjkim if (hv_high >= 0x40000010) { 162221214Sjkim do_cpuid(0x40000010, regs); 163221214Sjkim tsc_freq = regs[0] * 1000; 164221214Sjkim } else { 165221214Sjkim vmware_hvcall(VMW_HVCMD_GETHZ, regs); 166221214Sjkim if (regs[1] != UINT_MAX) 167221214Sjkim tsc_freq = regs[0] | ((uint64_t)regs[1] << 32); 168221214Sjkim } 169221214Sjkim tsc_is_invariant = 1; 170221214Sjkim return (1); 171221214Sjkim} 172221214Sjkim 173220577Sjkimstatic void 174220577Sjkimtsc_freq_intel(void) 1751390Ssos{ 176220577Sjkim char brand[48]; 177220577Sjkim u_int regs[4]; 178220577Sjkim uint64_t freq; 179220577Sjkim char *p; 180220577Sjkim u_int i; 1811390Ssos 182220577Sjkim /* 183220577Sjkim * Intel Processor Identification and the CPUID Instruction 184220577Sjkim * Application Note 485. 185220577Sjkim * http://www.intel.com/assets/pdf/appnote/241618.pdf 186220577Sjkim */ 187220577Sjkim if (cpu_exthigh >= 0x80000004) { 188220577Sjkim p = brand; 189220577Sjkim for (i = 0x80000002; i < 0x80000005; i++) { 190220577Sjkim do_cpuid(i, regs); 191220577Sjkim memcpy(p, regs, sizeof(regs)); 192220577Sjkim p += sizeof(regs); 193220577Sjkim } 194220577Sjkim p = NULL; 195220577Sjkim for (i = 0; i < sizeof(brand) - 1; i++) 196220577Sjkim if (brand[i] == 'H' && brand[i + 1] == 'z') 197220577Sjkim p = brand + i; 198220577Sjkim if (p != NULL) { 199220577Sjkim p -= 5; 200220577Sjkim switch (p[4]) { 201220577Sjkim case 'M': 202220577Sjkim i = 1; 203220577Sjkim break; 204220577Sjkim case 'G': 205220577Sjkim i = 1000; 206220577Sjkim break; 207220577Sjkim case 'T': 208220577Sjkim i = 1000000; 209220577Sjkim break; 210220577Sjkim default: 211220577Sjkim return; 212220577Sjkim } 213220577Sjkim#define C2D(c) ((c) - '0') 214220577Sjkim if (p[1] == '.') { 215220577Sjkim freq = C2D(p[0]) * 1000; 216220577Sjkim freq += C2D(p[2]) * 100; 217220577Sjkim freq += C2D(p[3]) * 10; 218220577Sjkim freq *= i * 1000; 219220577Sjkim } else { 220220577Sjkim freq = C2D(p[0]) * 1000; 221220577Sjkim freq += C2D(p[1]) * 100; 222220577Sjkim freq += C2D(p[2]) * 10; 223220577Sjkim freq += C2D(p[3]); 224220577Sjkim freq *= i * 1000000; 225220577Sjkim } 226220577Sjkim#undef C2D 227220577Sjkim tsc_freq = freq; 228220577Sjkim } 229220577Sjkim } 230220577Sjkim} 23132054Sphk 232220577Sjkimstatic void 233220577Sjkimprobe_tsc_freq(void) 234220577Sjkim{ 235220579Sjkim u_int regs[4]; 236220577Sjkim uint64_t tsc1, tsc2; 23715508Sbde 238221214Sjkim if (cpu_high >= 6) { 239221214Sjkim do_cpuid(6, regs); 240221214Sjkim if ((regs[2] & CPUID_PERF_STAT) != 0) { 241221214Sjkim /* 242221214Sjkim * XXX Some emulators expose host CPUID without actual 243221214Sjkim * support for these MSRs. We must test whether they 244221214Sjkim * really work. 245221214Sjkim */ 246221214Sjkim wrmsr(MSR_MPERF, 0); 247221214Sjkim wrmsr(MSR_APERF, 0); 248221214Sjkim DELAY(10); 249221214Sjkim if (rdmsr(MSR_MPERF) > 0 && rdmsr(MSR_APERF) > 0) 250221214Sjkim tsc_perf_stat = 1; 251221214Sjkim } 252221214Sjkim } 253221214Sjkim 254221214Sjkim if (tsc_freq_vmware()) 255221214Sjkim return; 256221214Sjkim 257216272Sjkim switch (cpu_vendor_id) { 258216272Sjkim case CPU_VENDOR_AMD: 259219469Sjkim if ((amd_pminfo & AMDPM_TSC_INVARIANT) != 0 || 260219469Sjkim (vm_guest == VM_GUEST_NO && 261219469Sjkim CPUID_TO_FAMILY(cpu_id) >= 0x10)) 262216272Sjkim tsc_is_invariant = 1; 263216272Sjkim break; 264216272Sjkim case CPU_VENDOR_INTEL: 265219469Sjkim if ((amd_pminfo & AMDPM_TSC_INVARIANT) != 0 || 266219469Sjkim (vm_guest == VM_GUEST_NO && 267219469Sjkim ((CPUID_TO_FAMILY(cpu_id) == 0x6 && 268216272Sjkim CPUID_TO_MODEL(cpu_id) >= 0xe) || 269216272Sjkim (CPUID_TO_FAMILY(cpu_id) == 0xf && 270219469Sjkim CPUID_TO_MODEL(cpu_id) >= 0x3)))) 271216272Sjkim tsc_is_invariant = 1; 272216272Sjkim break; 273216272Sjkim case CPU_VENDOR_CENTAUR: 274219469Sjkim if (vm_guest == VM_GUEST_NO && 275219469Sjkim CPUID_TO_FAMILY(cpu_id) == 0x6 && 276216272Sjkim CPUID_TO_MODEL(cpu_id) >= 0xf && 277216272Sjkim (rdmsr(0x1203) & 0x100000000ULL) == 0) 278216272Sjkim tsc_is_invariant = 1; 279216272Sjkim break; 280216272Sjkim } 281216272Sjkim 282220577Sjkim if (tsc_skip_calibration) { 283220577Sjkim if (cpu_vendor_id == CPU_VENDOR_INTEL) 284220577Sjkim tsc_freq_intel(); 285220577Sjkim return; 286220577Sjkim } 287220577Sjkim 288220577Sjkim if (bootverbose) 289220577Sjkim printf("Calibrating TSC clock ... "); 290220577Sjkim tsc1 = rdtsc(); 291220577Sjkim DELAY(1000000); 292220577Sjkim tsc2 = rdtsc(); 293220577Sjkim tsc_freq = tsc2 - tsc1; 294220577Sjkim if (bootverbose) 295220577Sjkim printf("TSC clock: %ju Hz\n", (intmax_t)tsc_freq); 296220577Sjkim} 297220577Sjkim 298220577Sjkimvoid 299220577Sjkiminit_TSC(void) 300220577Sjkim{ 301220577Sjkim 302220577Sjkim if ((cpu_feature & CPUID_TSC) == 0 || tsc_disabled) 303220577Sjkim return; 304220577Sjkim 305220577Sjkim probe_tsc_freq(); 306220577Sjkim 307167905Snjl /* 308216274Sjkim * Inform CPU accounting about our boot-time clock rate. This will 309216274Sjkim * be updated if someone loads a cpufreq driver after boot that 310216274Sjkim * discovers a new max frequency. 311167905Snjl */ 312220577Sjkim if (tsc_freq != 0) 313221178Sjkim set_cputicker(rdtsc, tsc_freq, !tsc_is_invariant); 314167905Snjl 315216274Sjkim if (tsc_is_invariant) 316216274Sjkim return; 317216274Sjkim 318167905Snjl /* Register to find out about changes in CPU frequency. */ 319184108Sjkim tsc_pre_tag = EVENTHANDLER_REGISTER(cpufreq_pre_change, 320184108Sjkim tsc_freq_changing, NULL, EVENTHANDLER_PRI_FIRST); 321167905Snjl tsc_post_tag = EVENTHANDLER_REGISTER(cpufreq_post_change, 322167905Snjl tsc_freq_changed, NULL, EVENTHANDLER_PRI_FIRST); 323167905Snjl tsc_levels_tag = EVENTHANDLER_REGISTER(cpufreq_levels_changed, 324167905Snjl tsc_levels_changed, NULL, EVENTHANDLER_PRI_ANY); 325118550Sphk} 32634617Sphk 327221703Sjkim#ifdef SMP 328221703Sjkim 329221703Sjkim#define TSC_READ(x) \ 330221703Sjkimstatic void \ 331221703Sjkimtsc_read_##x(void *arg) \ 332221703Sjkim{ \ 333221703Sjkim uint32_t *tsc = arg; \ 334221703Sjkim u_int cpu = PCPU_GET(cpuid); \ 335221703Sjkim \ 336221703Sjkim tsc[cpu * 3 + x] = rdtsc32(); \ 337221703Sjkim} 338221703SjkimTSC_READ(0) 339221703SjkimTSC_READ(1) 340221703SjkimTSC_READ(2) 341221703Sjkim#undef TSC_READ 342221703Sjkim 343221703Sjkim#define N 1000 344221703Sjkim 345221703Sjkimstatic void 346221703Sjkimcomp_smp_tsc(void *arg) 347221703Sjkim{ 348221703Sjkim uint32_t *tsc; 349221703Sjkim int32_t d1, d2; 350221703Sjkim u_int cpu = PCPU_GET(cpuid); 351221703Sjkim u_int i, j, size; 352221703Sjkim 353221703Sjkim size = (mp_maxid + 1) * 3; 354221703Sjkim for (i = 0, tsc = arg; i < N; i++, tsc += size) 355221703Sjkim CPU_FOREACH(j) { 356221703Sjkim if (j == cpu) 357221703Sjkim continue; 358221703Sjkim d1 = tsc[cpu * 3 + 1] - tsc[j * 3]; 359221703Sjkim d2 = tsc[cpu * 3 + 2] - tsc[j * 3 + 1]; 360221703Sjkim if (d1 <= 0 || d2 <= 0) { 361221703Sjkim smp_tsc = 0; 362221703Sjkim return; 363221703Sjkim } 364221703Sjkim } 365221703Sjkim} 366221703Sjkim 367221703Sjkimstatic int 368221703Sjkimtest_smp_tsc(void) 369221703Sjkim{ 370221703Sjkim uint32_t *data, *tsc; 371221703Sjkim u_int i, size; 372221703Sjkim 373221703Sjkim if (!smp_tsc && !tsc_is_invariant) 374221703Sjkim return (-100); 375221703Sjkim size = (mp_maxid + 1) * 3; 376221703Sjkim data = malloc(sizeof(*data) * size * N, M_TEMP, M_WAITOK); 377221703Sjkim for (i = 0, tsc = data; i < N; i++, tsc += size) 378221703Sjkim smp_rendezvous(tsc_read_0, tsc_read_1, tsc_read_2, tsc); 379221703Sjkim smp_tsc = 1; /* XXX */ 380221703Sjkim smp_rendezvous(smp_no_rendevous_barrier, comp_smp_tsc, 381221703Sjkim smp_no_rendevous_barrier, data); 382221703Sjkim free(data, M_TEMP); 383221703Sjkim if (bootverbose) 384221703Sjkim printf("SMP: %sed TSC synchronization test\n", 385221703Sjkim smp_tsc ? "pass" : "fail"); 386222869Sjkim if (smp_tsc && tsc_is_invariant) { 387222869Sjkim switch (cpu_vendor_id) { 388222869Sjkim case CPU_VENDOR_AMD: 389222869Sjkim /* 390222869Sjkim * Starting with Family 15h processors, TSC clock 391222869Sjkim * source is in the north bridge. Check whether 392222869Sjkim * we have a single-socket/multi-core platform. 393222869Sjkim * XXX Need more work for complex cases. 394222869Sjkim */ 395222869Sjkim if (CPUID_TO_FAMILY(cpu_id) < 0x15 || 396222869Sjkim (amd_feature2 & AMDID2_CMP) == 0 || 397222869Sjkim smp_cpus > (cpu_procinfo2 & AMDID_CMP_CORES) + 1) 398222869Sjkim break; 399222869Sjkim return (1000); 400222869Sjkim case CPU_VENDOR_INTEL: 401222869Sjkim /* 402222869Sjkim * XXX Assume Intel platforms have synchronized TSCs. 403222869Sjkim */ 404222869Sjkim return (1000); 405222869Sjkim } 406222869Sjkim return (800); 407222869Sjkim } 408222869Sjkim return (-100); 409221703Sjkim} 410221703Sjkim 411221703Sjkim#undef N 412221703Sjkim 413221703Sjkim#endif /* SMP */ 414221703Sjkim 415221703Sjkimstatic void 416118550Sphkinit_TSC_tc(void) 417118550Sphk{ 418222866Sjkim uint64_t max_freq; 419222866Sjkim int shift; 420209103Smav 421219673Sjkim if ((cpu_feature & CPUID_TSC) == 0 || tsc_disabled) 422209103Smav return; 423209103Smav 42434617Sphk /* 425222866Sjkim * Limit timecounter frequency to fit in an int and prevent it from 426222866Sjkim * overflowing too fast. 427222866Sjkim */ 428222866Sjkim max_freq = UINT_MAX; 429222866Sjkim 430222866Sjkim /* 431160964Syar * We can not use the TSC if we support APM. Precise timekeeping 43249186Smsmith * on an APM'ed machine is at best a fools pursuit, since 43334617Sphk * any and all of the time spent in various SMM code can't 43434617Sphk * be reliably accounted for. Reading the RTC is your only 435160964Syar * source of reliable time info. The i8254 loses too, of course, 43634617Sphk * but we need to have some kind of time... 43749186Smsmith * We don't know at this point whether APM is going to be used 43849186Smsmith * or not, nor when it might be activated. Play it safe. 43934617Sphk */ 44085835Siwasaki if (power_pm_get_type() == POWER_PM_TYPE_APM) { 441118987Sphk tsc_timecounter.tc_quality = -1000; 44285835Siwasaki if (bootverbose) 443110370Sphk printf("TSC timecounter disabled: APM enabled.\n"); 444221703Sjkim goto init; 44564031Sphk } 44634617Sphk 447118987Sphk#ifdef SMP 448118987Sphk /* 449221703Sjkim * We can not use the TSC in SMP mode unless the TSCs on all CPUs are 450221703Sjkim * synchronized. If the user is sure that the system has synchronized 451221703Sjkim * TSCs, set kern.timecounter.smp_tsc tunable to a non-zero value. 452222866Sjkim * We also limit the frequency even lower to avoid "temporal anomalies" 453222866Sjkim * as much as possible. 454118987Sphk */ 455222866Sjkim if (smp_cpus > 1) { 456221703Sjkim tsc_timecounter.tc_quality = test_smp_tsc(); 457222866Sjkim max_freq >>= 8; 458222869Sjkim } else 459118987Sphk#endif 460222869Sjkim if (tsc_is_invariant) 461222869Sjkim tsc_timecounter.tc_quality = 1000; 462222869Sjkim 463221703Sjkiminit: 464222866Sjkim for (shift = 0; shift < 32 && (tsc_freq >> shift) > max_freq; shift++) 465222866Sjkim ; 466222866Sjkim if (shift > 0) { 467222866Sjkim tsc_timecounter.tc_get_timecount = tsc_get_timecount_lowres; 468222866Sjkim tsc_timecounter.tc_name = "TSC-low"; 469222866Sjkim if (bootverbose) 470222866Sjkim printf("TSC timecounter discards lower %d bit(s).\n", 471222866Sjkim shift); 472222866Sjkim } 473219461Sjkim if (tsc_freq != 0) { 474222866Sjkim tsc_timecounter.tc_frequency = tsc_freq >> shift; 475222866Sjkim tsc_timecounter.tc_priv = (void *)(intptr_t)shift; 47658377Sphk tc_init(&tsc_timecounter); 47733690Sphk } 4784Srgrimes} 479221703SjkimSYSINIT(tsc_tc, SI_SUB_SMP, SI_ORDER_ANY, init_TSC_tc, NULL); 4804Srgrimes 481167905Snjl/* 482167905Snjl * When cpufreq levels change, find out about the (new) max frequency. We 483167905Snjl * use this to update CPU accounting in case it got a lower estimate at boot. 484167905Snjl */ 485167905Snjlstatic void 486167905Snjltsc_levels_changed(void *arg, int unit) 487167905Snjl{ 488167905Snjl device_t cf_dev; 489167905Snjl struct cf_level *levels; 490167905Snjl int count, error; 491167905Snjl uint64_t max_freq; 492167905Snjl 493167905Snjl /* Only use values from the first CPU, assuming all are equal. */ 494167905Snjl if (unit != 0) 495167905Snjl return; 496167905Snjl 497167905Snjl /* Find the appropriate cpufreq device instance. */ 498167905Snjl cf_dev = devclass_get_device(devclass_find("cpufreq"), unit); 499167905Snjl if (cf_dev == NULL) { 500167905Snjl printf("tsc_levels_changed() called but no cpufreq device?\n"); 501167905Snjl return; 502167905Snjl } 503167905Snjl 504167905Snjl /* Get settings from the device and find the max frequency. */ 505167905Snjl count = 64; 506167905Snjl levels = malloc(count * sizeof(*levels), M_TEMP, M_NOWAIT); 507167905Snjl if (levels == NULL) 508167905Snjl return; 509167905Snjl error = CPUFREQ_LEVELS(cf_dev, levels, &count); 510167905Snjl if (error == 0 && count != 0) { 511167905Snjl max_freq = (uint64_t)levels[0].total_set.freq * 1000000; 512167905Snjl set_cputicker(rdtsc, max_freq, 1); 513167905Snjl } else 514167905Snjl printf("tsc_levels_changed: no max freq found\n"); 515167905Snjl free(levels, M_TEMP); 516167905Snjl} 517167905Snjl 518167905Snjl/* 519167905Snjl * If the TSC timecounter is in use, veto the pending change. It may be 520167905Snjl * possible in the future to handle a dynamically-changing timecounter rate. 521167905Snjl */ 522167905Snjlstatic void 523167905Snjltsc_freq_changing(void *arg, const struct cf_level *level, int *status) 524167905Snjl{ 525167905Snjl 526216274Sjkim if (*status != 0 || timecounter != &tsc_timecounter) 527167905Snjl return; 528167905Snjl 529167905Snjl printf("timecounter TSC must not be in use when " 530184102Sjkim "changing frequencies; change denied\n"); 531167905Snjl *status = EBUSY; 532167905Snjl} 533167905Snjl 534167905Snjl/* Update TSC freq with the value indicated by the caller. */ 535167905Snjlstatic void 536167905Snjltsc_freq_changed(void *arg, const struct cf_level *level, int status) 537167905Snjl{ 538220433Sjkim uint64_t freq; 539216276Sjkim 540216276Sjkim /* If there was an error during the transition, don't do anything. */ 541219473Sjkim if (tsc_disabled || status != 0) 542167905Snjl return; 543167905Snjl 544167905Snjl /* Total setting for this level gives the new frequency in MHz. */ 545220433Sjkim freq = (uint64_t)level->total_set.freq * 1000000; 546220433Sjkim atomic_store_rel_64(&tsc_freq, freq); 547222866Sjkim tsc_timecounter.tc_frequency = 548222866Sjkim freq >> (int)(intptr_t)tsc_timecounter.tc_priv; 549167905Snjl} 550167905Snjl 55115508Sbdestatic int 55262573Sphksysctl_machdep_tsc_freq(SYSCTL_HANDLER_ARGS) 55315508Sbde{ 55415508Sbde int error; 555110039Sphk uint64_t freq; 55615508Sbde 557220433Sjkim freq = atomic_load_acq_64(&tsc_freq); 558220433Sjkim if (freq == 0) 55915508Sbde return (EOPNOTSUPP); 560217616Smdf error = sysctl_handle_64(oidp, &freq, 0, req); 561219700Sjkim if (error == 0 && req->newptr != NULL) { 562220433Sjkim atomic_store_rel_64(&tsc_freq, freq); 563222866Sjkim tsc_timecounter.tc_frequency = 564222866Sjkim freq >> (int)(intptr_t)tsc_timecounter.tc_priv; 565219700Sjkim } 56615508Sbde return (error); 56715508Sbde} 56815508Sbde 569217616SmdfSYSCTL_PROC(_machdep, OID_AUTO, tsc_freq, CTLTYPE_U64 | CTLFLAG_RW, 570220613Sjkim 0, 0, sysctl_machdep_tsc_freq, "QU", "Time Stamp Counter frequency"); 57133690Sphk 572220632Sjkimstatic u_int 573222866Sjkimtsc_get_timecount(struct timecounter *tc __unused) 57433690Sphk{ 575220632Sjkim 576220632Sjkim return (rdtsc32()); 57733690Sphk} 578222866Sjkim 579222866Sjkimstatic u_int 580222866Sjkimtsc_get_timecount_lowres(struct timecounter *tc) 581222866Sjkim{ 582222866Sjkim 583222866Sjkim return (rdtsc() >> (int)(intptr_t)tc->tc_priv); 584222866Sjkim} 585