svn commit: r353007 - stable/11/sys/x86/x86

Konstantin Belousov kib at FreeBSD.org
Wed Oct 2 13:46:41 UTC 2019


Author: kib
Date: Wed Oct  2 13:46:40 2019
New Revision: 353007
URL: https://svnweb.freebsd.org/changeset/base/353007

Log:
  MFC r352684:
  x86: Fall back to leaf 0x16 if TSC frequency is obtained by CPUID and
  leaf 0x15 is not functional.

Modified:
  stable/11/sys/x86/x86/tsc.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/x86/x86/tsc.c
==============================================================================
--- stable/11/sys/x86/x86/tsc.c	Wed Oct  2 13:43:24 2019	(r353006)
+++ stable/11/sys/x86/x86/tsc.c	Wed Oct  2 13:46:40 2019	(r353007)
@@ -130,7 +130,11 @@ tsc_freq_vmware(void)
 
 /*
  * Calculate TSC frequency using information from the CPUID leaf 0x15
- * 'Time Stamp Counter and Nominal Core Crystal Clock'.  It should be
+ * 'Time Stamp Counter and Nominal Core Crystal Clock'.  If leaf 0x15
+ * is not functional, as it is on Skylake/Kabylake, try 0x16 'Processor
+ * Frequency Information'.  Leaf 0x16 is described in the SDM as
+ * informational only, but if 0x15 did not work, and TSC calibration
+ * is disabled, it is the best we can get at all.  It should still be
  * an improvement over the parsing of the CPU model name in
  * tsc_freq_intel(), when available.
  */
@@ -142,10 +146,20 @@ tsc_freq_cpuid(void)
 	if (cpu_high < 0x15)
 		return (false);
 	do_cpuid(0x15, regs);
-	if (regs[0] == 0 || regs[1] == 0 || regs[2] == 0)
+	if (regs[0] != 0 && regs[1] != 0 && regs[2] != 0) {
+		tsc_freq = (uint64_t)regs[2] * regs[1] / regs[0];
+		return (true);
+	}
+
+	if (cpu_high < 0x16)
 		return (false);
-	tsc_freq = (uint64_t)regs[2] * regs[1] / regs[0];
-	return (true);
+	do_cpuid(0x16, regs);
+	if (regs[0] != 0) {
+		tsc_freq = (uint64_t)regs[0] * 1000000;
+		return (true);
+	}
+
+	return (false);
 }
 
 static void


More information about the svn-src-all mailing list