Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Sep 2019 13:36:56 +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: r352684 - head/sys/x86/x86
Message-ID:  <201909251336.x8PDauVJ022462@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Sep 25 13:36:56 2019
New Revision: 352684
URL: https://svnweb.freebsd.org/changeset/base/352684

Log:
  x86: Fall back to leaf 0x16 if TSC frequency is obtained by CPUID and
  leaf 0x15 is not functional.
  
  This should improve automatic TSC frequency determination on
  Skylake/Kabylake/... families, where 0x15 exists but does not provide
  all necessary information.  SDM contains relatively strong wording
  against such uses of 0x16, but Intel does not give us any other way to
  obtain the frequency. Linux did the same in the commit
  604dc9170f2435d27da5039a3efd757dceadc684.
  
  Based on submission by:	Neel Chauhan <neel@neelc.org>
  PR:	240475
  Reviewed by:	markj
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week
  Differential revision:	https://reviews.freebsd.org/D21777

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

Modified: head/sys/x86/x86/tsc.c
==============================================================================
--- head/sys/x86/x86/tsc.c	Wed Sep 25 13:29:56 2019	(r352683)
+++ head/sys/x86/x86/tsc.c	Wed Sep 25 13:36:56 2019	(r352684)
@@ -134,7 +134,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.
  */
@@ -146,10 +150,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?201909251336.x8PDauVJ022462>