Source-Changes-HG archive

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

[src/trunk]: src/sys/arch Print a rate limited warning if the TSC timecounter...



details:   https://anonhg.NetBSD.org/src/rev/0b43e0963cfc
branches:  trunk
changeset: 934563:0b43e0963cfc
user:      ad <ad%NetBSD.org@localhost>
date:      Sat Jun 13 23:58:51 2020 +0000

description:
Print a rate limited warning if the TSC timecounter goes backwards from the
viewpoint of any single LWP.

diffstat:

 sys/arch/amd64/amd64/cpufunc.S |   9 +++++----
 sys/arch/amd64/include/proc.h  |   3 ++-
 sys/arch/i386/i386/cpufunc.S   |  11 +++++------
 sys/arch/i386/include/proc.h   |   3 ++-
 sys/arch/x86/x86/tsc.c         |  40 +++++++++++++++++++++++++++++++++++++---
 5 files changed, 51 insertions(+), 15 deletions(-)

diffs (176 lines):

diff -r dba2ea83a496 -r 0b43e0963cfc sys/arch/amd64/amd64/cpufunc.S
--- a/sys/arch/amd64/amd64/cpufunc.S    Sat Jun 13 22:35:23 2020 +0000
+++ b/sys/arch/amd64/amd64/cpufunc.S    Sat Jun 13 23:58:51 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cpufunc.S,v 1.59 2020/06/01 22:58:06 ad Exp $  */
+/*     $NetBSD: cpufunc.S,v 1.60 2020/06/13 23:58:51 ad Exp $  */
 
 /*
  * Copyright (c) 1998, 2007, 2008, 2020 The NetBSD Foundation, Inc.
@@ -206,8 +206,10 @@
 END(x86_hotpatch)
 #endif /* !XENPV */
 
-/* Could be exact same as cpu_counter, but KMSAN needs to have the correct
- * size of the return value. */
+/*
+ * Could be exact same as cpu_counter, but KMSAN needs to have the correct
+ * size of the return value.
+ */
 ENTRY(cpu_counter32)
        movq    CPUVAR(CURLWP), %rcx
 1:
@@ -221,7 +223,6 @@
 2:
        jmp     1b
 END(cpu_counter32)
-STRONG_ALIAS(tsc_get_timecount, cpu_counter32)
 
 ENTRY(cpu_counter)
        movq    CPUVAR(CURLWP), %rcx
diff -r dba2ea83a496 -r 0b43e0963cfc sys/arch/amd64/include/proc.h
--- a/sys/arch/amd64/include/proc.h     Sat Jun 13 22:35:23 2020 +0000
+++ b/sys/arch/amd64/include/proc.h     Sat Jun 13 23:58:51 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: proc.h,v 1.24 2020/01/13 00:26:52 ad Exp $     */
+/*     $NetBSD: proc.h,v 1.25 2020/06/13 23:58:51 ad Exp $     */
 
 /*
  * Copyright (c) 1991 Regents of the University of California.
@@ -46,6 +46,7 @@
 struct vm_page;
 
 struct mdlwp {
+       volatile uint64_t md_tsc;       /* last TSC reading */
        struct  trapframe *md_regs;     /* registers on current frame */
        int     md_flags;               /* machine-dependent flags */
        volatile int md_astpending;
