Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1525996

[patch 5/8] x86/tsc: Sync test only for the first cpu in a package

From Thomas Gleixner <tglx@linutronix.de>
Newsgroups linux.kernel
Subject [patch 5/8] x86/tsc: Sync test only for the first cpu in a package
Date 2016-11-19 15:00 +0100
Message-ID <sFelr-5AY-21@gated-at.bofh.it> (permalink)
References <sFelr-5AY-3@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


If the TSC_ADJUST MSR is available all CPUs in a package are forced to the
same value. So TSCs cannot be out of sync when the first CPU in the package
was in sync.

That allows to skip the sync test for all CPUs except the first starting
CPU in a package.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 arch/x86/include/asm/tsc.h |    4 ++--
 arch/x86/kernel/tsc_sync.c |   37 ++++++++++++++++++++++++++++---------
 2 files changed, 30 insertions(+), 11 deletions(-)

--- a/arch/x86/include/asm/tsc.h
+++ b/arch/x86/include/asm/tsc.h
@@ -49,10 +49,10 @@ extern void check_tsc_sync_source(int cp
 extern void check_tsc_sync_target(void);
 
 #ifdef CONFIG_X86_TSC
-extern void tsc_store_and_check_tsc_adjust(void);
+extern bool tsc_store_and_check_tsc_adjust(void);
 extern void tsc_verify_tsc_adjust(void);
 #else
-static inline void tsc_store_and_check_tsc_adjust(void) { }
+static inline bool tsc_store_and_check_tsc_adjust(void) { }
 static inline void tsc_verify_tsc_adjust(void) { }
 #endif
 
--- a/arch/x86/kernel/tsc_sync.c
+++ b/arch/x86/kernel/tsc_sync.c
@@ -47,18 +47,19 @@ void tsc_verify_tsc_adjust(void)
 }
 
 #ifndef CONFIG_SMP
-void __init tsc_store_and_check_tsc_adjust(void)
+bool __init tsc_store_and_check_tsc_adjust(void)
 {
 	struct tsc_adjust *ref, *cur = this_cpu_ptr(&tsc_adjust);
 	s64 bootval;
 
 	if (!boot_cpu_has(X86_FEATURE_TSC_ADJUST))
-		return;
+		return false;
 
 	rdmsrl(MSR_IA32_TSC_ADJUST, bootval);
 	cur->bootval = bootval;
 	cur->adjusted = bootval;
 	pr_info("TSC ADJUST: Boot CPU%u: %lld\n", cpu,  bootval);
+	return false;
 }
 
 #else /* !CONFIG_SMP */
@@ -66,14 +67,14 @@ void __init tsc_store_and_check_tsc_adju
 /*
  * Store and check the TSC ADJUST MSR if available
  */
-void tsc_store_and_check_tsc_adjust(void)
+bool tsc_store_and_check_tsc_adjust(void)
 {
 	struct tsc_adjust *ref, *cur = this_cpu_ptr(&tsc_adjust);
 	unsigned int refcpu, cpu = smp_processor_id();
 	s64 bootval;
 
 	if (!boot_cpu_has(X86_FEATURE_TSC_ADJUST))
-		return;
+		return false;
 
 	rdmsrl(MSR_IA32_TSC_ADJUST, bootval);
 	cur->bootval = bootval;
@@ -95,7 +96,7 @@ void tsc_store_and_check_tsc_adjust(void
 		 */
 		cur->adjusted = bootval;
 		pr_info_once("TSC ADJUST: Boot CPU%u: %lld\n", cpu,  bootval);
-		return;
+		return false;
 	}
 
 	ref = per_cpu_ptr(&tsc_adjust, refcpu);
@@ -119,6 +120,11 @@ void tsc_store_and_check_tsc_adjust(void
 		cur->adjusted = ref->adjusted;
 		wrmsrl(MSR_IA32_TSC_ADJUST, ref->adjusted);
 	}
+	/*
+	 * We have the TSCs forced to be in sync on this package. Skip sync
+	 * test:
+	 */
+	return true;
 }
 
 /*
@@ -127,6 +133,7 @@ void tsc_store_and_check_tsc_adjust(void
  */
 static atomic_t start_count;
 static atomic_t stop_count;
+static atomic_t skip_test;
 
 /*
  * We use a raw spinlock in this exceptional case, because
@@ -250,10 +257,16 @@ void check_tsc_sync_source(int cpu)
 	atomic_set(&stop_count, 0);
 
 	/*
-	 * Wait for the target to arrive:
+	 * Wait for the target to start or to skip the test:
 	 */
-	while (atomic_read(&start_count) != cpus-1)
+	while (atomic_read(&start_count) != cpus - 1) {
+		if (atomic_read(&skip_test) > 0) {
+			atomic_set(&skip_test, 0);
+			return;
+		}
 		cpu_relax();
+	}
+
 	/*
 	 * Trigger the target to continue into the measurement too:
 	 */
@@ -303,8 +316,14 @@ void check_tsc_sync_target(void)
 	if (unsynchronized_tsc() || tsc_clocksource_reliable)
 		return;
 
-	/* Store and check the TSC ADJUST MSR */
-	tsc_store_and_check_tsc_adjust();
+	/*
+	 * Store, verify and sanitize the TSC adjust register. If
+	 * successful skip the test.
+	 */
+	if (tsc_store_and_check_tsc_adjust()) {
+		atomic_inc(&skip_test);
+		return;
+	}
 
 	/*
 	 * Register this CPU's participation and wait for the

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[patch 0/8] x86/tsc: Utilize TSC_ADJUST MSR Thomas Gleixner <tglx@linutronix.de> - 2016-11-19 15:00 +0100
  [patch 4/8] x86/tsc: Verify TSC_ADJUST from idle Thomas Gleixner <tglx@linutronix.de> - 2016-11-19 15:00 +0100
    Re: [patch 4/8] x86/tsc: Verify TSC_ADJUST from idle Peter Zijlstra <peterz@infradead.org> - 2016-11-20 14:20 +0100
      Re: [patch 4/8] x86/tsc: Verify TSC_ADJUST from idle Thomas Gleixner <tglx@linutronix.de> - 2016-11-21 09:20 +0100
        Re: [patch 4/8] x86/tsc: Verify TSC_ADJUST from idle Peter Zijlstra <peterz@infradead.org> - 2016-11-21 12:10 +0100
    Re: [patch 4/8] x86/tsc: Verify TSC_ADJUST from idle Andi Kleen <andi@firstfloor.org> - 2016-11-22 00:00 +0100
  [patch 5/8] x86/tsc: Sync test only for the first cpu in a package Thomas Gleixner <tglx@linutronix.de> - 2016-11-19 15:00 +0100
  [patch 3/8] x86/tsc: Store and check TSC ADJUST MSR Thomas Gleixner <tglx@linutronix.de> - 2016-11-19 15:00 +0100
  [patch 1/8] x86/tsc: Use X86_FEATURE_TSC_ADJUST in detect_art() Thomas Gleixner <tglx@linutronix.de> - 2016-11-19 15:00 +0100
  [patch 2/8] x86/tsc: Detect random warps Thomas Gleixner <tglx@linutronix.de> - 2016-11-19 15:00 +0100
  [patch 7/8] x86/tsc: Prepare warp test for TSC adjustment Thomas Gleixner <tglx@linutronix.de> - 2016-11-19 15:00 +0100

csiph-web