Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 26 Jun 2018 08:35:58 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r335657 - in stable/11/sys: amd64/include dev/acpica i386/include x86/x86
Message-ID:  <201806260835.w5Q8Zw0j075948@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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



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