Re: BogoMIPS and changed CPU speed

From: Pavel Machek (pavel@suse.cz)
Date: Sun Jul 23 2000 - 14:41:45 EST


Hi!

> As I understand the BogoMIPS value is used for some fine grained
> delays. How does then the system survive a big change in the processor
> speed when :
>
> - user changes FSB on the fly ( possible with newer mainboards,
> I never tried it though )
> - CPU goes to lower clock due to power management
> - user (de)activates TURBO on older x86 computers

- CPU goes to HIGHER clock due to power managment. This happens on my
toshiba.

We've got a problem. There's no good solution, but we can at least
recalibrate delay loop after change. Machine may have already died
before that, but that does not happen in practice. User should at
least know there is a problem...

                                                                Pavel

--- clean/arch/i386/kernel/time.c Wed Jul 12 21:02:29 2000
+++ linux/arch/i386/kernel/time.c Sun Jul 23 21:39:10 2000
@@ -63,7 +63,7 @@
  */
 #include <linux/irq.h>
 
-
+extern int x86_udelay_tsc;
 unsigned long cpu_hz; /* Detected as we calibrate the TSC */
 
 /* Number of usecs that the last interrupt was delayed */
@@ -152,7 +152,7 @@
  * comp.protocols.time.ntp!
  */
 
-static unsigned long do_slow_gettimeoffset(void)
+static unsigned long do_read_hwtimer(void)
 {
         int count;
 
@@ -227,7 +227,7 @@
 
                                 count -= 256;
 #else
- printk("do_slow_gettimeoffset(): hardware timer problem?\n");
+ printk("do_read_hwtimer(): hardware timer problem?\n");
 #endif
                         }
                 }
@@ -235,6 +235,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;
@@ -451,6 +457,38 @@
 
 static int use_tsc = 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;
+ /*
+ * We could be more selective here I suspect
+ * and just enable this for the next intel chips ?
+ */
+ x86_udelay_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);
+ }
+ }
+ }
+}
+
 /*
  * This is the same as the above, except we _also_ save the current
  * Time Stamp Counter value at the time of the timer interrupt, so that
@@ -469,6 +507,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)
         {
                 /*
@@ -589,7 +648,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);
@@ -656,8 +715,6 @@
 
 void __init time_init(void)
 {
- extern int x86_udelay_tsc;
-
         xtime.tv_sec = get_cmos_time();
         xtime.tv_usec = 0;
 
@@ -688,34 +745,7 @@
  
          dodgy_tsc();
          
- if (cpu_has_tsc) {
- unsigned long tsc_quotient = calibrate_tsc();
- if (tsc_quotient) {
- fast_gettimeoffset_quotient = tsc_quotient;
- use_tsc = 1;
- /*
- * We could be more selective here I suspect
- * and just enable this for the next intel chips ?
- */
- x86_udelay_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 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 : Sun Jul 23 2000 - 21:00:20 EST