direct-io.hg

changeset 560:e5bf251a865f

bitkeeper revision 1.259.3.1 (3f0bdfccTmutwO6orDoiZ1_lOqbkAw)

lock system time to RTC
author rneugeba@wyvis.research.intel-research.net
date Wed Jul 09 09:26:36 2003 +0000 (2003-07-09)
parents 970fdf86f98e
children faa66eccb6f3
files BitKeeper/etc/logging_ok xen/arch/i386/time.c
line diff
     1.1 --- a/BitKeeper/etc/logging_ok	Sat Jul 05 14:52:49 2003 +0000
     1.2 +++ b/BitKeeper/etc/logging_ok	Wed Jul 09 09:26:36 2003 +0000
     1.3 @@ -18,6 +18,7 @@ lynx@idefix.cl.cam.ac.uk
     1.4  rgr22@boulderdash.cl.cam.ac.uk
     1.5  rn@wyvis.camb.intel-research.net
     1.6  rn@wyvis.research.intel-research.net
     1.7 +rneugeba@wyvis.research.intel-research.net
     1.8  smh22@boulderdash.cl.cam.ac.uk
     1.9  smh22@labyrinth.cl.cam.ac.uk
    1.10  smh22@uridium.cl.cam.ac.uk
     2.1 --- a/xen/arch/i386/time.c	Sat Jul 05 14:52:49 2003 +0000
     2.2 +++ b/xen/arch/i386/time.c	Wed Jul 09 09:26:36 2003 +0000
     2.3 @@ -185,11 +185,41 @@ mktime (unsigned int year, unsigned int 
     2.4          )*60 + sec; /* finally seconds */
     2.5  }
     2.6  
     2.7 -static unsigned long get_cmos_time(void)
     2.8 +static unsigned long __get_cmos_time(void)
     2.9  {
    2.10      unsigned int year, mon, day, hour, min, sec;
    2.11 +    /* Linux waits here for a the Update-In-Progress (UIP) flag going
    2.12 +     * from 1 to 0. This can take up to a second. This is not acceptable
    2.13 +     * for the use in Xen and this code is therfor removed at the cost
    2.14 +     * of reduced accuracy. */
    2.15 +    sec = CMOS_READ(RTC_SECONDS);
    2.16 +    min = CMOS_READ(RTC_MINUTES);
    2.17 +    hour = CMOS_READ(RTC_HOURS);
    2.18 +    day = CMOS_READ(RTC_DAY_OF_MONTH);
    2.19 +    mon = CMOS_READ(RTC_MONTH);
    2.20 +    year = CMOS_READ(RTC_YEAR);
    2.21 +    
    2.22 +    if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
    2.23 +    {
    2.24 +        BCD_TO_BIN(sec);
    2.25 +        BCD_TO_BIN(min);
    2.26 +        BCD_TO_BIN(hour);
    2.27 +        BCD_TO_BIN(day);
    2.28 +        BCD_TO_BIN(mon);
    2.29 +        BCD_TO_BIN(year);
    2.30 +    }
    2.31 +
    2.32 +    if ((year += 1900) < 1970)
    2.33 +        year += 100;
    2.34 +
    2.35 +    return mktime(year, mon, day, hour, min, sec);
    2.36 +}
    2.37 +
    2.38 +/* the more accurate version waits for a change */
    2.39 +static unsigned long get_cmos_time(void)
    2.40 +{
    2.41 +    unsigned long res;
    2.42      int i;
    2.43 -
    2.44      spin_lock(&rtc_lock);
    2.45      /* The Linux interpretation of the CMOS clock register contents:
    2.46       * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
    2.47 @@ -203,29 +233,10 @@ static unsigned long get_cmos_time(void)
    2.48      for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
    2.49          if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
    2.50              break;
    2.51 -    do { /* Isn't this overkill ? UIP above should guarantee consistency */
    2.52 -        sec = CMOS_READ(RTC_SECONDS);
    2.53 -        min = CMOS_READ(RTC_MINUTES);
    2.54 -        hour = CMOS_READ(RTC_HOURS);
    2.55 -        day = CMOS_READ(RTC_DAY_OF_MONTH);
    2.56 -        mon = CMOS_READ(RTC_MONTH);
    2.57 -        year = CMOS_READ(RTC_YEAR);
    2.58 -    } while (sec != CMOS_READ(RTC_SECONDS));
    2.59 -    if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
    2.60 -    {
    2.61 -        BCD_TO_BIN(sec);
    2.62 -        BCD_TO_BIN(min);
    2.63 -        BCD_TO_BIN(hour);
    2.64 -        BCD_TO_BIN(day);
    2.65 -        BCD_TO_BIN(mon);
    2.66 -        BCD_TO_BIN(year);
    2.67 -    }
    2.68 +    res = __get_cmos_time();
    2.69      spin_unlock(&rtc_lock);
    2.70 -    if ((year += 1900) < 1970)
    2.71 -        year += 100;
    2.72 -    printk(".... CMOS Clock:  %02d/%02d/%04d %02d:%02d:%02d\n",
    2.73 -           day, mon, year, hour, min, sec);
    2.74 -    return mktime(year, mon, day, hour, min, sec);
    2.75 +    return res;
    2.76 +
    2.77  }
    2.78  
    2.79  /***************************************************************************
    2.80 @@ -368,6 +379,64 @@ static void update_time(unsigned long fo
    2.81      add_ac_timer(&update_timer);
    2.82  }
    2.83  
    2.84 +
    2.85 +/*
    2.86 + * VERY crude way to keep system time from drfiting.
    2.87 + * Update the scaling factor using the RTC
    2.88 + * This is done periodically of it's own timer
    2.89 + * We maintain an array of cpu frequencies.
    2.90 + * - index 0 -> go slower
    2.91 + * - index 1 -> frequency as determined during calibration
    2.92 + * - index 2 -> go faster
    2.93 + */
    2.94 +#define UPDATE_PERIOD   SECONDS(50)
    2.95 +static struct ac_timer scale_timer;
    2.96 +static unsigned long   init_cmos_time;
    2.97 +static u64             cpu_freqs[3];
    2.98 +static void update_scale(unsigned long foo)
    2.99 +{
   2.100 +    unsigned long  flags;
   2.101 +    unsigned long  cmos_time;
   2.102 +    s_time_t       now;
   2.103 +    s32            st, ct, dt;
   2.104 +    u64            scale;
   2.105 +    int            freq_index;
   2.106 +
   2.107 +    spin_lock(&rtc_lock);
   2.108 +    cmos_time = __get_cmos_time();
   2.109 +    spin_unlock(&rtc_lock);
   2.110 +
   2.111 +    spin_lock_irqsave(&stime_lock, flags);
   2.112 +    now  = __get_s_time();
   2.113 +
   2.114 +    ct = (cmos_time - init_cmos_time);
   2.115 +    st = (s32)(now/SECONDS(1));
   2.116 +    dt = ct - st;
   2.117 +
   2.118 +    /* work out adjustment to scaling factor. allow +/- 1s drift */
   2.119 +    if (dt < -1) freq_index = 0;       /* go slower */
   2.120 +    else if (dt > 1) freq_index = 2;   /* go faster */
   2.121 +    else freq_index = 1;               /* correct speed */
   2.122 +
   2.123 +    if (dt <= -10 || dt >= 10)
   2.124 +        printk("Large time drift (cmos time - system time = %ds)\n", dt);
   2.125 +
   2.126 +    /* set new frequency  */
   2.127 +    cpu_freq = cpu_freqs[freq_index];
   2.128 +
   2.129 +    /* adjust scaling factor */
   2.130 +    scale = 1000000000LL << 32;
   2.131 +    scale /= cpu_freq;
   2.132 +    st_scale_f = scale & 0xffffffff;
   2.133 +    st_scale_i = scale >> 32;
   2.134 +
   2.135 +    spin_unlock_irqrestore(&stime_lock, flags);
   2.136 +    scale_timer.expires  = now + UPDATE_PERIOD;
   2.137 +    add_ac_timer(&scale_timer);
   2.138 +    TRC(printk(" %ds[%d] ", dt, freq_index));
   2.139 +}
   2.140 +
   2.141 +
   2.142  /***************************************************************************
   2.143   * Init Xeno Time
   2.144   * This has to be done after all CPUs have been booted
   2.145 @@ -376,7 +445,9 @@ int __init init_xeno_time()
   2.146  {
   2.147      int      cpu = smp_processor_id();
   2.148      u32      cpu_cycle;  /* time of one cpu cyle in pico-seconds */
   2.149 -    u64      scale;      /* scale factor  */
   2.150 +    u64      scale;      /* scale factor */
   2.151 +    s64      freq_off;
   2.152 +
   2.153  
   2.154      spin_lock_init(&stime_lock);
   2.155      spin_lock_init(&wctime_lock);
   2.156 @@ -385,15 +456,26 @@ int __init init_xeno_time()
   2.157  
   2.158      /* System Time */
   2.159      cpu_cycle   = (u32) (1000000000LL/cpu_khz); /* in pico seconds */
   2.160 +
   2.161      scale = 1000000000LL << 32;
   2.162      scale /= cpu_freq;
   2.163      st_scale_f = scale & 0xffffffff;
   2.164      st_scale_i = scale >> 32;
   2.165  
   2.166 +    
   2.167 +    /* calculate adjusted frequencies */
   2.168 +    freq_off  = cpu_freq/1000; /* .1%  */
   2.169 +    cpu_freqs[0] = cpu_freq + freq_off;
   2.170 +    cpu_freqs[1] = cpu_freq;
   2.171 +    cpu_freqs[2] = cpu_freq - freq_off;
   2.172 +
   2.173      /* Wall Clock time */
   2.174      wall_clock_time.tv_sec  = get_cmos_time();
   2.175      wall_clock_time.tv_usec = 0;
   2.176  
   2.177 +    /* init cmos_time  for synchronising */
   2.178 +    init_cmos_time = wall_clock_time.tv_sec - 3;
   2.179 +
   2.180      /* set starting times */
   2.181      stime_now = (s_time_t)0;
   2.182      rdtscl(stime_pcc);
   2.183 @@ -404,12 +486,19 @@ int __init init_xeno_time()
   2.184      update_timer.data = 1;
   2.185      update_timer.function = &update_time;
   2.186      update_time(0);
   2.187 + 
   2.188 +    init_ac_timer(&scale_timer, 0);
   2.189 +    scale_timer.data = 4;
   2.190 +    scale_timer.function = &update_scale;
   2.191 +    update_scale(0);
   2.192  
   2.193 -    printk(".... System Time: %lldns\n", NOW());
   2.194 -    printk(".....cpu_cycle:   %u ps\n",  cpu_cycle);
   2.195 -    printk(".... st_scale_f:  %X\n",     st_scale_f);
   2.196 -    printk(".... st_scale_i:  %X\n",     st_scale_i);
   2.197 -    printk(".... stime_pcc:   %u\n",     stime_pcc);
   2.198 +    printk(".... System Time: %lldns\n",   NOW());
   2.199 +    printk(".....cpu_freq:    %08X%08X\n", (u32)(cpu_freq>>32), (u32)cpu_freq);
   2.200 +    printk(".....cpu_cycle:   %u ps\n",    cpu_cycle);
   2.201 +    printk(".....scale:       %08X%08X\n", (u32)(scale>>32), (u32)scale);
   2.202 +    printk(".... st_scale_f:  %X\n",       st_scale_f);
   2.203 +    printk(".... st_scale_i:  %X\n",       st_scale_i);
   2.204 +    printk(".... stime_pcc:   %u\n",       stime_pcc);
   2.205  
   2.206      printk(".... Wall Clock:  %lds %ldus\n", wall_clock_time.tv_sec,
   2.207             wall_clock_time.tv_usec);