Date: Wed, 15 Apr 2020 22:28:51 +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: r359997 - head/sys/x86/x86 Message-ID: <202004152228.03FMSpEA071568@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Wed Apr 15 22:28:51 2020 New Revision: 359997 URL: https://svnweb.freebsd.org/changeset/base/359997 Log: Improve TSC calibration logic. Stop attempting to use FADT legacy hardware flag, it is almost always a lie. Instead, unless user explicitly disabled the calibration, calibrate against 8254 ISA clock. Then, obtain the rough value of the expected TSC frequency from CPUID leafs 0x15/0x16 or even from the CPU marketing name string. If calibration results look unbelievably bogus comparing with CPUID leafs report, use CPUID one. Intel does not recommend to use CPUID leaf 0x16 for the value of the system time frequency, indeed the error there might be up to 1% which e.g. makes ntpd give up. If ISA clock is present, we win, if not, we get some frequency that allows the machine to boot without enormous delay. Next improvement would be to use HPET for re-calibration if we decided that ISA clock gives bogus results, after HPETs are enumerated. This is a much bigger change since we probably would need to re-evaluate some constants depending on TSC frequency. Reviewed by: emaste, jhb, scottl Tested by: scottl Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D24426 Modified: head/sys/x86/x86/tsc.c Modified: head/sys/x86/x86/tsc.c ============================================================================== --- head/sys/x86/x86/tsc.c Wed Apr 15 22:27:24 2020 (r359996) +++ head/sys/x86/x86/tsc.c Wed Apr 15 22:28:51 2020 (r359997) @@ -83,8 +83,8 @@ SYSCTL_INT(_machdep, OID_AUTO, disable_tsc, CTLFLAG_RD "Disable x86 Time Stamp Counter"); static int tsc_skip_calibration; -SYSCTL_INT(_machdep, OID_AUTO, disable_tsc_calibration, CTLFLAG_RDTUN | - CTLFLAG_NOFETCH, &tsc_skip_calibration, 0, +SYSCTL_INT(_machdep, OID_AUTO, disable_tsc_calibration, CTLFLAG_RDTUN, + &tsc_skip_calibration, 0, "Disable TSC frequency calibration"); static void tsc_freq_changed(void *arg, const struct cf_level *level, @@ -230,7 +230,6 @@ probe_tsc_freq(void) { uint64_t tmp_freq, tsc1, tsc2; int no_cpuid_override; - uint16_t bootflags; if (cpu_power_ecx & CPUID_PERF_STAT) { /* @@ -287,30 +286,13 @@ probe_tsc_freq(void) break; } - if (!TUNABLE_INT_FETCH("machdep.disable_tsc_calibration", - &tsc_skip_calibration)) { - /* - * User did not give the order about calibration. - * If he did, we do not try to guess. - * - * Otherwise, if ACPI FADT reports that the platform - * is legacy-free and CPUID provides TSC frequency, - * use it. The calibration could fail anyway since - * ISA timer can be absent or power gated. - */ - if (acpi_get_fadt_bootflags(&bootflags) && - (bootflags & ACPI_FADT_LEGACY_DEVICES) == 0 && - tsc_freq_cpuid(&tmp_freq)) { - printf("Skipping TSC calibration since no legacy " - "devices reported by FADT and CPUID works\n"); - tsc_skip_calibration = 1; - } - } if (tsc_skip_calibration) { if (tsc_freq_cpuid(&tmp_freq)) tsc_freq = tmp_freq; else if (cpu_vendor_id == CPU_VENDOR_INTEL) tsc_freq_intel(); + if (tsc_freq == 0) + tsc_disabled = 1; } else { if (bootverbose) printf("Calibrating TSC clock ... "); @@ -324,8 +306,9 @@ probe_tsc_freq(void) * the frequency reported by CPUID 0x15/0x16 leafs * differ significantly, this probably means that * calibration is bogus. It happens on machines - * without 8254 timer and with BIOS not properly - * reporting it in FADT boot flags. + * without 8254 timer. The BIOS rarely properly + * reports it in FADT boot flags, so just compare the + * frequencies directly. */ if (tsc_freq_cpuid(&tmp_freq) && qabs(tsc_freq - tmp_freq) > uqmin(tsc_freq, tmp_freq)) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202004152228.03FMSpEA071568>