Author: jkim
Date: Tue Oct 21 00:38:00 2008
New Revision: 184102
URL: http://svn.freebsd.org/changeset/base/184102

Log:
  Turn off CPU frequency change notifiers when the TSC is P-state invariant
  or it is forced by setting 'kern.timecounter.invariant_tsc' tunable
  to non-zero.

Modified:
  head/sys/amd64/amd64/identcpu.c
  head/sys/amd64/amd64/prof_machdep.c
  head/sys/amd64/amd64/tsc.c
  head/sys/amd64/include/clock.h
  head/sys/contrib/altq/altq/altq_subr.c
  head/sys/i386/i386/identcpu.c
  head/sys/i386/i386/tsc.c
  head/sys/i386/include/clock.h
  head/sys/i386/isa/prof_machdep.c

Modified: head/sys/amd64/amd64/identcpu.c
==============================================================================
--- head/sys/amd64/amd64/identcpu.c     Tue Oct 21 00:17:55 2008        
(r184101)
+++ head/sys/amd64/amd64/identcpu.c     Tue Oct 21 00:38:00 2008        
(r184102)
@@ -347,6 +347,12 @@ printcpuinfo(void)
                            "AuthenticAMD") == 0)
                                cpu_feature &= ~CPUID_HTT;
 
+                       if (!tsc_is_invariant &&
+                           (amd_pminfo & AMDPM_TSC_INVARIANT)) {
+                               tsc_is_invariant = 1;
+                               printf("\n  P-state invariant TSC");
+                       }
+
                        /*
                         * If this CPU supports HTT or CMP then mention the
                         * number of physical/logical cores it contains.
@@ -409,8 +415,11 @@ panicifcpuunsupported(void)
 static void
 tsc_freq_changed(void *arg, const struct cf_level *level, int status)
 {
-       /* If there was an error during the transition, don't do anything. */
-       if (status != 0)
+       /*
+        * If there was an error during the transition or
+        * TSC is P-state invariant, don't do anything.
+        */
+       if (status != 0 || tsc_is_invariant)
                return;
 
        /* Total setting for this level gives the new frequency in MHz. */