diff -r dba2ea83a496 -r 0b43e0963cfc sys/arch/i386/i386/cpufunc.S
--- a/sys/arch/i386/i386/cpufunc.S      Sat Jun 13 22:35:23 2020 +0000
+++ b/sys/arch/i386/i386/cpufunc.S      Sat Jun 13 23:58:51 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: cpufunc.S,v 1.45 2020/05/28 20:03:19 ad Exp $  */
+/*     $NetBSD: cpufunc.S,v 1.46 2020/06/13 23:58:52 ad Exp $  */
 
 /*-
  * Copyright (c) 1998, 2007, 2020 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
 #include <sys/errno.h>
 
 #include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: cpufunc.S,v 1.45 2020/05/28 20:03:19 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpufunc.S,v 1.46 2020/06/13 23:58:52 ad Exp $");
 
 #include "opt_xen.h"
 
@@ -163,7 +163,7 @@
        ret
 END(msr_onfault)
 
-ENTRY(tsc_get_timecount)
+ENTRY(cpu_counter)
        pushl   %ebx
        movl    CPUVAR(CURLWP), %ecx
 1:
@@ -177,10 +177,9 @@
        ret
 2:
        jmp     1b
-END(tsc_get_timecount)
+END(cpu_counter)
 
-STRONG_ALIAS(cpu_counter, tsc_get_timecount)
-STRONG_ALIAS(cpu_counter32, tsc_get_timecount)
+STRONG_ALIAS(cpu_counter32, cpu_counter)
 
 ENTRY(breakpoint)
        pushl   %ebp
diff -r dba2ea83a496 -r 0b43e0963cfc sys/arch/i386/include/proc.h
--- a/sys/arch/i386/include/proc.h      Sat Jun 13 22:35:23 2020 +0000
+++ b/sys/arch/i386/include/proc.h      Sat Jun 13 23:58:51 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: proc.h,v 1.47 2020/01/13 00:26:52 ad Exp $     */
+/*     $NetBSD: proc.h,v 1.48 2020/06/13 23:58:52 ad Exp $     */
 
 /*
  * Copyright (c) 1991 Regents of the University of California.
@@ -46,6 +46,7 @@
 #define        MDL_FPU_IN_CPU          0x0020  /* the FPU state is in the CPU */
 
 struct mdlwp {
+       volatile uint64_t md_tsc;       /* last TSC reading */
        struct  trapframe *md_regs;     /* registers on current frame */
        int     md_flags;               /* machine-dependent flags */
        volatile int md_astpending;     /* AST pending for this process */
diff -r dba2ea83a496 -r 0b43e0963cfc sys/arch/x86/x86/tsc.c
--- a/sys/arch/x86/x86/tsc.c    Sat Jun 13 22:35:23 2020 +0000
+++ b/sys/arch/x86/x86/tsc.c    Sat Jun 13 23:58:51 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tsc.c,v 1.48 2020/05/27 18:46:15 ad Exp $      */
+/*     $NetBSD: tsc.c,v 1.49 2020/06/13 23:58:52 ad Exp $      */
 
 /*-
  * Copyright (c) 2008, 2020 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.48 2020/05/27 18:46:15 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tsc.c,v 1.49 2020/06/13 23:58:52 ad Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -38,6 +38,7 @@
 #include <sys/kernel.h>
 #include <sys/cpu.h>
 #include <sys/xcall.h>
+#include <sys/lock.h>
 
 #include <machine/cpu_counter.h>
 #include <machine/cpuvar.h>
@@ -50,7 +51,7 @@
 #define        TSC_SYNC_ROUNDS         1000
 #define        ABS(a)                  ((a) >= 0 ? (a) : -(a))
 
-u_int  tsc_get_timecount(struct timecounter *);
+static u_int   tsc_get_timecount(struct timecounter *);
 
 static void    tsc_delay(unsigned int);
 
@@ -352,3 +353,36 @@
                x86_pause();
        }
 }
+
+static u_int
+tsc_get_timecount(struct timecounter *tc)
+{
+       static __cpu_simple_lock_t lock = __SIMPLELOCK_UNLOCKED;
+       static int lastwarn;
+       uint64_t cur, prev;
+       lwp_t *l = curlwp;
+       int ticks;
+
+       /*
+        * Previous value must be read before the counter and stored to
+        * after, because this routine can be called from interrupt context
+        * and may run over the top of an existing invocation.  Ordering is
+        * guaranteed by "volatile" on md_tsc.
+        */
+       prev = l->l_md.md_tsc;
+       cur = cpu_counter();
+       if (__predict_false(cur < prev)) {
+               if ((cur >> 63) == (prev >> 63) &&
+                   __cpu_simple_lock_try(&lock)) {
+                       ticks = getticks();
+                       if (ticks - lastwarn >= hz) {
+                               printf("WARNING: TSC time went backwards "
+                                   " by %u\n", (unsigned)(prev - cur));
+                               lastwarn = ticks;
+                       }
+                       __cpu_simple_unlock(&lock);
+               }
+       }
+       l->l_md.md_tsc = cur;
+       return (uint32_t)cur;
+}



Home | Main Index | Thread Index | Old Index