Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Apr 2018 16:43:45 +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: r333002 - head/sys/x86/x86
Message-ID:  <201804251643.w3PGhjaw047839@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Apr 25 16:43:45 2018
New Revision: 333002
URL: https://svnweb.freebsd.org/changeset/base/333002

Log:
  Use CPUID leaf 0x15 to get TSC frequency when the calibration is
  disabled.
  
  Intel finally added this information, which allows us to not parse CPU
  identification string looking for the nominal frequency.  The leaf is
  present e.g. on Appolo Lake Atom CPUs.  It is only used if the TSC
  calibration is disabled by user.
  
  Also, report the TSC frequency in bootverbose mode always, regardless
  of the way it was obtained.
  
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week

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

Modified: head/sys/x86/x86/tsc.c
==============================================================================
--- head/sys/x86/x86/tsc.c	Wed Apr 25 16:28:51 2018	(r333001)
+++ head/sys/x86/x86/tsc.c	Wed Apr 25 16:43:45 2018	(r333002)
@@ -129,6 +129,26 @@ tsc_freq_vmware(void)
 	tsc_is_invariant = 1;
 }
 
+/*
+ * Calculate TSC frequency using information from the CPUID leaf 0x15
+ * 'Time Stamp Counter and Nominal Core Crystal Clock'.  It should be
+ * an improvement over the parsing of the CPU model name in
+ * tsc_freq_intel(), when available.
+ */
+static bool
+tsc_freq_cpuid(void)
+{
+	u_int regs[4];
+
+	if (cpu_high < 0x15)
+		return (false);
+	do_cpuid(0x15, regs);
+	if (regs[0] == 0 || regs[1] == 0 || regs[2] == 0)
+		return (false);
+	tsc_freq = (uint64_t)regs[2] * regs[1] / regs[0];
+	return (true);
+}
+
 static void
 tsc_freq_intel(void)
 {
@@ -253,17 +273,18 @@ probe_tsc_freq(void)
 	}
 
 	if (tsc_skip_calibration) {
-		if (cpu_vendor_id == CPU_VENDOR_INTEL)
+		if (tsc_freq_cpuid())
+			;
+		else if (cpu_vendor_id == CPU_VENDOR_INTEL)
 			tsc_freq_intel();
-		return;
+	} else {
+		if (bootverbose)
+			printf("Calibrating TSC clock ... ");
+		tsc1 = rdtsc();
+		DELAY(1000000);
+		tsc2 = rdtsc();
+		tsc_freq = tsc2 - tsc1;
 	}
-
-	if (bootverbose)
-	        printf("Calibrating TSC clock ... ");
-	tsc1 = rdtsc();
-	DELAY(1000000);
-	tsc2 = rdtsc();
-	tsc_freq = tsc2 - tsc1;
 	if (bootverbose)
 		printf("TSC clock: %ju Hz\n", (intmax_t)tsc_freq);
 }



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