Modified: head/sys/amd64/amd64/prof_machdep.c
==============================================================================
--- head/sys/amd64/amd64/prof_machdep.c Tue Oct 21 00:17:55 2008        
(r184101)
+++ head/sys/amd64/amd64/prof_machdep.c Tue Oct 21 00:38:00 2008        
(r184102)
@@ -383,8 +383,11 @@ static void
 tsc_freq_changed(void *arg, const struct cf_level *level, int status)
 {
 
-       /* If there was an error during the transition, don't do anything. */
-       if (status != 0)
+       /*
+        * If there was an error during the transition or
+        * TSC is P-state invariant, don't do anything.
+        */
+       if (status != 0 || tsc_is_invariant)
                return;
        if (cputime_prof_active && cputime_clock == CPUTIME_CLOCK_TSC)
                printf("warning: cpu freq changed while profiling active\n");

Modified: head/sys/amd64/amd64/tsc.c
==============================================================================
--- head/sys/amd64/amd64/tsc.c  Tue Oct 21 00:17:55 2008        (r184101)
+++ head/sys/amd64/amd64/tsc.c  Tue Oct 21 00:38:00 2008        (r184102)
@@ -48,8 +48,13 @@ __FBSDID("$FreeBSD$");
 
 uint64_t       tsc_freq;
 int            tsc_is_broken;
+int            tsc_is_invariant;
 static eventhandler_tag tsc_levels_tag, tsc_pre_tag, tsc_post_tag;
 
+SYSCTL_INT(_kern_timecounter, OID_AUTO, invariant_tsc, CTLFLAG_RDTUN,
+    &tsc_is_invariant, 0, "Indicates whether the TSC is P-state invariant");
+TUNABLE_INT("kern.timecounter.invariant_tsc", &tsc_is_invariant);
+
 #ifdef SMP
 static int     smp_tsc;
 SYSCTL_INT(_kern_timecounter, OID_AUTO, smp_tsc, CTLFLAG_RDTUN, &smp_tsc, 0,
@@ -174,11 +179,12 @@ static void
 tsc_freq_changing(void *arg, const struct cf_level *level, int *status)
 {
 
-       if (*status != 0 || timecounter != &tsc_timecounter)
+       if (*status != 0 || timecounter != &tsc_timecounter ||
+           tsc_is_invariant)
                return;
 
        printf("timecounter TSC must not be in use when "
-            "changing frequencies; change denied\n");
+           "changing frequencies; change denied\n");
        *status = EBUSY;
 }
 
@@ -186,8 +192,11 @@ tsc_freq_changing(void *arg, const struc
 static void
 tsc_freq_changed(void *arg, const struct cf_level *level, int status)
 {
-       /* If there was an error during the transition, don't do anything. */
-       if (status != 0)
+       /*
+        * If there was an error during the transition or
+        * TSC is P-state invariant, don't do anything.
+        */
+       if (status != 0 || tsc_is_invariant)
                return;
 
        /* Total setting for this level gives the new frequency in MHz. */

Modified: head/sys/amd64/include/clock.h
==============================================================================
--- head/sys/amd64/include/clock.h      Tue Oct 21 00:17:55 2008        
(r184101)
+++ head/sys/amd64/include/clock.h      Tue Oct 21 00:38:00 2008        
(r184102)
@@ -20,6 +20,7 @@ extern u_int  i8254_freq;
 extern int     i8254_max_count;
 extern uint64_t        tsc_freq;
 extern int     tsc_is_broken;
+extern int     tsc_is_invariant;
 
 void   i8254_init(void);
 

Modified: head/sys/contrib/altq/altq/altq_subr.c
==============================================================================
--- head/sys/contrib/altq/altq/altq_subr.c      Tue Oct 21 00:17:55 2008        
(r184101)
+++ head/sys/contrib/altq/altq/altq_subr.c      Tue Oct 21 00:38:00 2008        
(r184102)
@@ -909,6 +909,12 @@ tsc_freq_changed(void *arg, const struct
        if (status != 0)
                return;
 
+#if (__FreeBSD_version >= 800050) && (defined(__amd64__) || defined(__i386__))
+       /* If TSC is P-state invariant, don't do anything. */
+       if (tsc_is_invariant)
+               return;
+#endif
+
        /* Total setting for this level gives the new frequency in MHz. */
        init_machclk();
 }

Modified: head/sys/i386/i386/identcpu.c
==============================================================================
--- head/sys/i386/i386/identcpu.c       Tue Oct 21 00:17:55 2008        
(r184101)
+++ head/sys/i386/i386/identcpu.c       Tue Oct 21 00:38:00 2008        
(r184102)
@@ -841,6 +841,12 @@ printcpuinfo(void)
                            "AuthenticAMD") == 0)
                                cpu_feature &= ~CPUID_HTT;
 
+                       if (!tsc_is_invariant &&
+                           (amd_pminfo & AMDPM_TSC_INVARIANT)) {
+                               tsc_is_invariant = 1;
+                               printf("\n  P-state invariant TSC");
+                       }
+
                        /*
                         * If this CPU supports HTT or CMP then mention the
                         * number of physical/logical cores it contains.
@@ -1059,8 +1065,11 @@ identifycyrix(void)
 static void
 tsc_freq_changed(void *arg, const struct cf_level *level, int status)
 {
-       /* If there was an error during the transition, don't do anything. */
-       if (status != 0)
+       /*
+        * If there was an error during the transition or
+        * TSC is P-state invariant, don't do anything.
+        */
+       if (status != 0 || tsc_is_invariant)
                return;
 
        /* Total setting for this level gives the new frequency in MHz. */

Modified: head/sys/i386/i386/tsc.c
==============================================================================
--- head/sys/i386/i386/tsc.c    Tue Oct 21 00:17:55 2008        (r184101)
+++ head/sys/i386/i386/tsc.c    Tue Oct 21 00:38:00 2008        (r184102)
@@ -48,9 +48,13 @@ __FBSDID("$FreeBSD$");
 
 uint64_t       tsc_freq;
 int            tsc_is_broken;
+int            tsc_is_invariant;
 u_int          tsc_present;
 static eventhandler_tag tsc_levels_tag, tsc_pre_tag, tsc_post_tag;
 
+SYSCTL_INT(_kern_timecounter, OID_AUTO, invariant_tsc, CTLFLAG_RDTUN,
+    &tsc_is_invariant, 0, "Indicates the TSC is P-state invariant");
+
 #ifdef SMP
 static int     smp_tsc;
 SYSCTL_INT(_kern_timecounter, OID_AUTO, smp_tsc, CTLFLAG_RDTUN, &smp_tsc, 0,
@@ -107,8 +111,9 @@ init_TSC(void)
        set_cputicker(rdtsc, tsc_freq, 1);
 
        /* Register to find out about changes in CPU frequency. */
-       tsc_pre_tag = EVENTHANDLER_REGISTER(cpufreq_pre_change,
-           tsc_freq_changing, NULL, EVENTHANDLER_PRI_FIRST);
+       if (!tsc_is_invariant)
+               tsc_pre_tag = EVENTHANDLER_REGISTER(cpufreq_pre_change,
+                   tsc_freq_changing, NULL, EVENTHANDLER_PRI_FIRST);
        tsc_post_tag = EVENTHANDLER_REGISTER(cpufreq_post_change,
            tsc_freq_changed, NULL, EVENTHANDLER_PRI_FIRST);
        tsc_levels_tag = EVENTHANDLER_REGISTER(cpufreq_levels_changed,
@@ -198,11 +203,12 @@ static void
 tsc_freq_changing(void *arg, const struct cf_level *level, int *status)
 {
 
-       if (*status != 0 || timecounter != &tsc_timecounter)
+       if (*status != 0 || timecounter != &tsc_timecounter ||
+           tsc_is_invariant)
                return;
 
        printf("timecounter TSC must not be in use when "
-            "changing frequencies; change denied\n");
+           "changing frequencies; change denied\n");
        *status = EBUSY;
 }
 
@@ -210,8 +216,11 @@ tsc_freq_changing(void *arg, const struc
 static void
 tsc_freq_changed(void *arg, const struct cf_level *level, int status)
 {
-       /* If there was an error during the transition, don't do anything. */
-       if (status != 0)
+       /*
+        * If there was an error during the transition or
+        * TSC is P-state invariant, don't do anything.
+        */
+       if (status != 0 || tsc_is_invariant)
                return;
 
        /* Total setting for this level gives the new frequency in MHz. */

Modified: head/sys/i386/include/clock.h
==============================================================================
--- head/sys/i386/include/clock.h       Tue Oct 21 00:17:55 2008        
(r184101)
+++ head/sys/i386/include/clock.h       Tue Oct 21 00:38:00 2008        
(r184102)
@@ -20,6 +20,7 @@ extern u_int  i8254_freq;
 extern int     i8254_max_count;
 extern uint64_t        tsc_freq;
 extern int     tsc_is_broken;
+extern int     tsc_is_invariant;
 
 void   i8254_init(void);
 

Modified: head/sys/i386/isa/prof_machdep.c
==============================================================================
--- head/sys/i386/isa/prof_machdep.c    Tue Oct 21 00:17:55 2008        
(r184101)
+++ head/sys/i386/isa/prof_machdep.c    Tue Oct 21 00:38:00 2008        
(r184102)
@@ -353,8 +353,11 @@ static void
 tsc_freq_changed(void *arg, const struct cf_level *level, int status)
 {
 
-       /* If there was an error during the transition, don't do anything. */
-       if (status != 0)
+       /*
+        * If there was an error during the transition or
+        * TSC is P-state invariant, don't do anything.
+        */
+       if (status != 0 || tsc_is_invariant)
                return;
        if (cputime_prof_active && cputime_clock == CPUTIME_CLOCK_TSC)
                printf("warning: cpu freq changed while profiling active\n");
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to