svn commit: r335657 - in stable/11/sys: amd64/include dev/acpica i386/include x86/x86
Andriy Gapon
avg at FreeBSD.org
Tue Jun 26 08:36:00 UTC 2018
Author: avg
Date: Tue Jun 26 08:35:58 2018
New Revision: 335657
URL: https://svnweb.freebsd.org/changeset/base/335657
Log:
MFC r334204,r334338: re-synchronize TSC-s on SMP systems after resume
Modified:
stable/11/sys/amd64/include/clock.h
stable/11/sys/dev/acpica/acpi.c
stable/11/sys/i386/include/clock.h
stable/11/sys/x86/x86/tsc.c
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sys/amd64/include/clock.h
==============================================================================
--- stable/11/sys/amd64/include/clock.h Tue Jun 26 08:31:08 2018 (r335656)
+++ stable/11/sys/amd64/include/clock.h Tue Jun 26 08:35:58 2018 (r335657)
@@ -34,6 +34,7 @@ void clock_init(void);
void startrtclock(void);
void init_TSC(void);
+void resume_TSC(void);
#define HAS_TIMER_SPKR 1
int timer_spkr_acquire(void);
Modified: stable/11/sys/dev/acpica/acpi.c
==============================================================================
--- stable/11/sys/dev/acpica/acpi.c Tue Jun 26 08:31:08 2018 (r335656)
+++ stable/11/sys/dev/acpica/acpi.c Tue Jun 26 08:35:58 2018 (r335657)
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <sys/timetc.h>
#if defined(__i386__) || defined(__amd64__)
+#include <machine/clock.h>
#include <machine/pci_cfgreg.h>
#endif
#include <machine/resource.h>
@@ -2991,6 +2992,10 @@ backout:
if (slp_state >= ACPI_SS_SLP_PREP)
AcpiLeaveSleepState(state);
if (slp_state >= ACPI_SS_SLEPT) {
+#if defined(__i386__) || defined(__amd64__)
+ /* NB: we are still using ACPI timecounter at this point. */
+ resume_TSC();
+#endif
acpi_resync_clock(sc);
acpi_enable_fixed_events(sc);
}
Modified: stable/11/sys/i386/include/clock.h
==============================================================================
--- stable/11/sys/i386/include/clock.h Tue Jun 26 08:31:08 2018 (r335656)
+++ stable/11/sys/i386/include/clock.h Tue Jun 26 08:35:58 2018 (r335657)
@@ -32,6 +32,7 @@ void clock_init(void);
void startrtclock(void);
void timer_restore(void);
void init_TSC(void);
+void resume_TSC(void);
#define HAS_TIMER_SPKR 1
int timer_spkr_acquire(void);
Modified: stable/11/sys/x86/x86/tsc.c
==============================================================================
--- stable/11/sys/x86/x86/tsc.c Tue Jun 26 08:31:08 2018 (r335656)
+++ stable/11/sys/x86/x86/tsc.c Tue Jun 26 08:35:58 2018 (r335657)
@@ -450,7 +450,7 @@ adj_smp_tsc(void *arg)
}
static int
-test_tsc(void)
+test_tsc(int adj_max_count)
{
uint64_t *data, *tsc;
u_int i, size, adj;
@@ -466,7 +466,7 @@ retry:
smp_tsc = 1; /* XXX */
smp_rendezvous(smp_no_rendezvous_barrier, comp_smp_tsc,
smp_no_rendezvous_barrier, data);
- if (!smp_tsc && adj < smp_tsc_adjust) {
+ if (!smp_tsc && adj < adj_max_count) {
adj++;
smp_rendezvous(smp_no_rendezvous_barrier, adj_smp_tsc,
smp_no_rendezvous_barrier, data);
@@ -504,19 +504,6 @@ retry:
#undef N
-#else
-
-/*
- * The function is not called, it is provided to avoid linking failure
- * on uniprocessor kernel.
- */
-static int
-test_tsc(void)
-{
-
- return (0);
-}
-
#endif /* SMP */
static void
@@ -577,9 +564,12 @@ init_TSC_tc(void)
* non-zero value. The TSC seems unreliable in virtualized SMP
* environments, so it is set to a negative quality in those cases.
*/
+#ifdef SMP
if (mp_ncpus > 1)
- tsc_timecounter.tc_quality = test_tsc();
- else if (tsc_is_invariant)
+ tsc_timecounter.tc_quality = test_tsc(smp_tsc_adjust);
+ else
+#endif /* SMP */
+ if (tsc_is_invariant)
tsc_timecounter.tc_quality = 1000;
max_freq >>= tsc_shift;
@@ -613,6 +603,32 @@ init:
}
}
SYSINIT(tsc_tc, SI_SUB_SMP, SI_ORDER_ANY, init_TSC_tc, NULL);
+
+void
+resume_TSC(void)
+{
+#ifdef SMP
+ int quality;
+
+ /* If TSC was not good on boot, it is unlikely to become good now. */
+ if (tsc_timecounter.tc_quality < 0)
+ return;
+ /* Nothing to do with UP. */
+ if (mp_ncpus < 2)
+ return;
+
+ /*
+ * If TSC was good, a single synchronization should be enough,
+ * but honour smp_tsc_adjust if it's set.
+ */
+ quality = test_tsc(MAX(smp_tsc_adjust, 1));
+ if (quality != tsc_timecounter.tc_quality) {
+ printf("TSC timecounter quality changed: %d -> %d\n",
+ tsc_timecounter.tc_quality, quality);
+ tsc_timecounter.tc_quality = quality;
+ }
+#endif /* SMP */
+}
/*
* When cpufreq levels change, find out about the (new) max frequency. We
More information about the svn-src-stable-11
mailing list