]> err.no Git - linux-2.6/blobdiff - arch/x86/kernel/tsc_32.c
x86: printk kernel version in WARN_ON and other dump_stack users
[linux-2.6] / arch / x86 / kernel / tsc_32.c
index b8a7cf6714327ebd7c338883ccb257901aeab3dc..9ebc0dab66b4ced5720818ce600b2dd14ccf0e18 100644 (file)
@@ -59,7 +59,7 @@ int check_tsc_unstable(void)
 }
 EXPORT_SYMBOL_GPL(check_tsc_unstable);
 
-/* Accellerators for sched_clock()
+/* Accelerators for sched_clock()
  * convert from cycles(64bits) => nanoseconds (64bits)
  *  basic equation:
  *             ns = cycles / (freq / ns_per_sec)
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(check_tsc_unstable);
  *     And since SC is a constant power of two, we can convert the div
  *  into a shift.
  *
- *  We can use khz divisor instead of mhz to keep a better percision, since
+ *  We can use khz divisor instead of mhz to keep a better precision, since
  *  cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits.
  *  (mathieu.desnoyers@polymtl.ca)
  *
@@ -131,38 +131,43 @@ unsigned long native_calculate_cpu_khz(void)
 {
        unsigned long long start, end;
        unsigned long count;
-       u64 delta64;
+       u64 delta64 = (u64)ULLONG_MAX;
        int i;
        unsigned long flags;
 
        local_irq_save(flags);
 
-       /* run 3 times to ensure the cache is warm */
+       /* run 3 times to ensure the cache is warm and to get an accurate reading */
        for (i = 0; i < 3; i++) {
                mach_prepare_counter();
                rdtscll(start);
                mach_countup(&count);
                rdtscll(end);
-       }
-       /*
-        * Error: ECTCNEVERSET
-        * The CTC wasn't reliable: we got a hit on the very first read,
-        * or the CPU was so fast/slow that the quotient wouldn't fit in
-        * 32 bits..
-        */
-       if (count <= 1)
-               goto err;
 
-       delta64 = end - start;
+               /*
+                * Error: ECTCNEVERSET
+                * The CTC wasn't reliable: we got a hit on the very first read,
+                * or the CPU was so fast/slow that the quotient wouldn't fit in
+                * 32 bits..
+                */
+               if (count <= 1)
+                       continue;
+
+               /* cpu freq too slow: */
+               if ((end - start) <= CALIBRATE_TIME_MSEC)
+                       continue;
+
+               /*
+                * We want the minimum time of all runs in case one of them
+                * is inaccurate due to SMI or other delay
+                */
+               delta64 = min(delta64, (end - start));
+       }
 
-       /* cpu freq too fast: */
+       /* cpu freq too fast (or every run was bad): */
        if (delta64 > (1ULL<<32))
                goto err;
 
-       /* cpu freq too slow: */
-       if (delta64 <= CALIBRATE_TIME_MSEC)
-               goto err;
-
        delta64 += CALIBRATE_TIME_MSEC/2; /* round for do_div */
        do_div(delta64,CALIBRATE_TIME_MSEC);