summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjkim <jkim@FreeBSD.org>2011-06-08 20:08:06 +0000
committerjkim <jkim@FreeBSD.org>2011-06-08 20:08:06 +0000
commit9f1a70eb734d9fedbce2586838c16de49f60da8c (patch)
treeaf1d79c0752baa83dbe227268ad4b419923528f2 /sys
parentfaed140c1e76bffac65f7208f4089af46dc84cc6 (diff)
downloadFreeBSD-src-9f1a70eb734d9fedbce2586838c16de49f60da8c.zip
FreeBSD-src-9f1a70eb734d9fedbce2586838c16de49f60da8c.tar.gz
Increase quality of TSC (or TSC-low) timecounter to 1000 if it is P-state
invariant. For SMP case (TSC-low), it also has to pass SMP synchronization test and the CPU vendor/model has to be white-listed explicitly. Currently, all Intel CPUs and single-socket AMD Family 15h processors are listed here. Discussed with: hackers
Diffstat (limited to 'sys')
-rw-r--r--sys/x86/x86/tsc.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/sys/x86/x86/tsc.c b/sys/x86/x86/tsc.c
index bd38703..c21906e 100644
--- a/sys/x86/x86/tsc.c
+++ b/sys/x86/x86/tsc.c
@@ -383,7 +383,29 @@ test_smp_tsc(void)
if (bootverbose)
printf("SMP: %sed TSC synchronization test\n",
smp_tsc ? "pass" : "fail");
- return (smp_tsc ? 800 : -100);
+ if (smp_tsc && tsc_is_invariant) {
+ switch (cpu_vendor_id) {
+ case CPU_VENDOR_AMD:
+ /*
+ * Starting with Family 15h processors, TSC clock
+ * source is in the north bridge. Check whether
+ * we have a single-socket/multi-core platform.
+ * XXX Need more work for complex cases.
+ */
+ if (CPUID_TO_FAMILY(cpu_id) < 0x15 ||
+ (amd_feature2 & AMDID2_CMP) == 0 ||
+ smp_cpus > (cpu_procinfo2 & AMDID_CMP_CORES) + 1)
+ break;
+ return (1000);
+ case CPU_VENDOR_INTEL:
+ /*
+ * XXX Assume Intel platforms have synchronized TSCs.
+ */
+ return (1000);
+ }
+ return (800);
+ }
+ return (-100);
}
#undef N
@@ -433,8 +455,11 @@ init_TSC_tc(void)
if (smp_cpus > 1) {
tsc_timecounter.tc_quality = test_smp_tsc();
max_freq >>= 8;
- }
+ } else
#endif
+ if (tsc_is_invariant)
+ tsc_timecounter.tc_quality = 1000;
+
init:
for (shift = 0; shift < 32 && (tsc_freq >> shift) > max_freq; shift++)
;
OpenPOWER on IntegriCloud