Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Apr 2020 22:28:51 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r359997 - head/sys/x86/x86
Message-ID:  <202004152228.03FMSpEA071568@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Apr 15 22:28:51 2020
New Revision: 359997
URL: https://svnweb.freebsd.org/changeset/base/359997

Log:
  Improve TSC calibration logic.
  
  Stop attempting to use FADT legacy hardware flag, it is almost always
  a lie.
  
  Instead, unless user explicitly disabled the calibration, calibrate
  against 8254 ISA clock.  Then, obtain the rough value of the expected
  TSC frequency from CPUID leafs 0x15/0x16 or even from the CPU
  marketing name string.  If calibration results look unbelievably bogus
  comparing with CPUID leafs report, use CPUID one.
  
  Intel does not recommend to use CPUID leaf 0x16 for the value of the
  system time frequency, indeed the error there might be up to 1% which
  e.g. makes ntpd give up.  If ISA clock is present, we win, if not, we
  get some frequency that allows the machine to boot without enormous
  delay.
  
  Next improvement would be to use HPET for re-calibration if we decided
  that ISA clock gives bogus results, after HPETs are enumerated. This
  is a much bigger change since we probably would need to re-evaluate
  some constants depending on TSC frequency.
  
  Reviewed by:	emaste, jhb, scottl
  Tested by:	scottl
  Sponsored by:	The FreeBSD Foundation
  MFC after:	2 weeks
  Differential revision:	https://reviews.freebsd.org/D24426

Modified:
  head/sys/x86/x86/tsc.c

Modified: head/sys/x86/x86/tsc.c
==============================================================================
--- head/sys/x86/x86/tsc.c	Wed Apr 15 22:27:24 2020	(r359996)
+++ head/sys/x86/x86/tsc.c	Wed Apr 15 22:28:51 2020	(r359997)
@@ -83,8 +83,8 @@ SYSCTL_INT(_machdep, OID_AUTO, disable_tsc, CTLFLAG_RD
     "Disable x86 Time Stamp Counter");
 
 static int	tsc_skip_calibration;
-SYSCTL_INT(_machdep, OID_AUTO, disable_tsc_calibration, CTLFLAG_RDTUN |
-    CTLFLAG_NOFETCH, &tsc_skip_calibration, 0,
+SYSCTL_INT(_machdep, OID_AUTO, disable_tsc_calibration, CTLFLAG_RDTUN,
+    &tsc_skip_calibration, 0,
     "Disable TSC frequency calibration");
 
 static void tsc_freq_changed(void *arg, const struct cf_level *level,
@@ -230,7 +230,6 @@ probe_tsc_freq(void)
 {
 	uint64_t tmp_freq, tsc1, tsc2;
 	int no_cpuid_override;
-	uint16_t bootflags;
 
 	if (cpu_power_ecx & CPUID_PERF_STAT) {
 		/*
@@ -287,30 +286,13 @@ probe_tsc_freq(void)
 		break;
 	}
 
-	if (!TUNABLE_INT_FETCH("machdep.disable_tsc_calibration",
-	    &tsc_skip_calibration)) {
-		/*
-		 * User did not give the order about calibration.
-		 * If he did, we do not try to guess.
-		 *
-		 * Otherwise, if ACPI FADT reports that the platform
-		 * is legacy-free and CPUID provides TSC frequency,
-		 * use it.  The calibration could fail anyway since
-		 * ISA timer can be absent or power gated.
-		 */
-		if (acpi_get_fadt_bootflags(&bootflags) &&
-		    (bootflags & ACPI_FADT_LEGACY_DEVICES) == 0 &&
-		    tsc_freq_cpuid(&tmp_freq)) {
-			printf("Skipping TSC calibration since no legacy "
-			    "devices reported by FADT and CPUID works\n");
-			tsc_skip_calibration = 1;
-		}
-	}
 	if (tsc_skip_calibration) {
 		if (tsc_freq_cpuid(&tmp_freq))
 			tsc_freq = tmp_freq;
 		else if (cpu_vendor_id == CPU_VENDOR_INTEL)
 			tsc_freq_intel();
+		if (tsc_freq == 0)
+			tsc_disabled = 1;
 	} else {
 		if (bootverbose)
 			printf("Calibrating TSC clock ... ");
@@ -324,8 +306,9 @@ probe_tsc_freq(void)
 		 * the frequency reported by CPUID 0x15/0x16 leafs
 		 * differ significantly, this probably means that
 		 * calibration is bogus.  It happens on machines
-		 * without 8254 timer and with BIOS not properly
-		 * reporting it in FADT boot flags.
+		 * without 8254 timer.  The BIOS rarely properly
+		 * reports it in FADT boot flags, so just compare the
+		 * frequencies directly.
 		 */
 		if (tsc_freq_cpuid(&tmp_freq) && qabs(tsc_freq - tmp_freq) >
 		    uqmin(tsc_freq, tmp_freq)) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202004152228.03FMSpEA071568>