Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 2 Oct 2019 13:43:24 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r353006 - stable/12/sys/x86/x86
Message-ID:  <201910021343.x92DhODD060319@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Oct  2 13:43:24 2019
New Revision: 353006
URL: https://svnweb.freebsd.org/changeset/base/353006

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

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

Modified: stable/12/sys/x86/x86/tsc.c
==============================================================================
--- stable/12/sys/x86/x86/tsc.c	Wed Oct  2 13:36:54 2019	(r353005)
+++ stable/12/sys/x86/x86/tsc.c	Wed Oct  2 13:43:24 2019	(r353006)
@@ -133,7 +133,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.
  */
@@ -145,10 +149,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



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