ia64/xen-unstable

changeset 5829:bf68b5fcbc9b

Simplify and fix the error-correction factor during
local timer calibration.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Jul 19 08:52:32 2005 +0000 (2005-07-19)
parents 43564304cf94
children 2ecb91fb6cdb
files xen/arch/x86/time.c
line diff
     1.1 --- a/xen/arch/x86/time.c	Mon Jul 18 20:22:11 2005 +0000
     1.2 +++ b/xen/arch/x86/time.c	Tue Jul 19 08:52:32 2005 +0000
     1.3 @@ -30,6 +30,8 @@
     1.4  #include <asm/div64.h>
     1.5  #include <io_ports.h>
     1.6  
     1.7 +#define EPOCH MILLISECS(1000)
     1.8 +
     1.9  unsigned long cpu_khz;  /* CPU clock frequency in kHz. */
    1.10  spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
    1.11  int timer_ack = 0;
    1.12 @@ -80,8 +82,8 @@ static inline u32 div_frac(u32 dividend,
    1.13  }
    1.14  
    1.15  /*
    1.16 - * 32-bit multiplication of integer multiplicand and fractional multiplier
    1.17 - * yielding 32-bit integer product.
    1.18 + * 32-bit multiplication of multiplicand and fractional multiplier
    1.19 + * yielding 32-bit product (radix point at same position as in multiplicand).
    1.20   */
    1.21  static inline u32 mul_frac(u32 multiplicand, u32 multiplier)
    1.22  {
    1.23 @@ -461,15 +463,23 @@ static void local_time_calibration(void 
    1.24  
    1.25      /*
    1.26       * System time and TSC ticks elapsed during the previous calibration
    1.27 -     * 'epoch'. Also the accumulated error in the local estimate. All these
    1.28 -     * values end up down-shifted to fit in 32 bits.
    1.29 +     * 'epoch'. These values are down-shifted to fit in 32 bits.
    1.30       */
    1.31 -    u64 stime_elapsed64, tsc_elapsed64, local_stime_error64;
    1.32 -    u32 stime_elapsed32, tsc_elapsed32, local_stime_error32;
    1.33 +    u64 stime_elapsed64, tsc_elapsed64;
    1.34 +    u32 stime_elapsed32, tsc_elapsed32;
    1.35 +
    1.36 +    /* The accumulated error in the local estimate. */
    1.37 +    u64 local_stime_err;
    1.38 +
    1.39 +    /* Error correction to slow down a fast local clock. */
    1.40 +    u32 error_factor = 0;
    1.41  
    1.42      /* Calculated TSC shift to ensure 32-bit scale multiplier. */
    1.43      int tsc_shift = 0;
    1.44  
    1.45 +    /* The overall calibration scale multiplier. */
    1.46 +    u32 calibration_mul_frac;
    1.47 +
    1.48      prev_tsc          = cpu_time[cpu].local_tsc_stamp;
    1.49      prev_local_stime  = cpu_time[cpu].stime_local_stamp;
    1.50      prev_master_stime = cpu_time[cpu].stime_master_stamp;
    1.51 @@ -497,13 +507,17 @@ static void local_time_calibration(void 
    1.52      tsc_elapsed64   = curr_tsc - prev_tsc;
    1.53  
    1.54      /*
    1.55 -     * Error in the local system time estimate. Clamp to epoch time period, or
    1.56 -     * we could end up with a negative scale factor (time going backwards!).
    1.57 -     * This effectively clamps the scale factor to >= 0.
    1.58 +     * Calculate error-correction factor. This only slows down a fast local
    1.59 +     * clock (slow clocks are warped forwards). The scale factor is clamped
    1.60 +     * to >= 0.5.
    1.61       */
    1.62 -    local_stime_error64 = curr_local_stime - curr_master_stime;
    1.63 -    if ( local_stime_error64 > stime_elapsed64 )
    1.64 -        local_stime_error64 = stime_elapsed64;
    1.65 +    if ( curr_local_stime != curr_master_stime )
    1.66 +    {
    1.67 +        local_stime_err = curr_local_stime - curr_master_stime;
    1.68 +        if ( local_stime_err > EPOCH )
    1.69 +            local_stime_err = EPOCH;
    1.70 +        error_factor = div_frac(EPOCH, EPOCH + (u32)local_stime_err);
    1.71 +    }
    1.72  
    1.73      /*
    1.74       * We require 0 < stime_elapsed < 2^31.
    1.75 @@ -513,14 +527,12 @@ static void local_time_calibration(void 
    1.76      while ( ((u32)stime_elapsed64 != stime_elapsed64) ||
    1.77              ((s32)stime_elapsed64 < 0) )
    1.78      {
    1.79 -        stime_elapsed64     >>= 1;
    1.80 -        tsc_elapsed64       >>= 1;
    1.81 -        local_stime_error64 >>= 1;
    1.82 +        stime_elapsed64 >>= 1;
    1.83 +        tsc_elapsed64   >>= 1;
    1.84      }
    1.85  
    1.86 -    /* stime_master_diff (and hence stime_error) now fit in a 32-bit word. */
    1.87 -    stime_elapsed32     = (u32)stime_elapsed64;
    1.88 -    local_stime_error32 = (u32)local_stime_error64;
    1.89 +    /* stime_master_diff now fits in a 32-bit word. */
    1.90 +    stime_elapsed32 = (u32)stime_elapsed64;
    1.91  
    1.92      /* tsc_elapsed <= 2*stime_elapsed */
    1.93      while ( tsc_elapsed64 > (stime_elapsed32 * 2) )
    1.94 @@ -541,21 +553,22 @@ static void local_time_calibration(void 
    1.95          tsc_shift++;
    1.96      }
    1.97  
    1.98 +    calibration_mul_frac = div_frac(stime_elapsed32, tsc_elapsed32);
    1.99 +    if ( error_factor != 0 )
   1.100 +        calibration_mul_frac = mul_frac(calibration_mul_frac, error_factor);
   1.101 +
   1.102  #if 0
   1.103 -    printk("---%d: %08x %d\n", cpu, 
   1.104 -           div_frac(stime_elapsed32 - local_stime_error32, tsc_elapsed32),
   1.105 -           tsc_shift);
   1.106 +    printk("---%d: %08x %d\n", cpu, calibration_mul_frac, tsc_shift);
   1.107  #endif
   1.108  
   1.109      /* Record new timestamp information. */
   1.110 -    cpu_time[cpu].tsc_scale.mul_frac = 
   1.111 -        div_frac(stime_elapsed32 - local_stime_error32, tsc_elapsed32);
   1.112 +    cpu_time[cpu].tsc_scale.mul_frac = calibration_mul_frac;
   1.113      cpu_time[cpu].tsc_scale.shift    = tsc_shift;
   1.114      cpu_time[cpu].local_tsc_stamp    = curr_tsc;
   1.115      cpu_time[cpu].stime_local_stamp  = curr_local_stime;
   1.116      cpu_time[cpu].stime_master_stamp = curr_master_stime;
   1.117  
   1.118 -    set_ac_timer(&cpu_time[cpu].calibration_timer, NOW() + MILLISECS(1000));
   1.119 +    set_ac_timer(&cpu_time[cpu].calibration_timer, NOW() + EPOCH);
   1.120  
   1.121      if ( cpu == 0 )
   1.122          platform_time_calibration();
   1.123 @@ -577,7 +590,7 @@ void init_percpu_time(void)
   1.124  
   1.125      init_ac_timer(&cpu_time[cpu].calibration_timer,
   1.126                    local_time_calibration, NULL, cpu);
   1.127 -    set_ac_timer(&cpu_time[cpu].calibration_timer, NOW() + MILLISECS(1000));
   1.128 +    set_ac_timer(&cpu_time[cpu].calibration_timer, NOW() + EPOCH);
   1.129  }
   1.130  
   1.131  /* Late init function (after all CPUs are booted). */