[patch] Re: bogo-bogomips

From: Pavel Machek (pavel@suse.cz)
Date: Sat Mar 18 2000 - 15:58:34 EST


Hi!

> > Makes me wonder if the RTC is playing up. Any theories?
>
> Its -BOGO- mips. Its a bogus meaningless indication of process speed. We've
> changed the way we measure it for delay loops to use the TSC on chips that
> support RDTSC.

But it is still broken.

Let laptop boot in maximum powersaving mode (low bateries will do the
trick on my toshiba), then plug AC in.

Suddenly, all your udelay() loops take only HALF of expected time;
that's problem.

I've got a code which detects such events, warns, and
recalibrates. Code looks like this:

                                                        Pavel

--- clean/arch/i386/kernel/time.c Fri Jan 21 13:39:12 2000
+++ linux/arch/i386/kernel/time.c Fri Jan 21 13:31:52 2000
@@ -145,7 +145,7 @@
  * comp.protocols.time.ntp!
  */
 
-static unsigned long do_slow_gettimeoffset(void)
+static unsigned long do_read_hwtimer(void)
 {
         int count;
 
@@ -209,7 +209,7 @@
 
                                 count -= 256;
 #else
- printk("do_slow_gettimeoffset(): hardware timer problem?\n");
+ printk("do_read_hwtimer(): hardware timer problem?\n");
 #endif
                         }
                 }
@@ -217,6 +217,12 @@
                 jiffies_p = jiffies_t;
 
         count_p = count;
+ return count;
+}
+
+unsigned long do_slow_gettimeoffset(void)
+{
+ unsigned long count = do_read_hwtimer();
 
         count = ((LATCH-1) - count) * TICK_SIZE;
         count = (count + LATCH/2) / LATCH;
@@ -430,6 +436,27 @@
          */
         write_lock(&xtime_lock);
 
+ if (use_tsc) {
+ long off = do_gettimeoffset();
+ static int faster = 0, slower = 0;
+ if (off > (1100000/HZ))
+ faster++;
+ else
+ faster = 0;
+
+ if (off < (900000/HZ))
+ slower++;
+ else
+ slower = 0;
+
+ if ((faster > 100) || (slower > 100)) {
+ printk( KERN_ERR "TSC is %s than it should be! ", (faster > 10) ? "faster" : "slower" );
+ big_calibrate_tsc();
+ faster = 0;
+ slower = 0;
+ }
+ }
+
         if (use_tsc)
         {
                 /*
@@ -548,7 +575,7 @@
 #define CALIBRATE_LATCH (5 * LATCH)
 #define CALIBRATE_TIME (5 * 1000020/HZ)
 
-static unsigned long __init calibrate_tsc(void)
+static unsigned long calibrate_tsc(void)
 {
        /* Set the Gate high, disable speaker */
         outb((inb(0x61) & ~0x02) | 0x01, 0x61);
@@ -613,11 +640,39 @@
         return 0;
 }
 
+void big_calibrate_tsc(void)
+{
+ if (boot_cpu_data.x86_capability & X86_FEATURE_TSC) {
+ unsigned long tsc_quotient = calibrate_tsc();
+ if (tsc_quotient) {
+ fast_gettimeoffset_quotient = tsc_quotient;
+ use_tsc = 1;
+#ifndef do_gettimeoffset
+ do_gettimeoffset = do_fast_gettimeoffset;
+#endif
+ do_get_fast_time = do_gettimeofday;
+
+ /* report CPU clock rate in Hz.
+ * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
+ * clock/second. Our precision is about 100 ppm.
+ */
+ { unsigned long eax=0, edx=1000000;
+ __asm__("divl %2"
+ :"=a" (cpu_hz), "=d" (edx)
+ :"r" (tsc_quotient),
+ "0" (eax), "1" (edx));
+ printk("Detected %ld Hz processor.\n", cpu_hz);
+ }
+ }
+ }
+}
+
 void __init time_init(void)
 {
         xtime.tv_sec = get_cmos_time();
         xtime.tv_usec = 0;
 
+
 /*
  * If we have APM enabled or the CPU clock speed is variable
  * (CPU stops clock on HLT or slows clock to save power)
@@ -645,29 +700,7 @@
  
          dodgy_tsc();
          
- if (boot_cpu_data.x86_capability & X86_FEATURE_TSC) {
- unsigned long tsc_quotient = calibrate_tsc();
- if (tsc_quotient) {
- fast_gettimeoffset_quotient = tsc_quotient;
- use_tsc = 1;
-#ifndef do_gettimeoffset
- do_gettimeoffset = do_fast_gettimeoffset;
-#endif
- do_get_fast_time = do_gettimeofday;
-
- /* report CPU clock rate in Hz.
- * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
- * clock/second. Our precision is about 100 ppm.
- */
- { unsigned long eax=0, edx=1000000;
- __asm__("divl %2"
- :"=a" (cpu_hz), "=d" (edx)
- :"r" (tsc_quotient),
- "0" (eax), "1" (edx));
- printk("Detected %ld Hz processor.\n", cpu_hz);
- }
- }
- }
+ big_calibrate_tsc();
 
 #ifdef CONFIG_VISWS
         printk("Starting Cobalt Timer system clock\n");

-- 
I'm pavel@ucw.cz. "In my country we have almost anarchy and I don't care."
Panos Katsaloulis describing me w.r.t. patents me at discuss@linmodems.org

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Mar 23 2000 - 21:00:26 EST