Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/x86/x86 Explain the TSC drift thing.



details:   https://anonhg.NetBSD.org/src/rev/58573a4ba1c9
branches:  trunk
changeset: 321327:58573a4ba1c9
user:      maxv <maxv%NetBSD.org@localhost>
date:      Sun Mar 11 13:38:02 2018 +0000

description:
Explain the TSC drift thing.

diffstat:

 sys/arch/x86/x86/cpu.c |  36 ++++++++++++++++++++++++------------
 1 files changed, 24 insertions(+), 12 deletions(-)

diffs (84 lines):

diff -r 2ef143f3824d -r 58573a4ba1c9 sys/arch/x86/x86/cpu.c
--- a/sys/arch/x86/x86/cpu.c    Sun Mar 11 11:48:39 2018 +0000
+++ b/sys/arch/x86/x86/cpu.c    Sun Mar 11 13:38:02 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cpu.c,v 1.149 2018/02/22 13:27:18 maxv Exp $   */
+/*     $NetBSD: cpu.c,v 1.150 2018/03/11 13:38:02 maxv Exp $   */
 
 /*
  * Copyright (c) 2000-2012 NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.149 2018/02/22 13:27:18 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.150 2018/03/11 13:38:02 maxv Exp $");
 
 #include "opt_ddb.h"
 #include "opt_mpbios.h"                /* for MPDEBUG */
@@ -674,7 +674,7 @@
 #endif /* MTRR */
 
        if (ci != &cpu_info_primary) {
-               /* Synchronize TSC again, and check for drift. */
+               /* Synchronize TSC */
                wbinvd();
                atomic_or_32(&ci->ci_flags, CPUF_RUNNING);
                tsc_sync_ap(ci);
@@ -786,8 +786,9 @@
        } else {
                /*
                 * Synchronize time stamp counters. Invalidate cache and do
-                * twice to try and minimize possible cache effects. Disable
-                * interrupts to try and rule out any external interference.
+                * twice (in tsc_sync_bp) to minimize possible cache effects.
+                * Disable interrupts to try and rule out any external
+                * interference.
                 */
                psl = x86_read_psl();
                x86_disable_intr();
@@ -854,19 +855,25 @@
        KDASSERT((ci->ci_flags & CPUF_PRESENT) == 0);
 
        /*
-        * Synchronize time stamp counters.  Invalidate cache and do twice
-        * to try and minimize possible cache effects.  Note that interrupts
-        * are off at this point.
+        * Synchronize the TSC for the first time. Note that interrupts are
+        * off at this point.
         */
        wbinvd();
        atomic_or_32(&ci->ci_flags, CPUF_PRESENT);
        tsc_sync_ap(ci);
 
        /*
-        * Wait to be brought online.  Use 'monitor/mwait' if available,
-        * in order to make the TSC drift as much as possible. so that
-        * we can detect it later.  If not available, try 'pause'.
-        * We'd like to use 'hlt', but we have interrupts off.
+        * Wait to be brought online.
+        *
+        * Use MONITOR/MWAIT if available. These instructions put the CPU in
+        * a low consumption mode (C-state), and if the TSC is not invariant,
+        * this causes the TSC to drift. We want this to happen, so that we
+        * can later detect (in tsc_tc_init) any abnormal drift with invariant
+        * TSCs. That's just for safety; by definition such drifts should
+        * never occur with invariant TSCs.
+        *
+        * If not available, try PAUSE. We'd like to use HLT, but we have
+        * interrupts off.
         */
        while ((ci->ci_flags & CPUF_GO) == 0) {
                if ((cpu_feature[1] & CPUID2_MONITOR) != 0) {
@@ -922,6 +929,11 @@
        lldt(GSYSSEL(GLDT_SEL, SEL_KPL));
        ltr(ci->ci_tss_sel);
 
+       /*
+        * cpu_init will re-synchronize the TSC, and will detect any abnormal
+        * drift that would have been caused by the use of MONITOR/MWAIT
+        * above.
+        */
        cpu_init(ci);
        cpu_get_tsc_freq(ci);
 



Home | Main Index | Thread Index | Old Index