ia64/xen-unstable
changeset 657:c82a216f0773
bitkeeper revision 1.372 (3f1d3b4c5vpfm6WgqbVfZVhO04znVw)
time.h, keyhandler.c, ac_timer.c, time.c, nmi.c, apic.c:
Clean ups.
time.h, keyhandler.c, ac_timer.c, time.c, nmi.c, apic.c:
Clean ups.
author | kaf24@scramble.cl.cam.ac.uk |
---|---|
date | Tue Jul 22 13:25:32 2003 +0000 (2003-07-22) |
parents | fb6f05624b37 |
children | 59ad019649a5 |
files | xen/arch/i386/apic.c xen/arch/i386/nmi.c xen/arch/i386/time.c xen/common/ac_timer.c xen/common/keyhandler.c xen/include/asm-i386/time.h |
line diff
1.1 --- a/xen/arch/i386/apic.c Mon Jul 21 15:05:07 2003 +0000 1.2 +++ b/xen/arch/i386/apic.c Tue Jul 22 13:25:32 2003 +0000 1.3 @@ -581,7 +581,7 @@ int __init calibrate_APIC_clock(void) 1.4 int i; 1.5 const int LOOPS = HZ/10; 1.6 1.7 - printk("calibrating APIC timer for CPU%d...\n", smp_processor_id()); 1.8 + printk("Calibrating APIC timer for CPU%d...\n", smp_processor_id()); 1.9 1.10 /* Put whatever arbitrary (but long enough) timeout 1.11 * value into the APIC clock, we just want to get the 1.12 @@ -611,12 +611,12 @@ int __init calibrate_APIC_clock(void) 1.13 result = (tt1-tt2)*APIC_DIVISOR/LOOPS; 1.14 1.15 printk("..... CPU speed is %ld.%04ld MHz.\n", 1.16 - ((long)(t2-t1)/LOOPS)/(1000000/HZ), 1.17 - ((long)(t2-t1)/LOOPS)%(1000000/HZ)); 1.18 + ((long)(t2-t1)/LOOPS) / (1000000/HZ), 1.19 + ((long)(t2-t1)/LOOPS) % (1000000/HZ)); 1.20 1.21 printk("..... Bus speed is %ld.%04ld MHz.\n", 1.22 - result/(1000000/HZ), 1.23 - result%(1000000/HZ)); 1.24 + result / (1000000/HZ), 1.25 + result % (1000000/HZ)); 1.26 1.27 cpu_freq = (u64)(((t2-t1)/LOOPS)*HZ); 1.28 1.29 @@ -625,10 +625,7 @@ int __init calibrate_APIC_clock(void) 1.30 bus_cycle = (u32) (1000000000000LL/bus_freq); /* in pico seconds */ 1.31 bus_scale = (1000*262144)/bus_cycle; 1.32 1.33 - /* print results */ 1.34 - printk("..... bus_freq = %u Hz\n", bus_freq); 1.35 - printk("..... bus_cycle = %u ps\n", bus_cycle); 1.36 - printk("..... bus_scale = %u \n", bus_scale); 1.37 + printk("..... bus_scale = 0x%08X\n", bus_scale); 1.38 /* reset APIC to zero timeout value */ 1.39 __setup_APIC_LVTT(0); 1.40 return result;
2.1 --- a/xen/arch/i386/nmi.c Mon Jul 21 15:05:07 2003 +0000 2.2 +++ b/xen/arch/i386/nmi.c Tue Jul 22 13:25:32 2003 +0000 2.3 @@ -93,29 +93,33 @@ int __init check_nmi_watchdog (void) 2.4 unsigned int prev_nmi_count[NR_CPUS]; 2.5 int j, cpu; 2.6 2.7 - if (!nmi_watchdog) 2.8 + if ( !nmi_watchdog ) 2.9 return 0; 2.10 2.11 - printk("testing NMI watchdog ---\n"); 2.12 + printk("Testing NMI watchdog --- "); 2.13 2.14 - for (j = 0; j < smp_num_cpus; j++) { 2.15 + for ( j = 0; j < smp_num_cpus; j++ ) 2.16 + { 2.17 cpu = cpu_logical_map(j); 2.18 prev_nmi_count[cpu] = irq_stat[cpu].__nmi_count; 2.19 } 2.20 sti(); 2.21 mdelay((10*1000)/nmi_hz); /* wait 10 ticks */ 2.22 2.23 - for (j = 0; j < smp_num_cpus; j++) { 2.24 + for ( j = 0; j < smp_num_cpus; j++ ) 2.25 + { 2.26 cpu = cpu_logical_map(j); 2.27 - if (nmi_count(cpu) - prev_nmi_count[cpu] <= 5) 2.28 - printk("CPU#%d: NMI stuck?\n", cpu); 2.29 + if ( nmi_count(cpu) - prev_nmi_count[cpu] <= 5 ) 2.30 + printk("CPU#%d stuck. ", cpu); 2.31 else 2.32 - printk("CPU#%d: NMI okay\n", cpu); 2.33 + printk("CPU#%d okay. ", cpu); 2.34 } 2.35 2.36 + printk("\n"); 2.37 + 2.38 /* now that we know it works we can reduce NMI frequency to 2.39 something more reasonable; makes a difference in some configs */ 2.40 - if (nmi_watchdog == NMI_LOCAL_APIC) 2.41 + if ( nmi_watchdog == NMI_LOCAL_APIC ) 2.42 nmi_hz = 1; 2.43 2.44 return 0; 2.45 @@ -132,8 +136,7 @@ static inline void nmi_pm_init(void) { } 2.46 static void __pminit clear_msr_range(unsigned int base, unsigned int n) 2.47 { 2.48 unsigned int i; 2.49 - 2.50 - for(i = 0; i < n; ++i) 2.51 + for ( i = 0; i < n; i++ ) 2.52 wrmsr(base+i, 0, 0); 2.53 } 2.54
3.1 --- a/xen/arch/i386/time.c Mon Jul 21 15:05:07 2003 +0000 3.2 +++ b/xen/arch/i386/time.c Tue Jul 22 13:25:32 2003 +0000 3.3 @@ -1,22 +1,16 @@ 3.4 /* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- 3.5 **************************************************************************** 3.6 - * (C) 2002 - Rolf Neugebauer - Intel Research Cambridge 3.7 + * (C) 2002-2003 - Rolf Neugebauer - Intel Research Cambridge 3.8 + * (C) 2002-2003 University of Cambridge 3.9 **************************************************************************** 3.10 * 3.11 * File: i386/time.c 3.12 - * Author: 3.13 - * Changes: 3.14 - * 3.15 - * Date: Jan 2003 3.16 + * Author: Rolf Neugebar & Keir Fraser 3.17 * 3.18 * Environment: Xen Hypervisor 3.19 * Description: modified version of Linux' time.c 3.20 * implements system and wall clock time. 3.21 * based on freebsd's implementation. 3.22 - * 3.23 - **************************************************************************** 3.24 - * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $ 3.25 - **************************************************************************** 3.26 */ 3.27 3.28 /* 3.29 @@ -49,27 +43,47 @@ 3.30 #define TRC(_x) 3.31 #endif 3.32 3.33 +/* GLOBALS */ 3.34 + 3.35 unsigned long cpu_khz; /* Detected as we calibrate the TSC */ 3.36 unsigned long ticks_per_usec; /* TSC ticks per microsecond. */ 3.37 +spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; 3.38 +int timer_ack = 0; 3.39 3.40 -/* We use this to prevent overflow of 31-bit RDTSC "diffs". */ 3.41 -static unsigned int rdtsc_bitshift; 3.42 +/* PRIVATE */ 3.43 3.44 -spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; 3.45 +static unsigned int rdtsc_bitshift; /* Which 32 bits of TSC do we use? */ 3.46 +static unsigned long init_cmos_time; /* RTC time when system time == 0 */ 3.47 +static u64 cpu_freqs[3]; /* Slow/correct/fast CPU freqs */ 3.48 +static u32 st_scale_f; /* Cycles -> ns, fractional part */ 3.49 +static u32 st_scale_i; /* Cycles -> ns, integer part */ 3.50 +static struct ac_timer update_timer; /* Periodic 'time update' function */ 3.51 +static spinlock_t stime_lock; /* Lock for accessing sys & wc time */ 3.52 +struct timeval wall_clock_time; /* WC time at last 'time update' */ 3.53 +static u32 tsc_irq; /* CPU0's TSC at last 'time update' */ 3.54 +static s_time_t stime_irq; /* System time at last 'time update' */ 3.55 3.56 -int timer_ack=0; 3.57 -extern spinlock_t i8259A_lock; 3.58 -static inline void do_timer_interrupt(int irq, 3.59 - void *dev_id, struct pt_regs *regs) 3.60 +/* 3.61 + * The scale update period is not a whole number of seconds since we want to 3.62 + * avoid being in sync with the CMOS update-in-progress flag. 3.63 + */ 3.64 +#define SCALE_UPDATE_PERIOD MILLISECS(50200) 3.65 +#define TIME_UPDATE_PERIOD MILLISECS(200) 3.66 + 3.67 + 3.68 +static inline void do_timer_interrupt( 3.69 + int irq, void *dev_id, struct pt_regs *regs) 3.70 { 3.71 #ifdef CONFIG_X86_IO_APIC 3.72 - if (timer_ack) { 3.73 + if ( timer_ack ) 3.74 + { 3.75 /* 3.76 * Subtle, when I/O APICs are used we have to ack timer IRQ manually 3.77 * to reset the IRR bit for do_slow_gettimeoffset(). This will also 3.78 * deassert NMI lines for the watchdog if run on an 82489DX-based 3.79 * system. 3.80 */ 3.81 + extern spinlock_t i8259A_lock; 3.82 spin_lock(&i8259A_lock); 3.83 outb(0x0c, 0x20); 3.84 /* Ack the IRQ; AEOI will end it automatically. */ 3.85 @@ -102,6 +116,8 @@ static struct irqaction irq0 = { timer_ 3.86 3.87 static unsigned long __init calibrate_tsc(void) 3.88 { 3.89 + unsigned long startlow, starthigh, endlow, endhigh, count; 3.90 + 3.91 /* Set the Gate high, disable speaker */ 3.92 outb((inb(0x61) & ~0x02) | 0x01, 0x61); 3.93 3.94 @@ -116,43 +132,24 @@ static unsigned long __init calibrate_ts 3.95 outb(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */ 3.96 outb(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */ 3.97 3.98 - { 3.99 - unsigned long startlow, starthigh; 3.100 - unsigned long endlow, endhigh; 3.101 - unsigned long count; 3.102 + rdtsc(startlow, starthigh); 3.103 + for ( count = 0; (inb(0x61) & 0x20) == 0; count++ ) 3.104 + continue; 3.105 + rdtsc(endlow, endhigh); 3.106 3.107 - rdtsc(startlow,starthigh); 3.108 - count = 0; 3.109 - do { 3.110 - count++; 3.111 - } while ((inb(0x61) & 0x20) == 0); 3.112 - rdtsc(endlow,endhigh); 3.113 - 3.114 - /* Error: ECTCNEVERSET */ 3.115 - if (count <= 1) 3.116 - goto bad_ctc; 3.117 + /* Error if the CTC doesn't behave itself. */ 3.118 + if ( count == 0 ) 3.119 + return 0; 3.120 3.121 - /* 64-bit subtract - gcc just messes up with long longs */ 3.122 - __asm__("subl %2,%0\n\t" 3.123 - "sbbl %3,%1" 3.124 - :"=a" (endlow), "=d" (endhigh) 3.125 - :"g" (startlow), "g" (starthigh), 3.126 - "0" (endlow), "1" (endhigh)); 3.127 - 3.128 - /* Error: ECPUTOOFAST */ 3.129 - if (endhigh) 3.130 - goto bad_ctc; 3.131 + /* [endhigh:endlow] = [endhigh:endlow] - [starthigh:startlow] */ 3.132 + __asm__( "subl %2,%0 ; sbbl %3,%1" 3.133 + : "=a" (endlow), "=d" (endhigh) 3.134 + : "g" (startlow), "g" (starthigh), "0" (endlow), "1" (endhigh) ); 3.135 3.136 - return endlow; 3.137 - } 3.138 + /* If quotient doesn't fit in 32 bits then we return error (zero). */ 3.139 + return endhigh ? 0 : endlow; 3.140 +} 3.141 3.142 - /* 3.143 - * The CTC wasn't reliable: we got a hit on the very first read, or the CPU 3.144 - * was so fast/slow that the quotient wouldn't fit in 32 bits.. 3.145 - */ 3.146 - bad_ctc: 3.147 - return 0; 3.148 -} 3.149 3.150 /*************************************************************************** 3.151 * CMOS Timer functions 3.152 @@ -178,32 +175,32 @@ mktime (unsigned int year, unsigned int 3.153 unsigned int day, unsigned int hour, 3.154 unsigned int min, unsigned int sec) 3.155 { 3.156 - if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */ 3.157 - mon += 12; /* Puts Feb last since it has leap day */ 3.158 + /* 1..12 -> 11,12,1..10: put Feb last since it has a leap day. */ 3.159 + if ( 0 >= (int) (mon -= 2) ) 3.160 + { 3.161 + mon += 12; 3.162 year -= 1; 3.163 } 3.164 + 3.165 return ((((unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day)+ 3.166 year*365 - 719499 3.167 )*24 + hour /* now have hours */ 3.168 - )*60 + min /* now have minutes */ 3.169 + )*60 + min /* now have minutes */ 3.170 )*60 + sec; /* finally seconds */ 3.171 } 3.172 3.173 static unsigned long __get_cmos_time(void) 3.174 { 3.175 unsigned int year, mon, day, hour, min, sec; 3.176 - /* Linux waits here for a the Update-In-Progress (UIP) flag going 3.177 - * from 1 to 0. This can take up to a second. This is not acceptable 3.178 - * for the use in Xen and this code is therfor removed at the cost 3.179 - * of reduced accuracy. */ 3.180 - sec = CMOS_READ(RTC_SECONDS); 3.181 - min = CMOS_READ(RTC_MINUTES); 3.182 + 3.183 + sec = CMOS_READ(RTC_SECONDS); 3.184 + min = CMOS_READ(RTC_MINUTES); 3.185 hour = CMOS_READ(RTC_HOURS); 3.186 - day = CMOS_READ(RTC_DAY_OF_MONTH); 3.187 - mon = CMOS_READ(RTC_MONTH); 3.188 + day = CMOS_READ(RTC_DAY_OF_MONTH); 3.189 + mon = CMOS_READ(RTC_MONTH); 3.190 year = CMOS_READ(RTC_YEAR); 3.191 3.192 - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) 3.193 + if ( !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD ) 3.194 { 3.195 BCD_TO_BIN(sec); 3.196 BCD_TO_BIN(min); 3.197 @@ -213,7 +210,7 @@ static unsigned long __get_cmos_time(voi 3.198 BCD_TO_BIN(year); 3.199 } 3.200 3.201 - if ((year += 1900) < 1970) 3.202 + if ( (year += 1900) < 1970 ) 3.203 year += 100; 3.204 3.205 return mktime(year, mon, day, hour, min, sec); 3.206 @@ -239,42 +236,33 @@ static unsigned long maybe_get_cmos_time 3.207 return retval; 3.208 } 3.209 3.210 -/* the more accurate version waits for a change */ 3.211 +/* This version spins until it definitely reads a valid time from CMOS RAM. */ 3.212 static unsigned long get_cmos_time(void) 3.213 { 3.214 unsigned long res, flags; 3.215 int i; 3.216 3.217 spin_lock_irqsave(&rtc_lock, flags); 3.218 - /* The Linux interpretation of the CMOS clock register contents: 3.219 - * When the Update-In-Progress (UIP) flag goes from 1 to 0, the 3.220 - * RTC registers show the second which has precisely just started. 3.221 - * Let's hope other operating systems interpret the RTC the same way. 3.222 - */ 3.223 + 3.224 /* read RTC exactly on falling edge of update flag */ 3.225 - for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ 3.226 - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) 3.227 + for ( i = 0 ; i < 1000000 ; i++ ) /* may take up to 1 second... */ 3.228 + if ( (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) ) 3.229 break; 3.230 - for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ 3.231 - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) 3.232 + for ( i = 0 ; i < 1000000 ; i++ ) /* must try at least 2.228 ms */ 3.233 + if ( !(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) ) 3.234 break; 3.235 + 3.236 res = __get_cmos_time(); 3.237 + 3.238 spin_unlock_irqrestore(&rtc_lock, flags); 3.239 return res; 3.240 } 3.241 3.242 + 3.243 /*************************************************************************** 3.244 - * Time 3.245 - * XXX RN: Will be able to remove some of the locking once the time is 3.246 - * update by the APIC on only one CPU. 3.247 + * System Time 3.248 ***************************************************************************/ 3.249 3.250 -static spinlock_t stime_lock; 3.251 -static u32 st_scale_f; 3.252 -static u32 st_scale_i; 3.253 -u32 stime_pcc; /* cycle counter value at last timer irq */ 3.254 -s_time_t stime_now; /* time in ns at last timer IRQ */ 3.255 - 3.256 static inline s_time_t __get_s_time(void) 3.257 { 3.258 s32 delta_tsc; 3.259 @@ -283,13 +271,13 @@ static inline s_time_t __get_s_time(void 3.260 3.261 rdtscll(tsc); 3.262 low = (u32)(tsc >> rdtsc_bitshift); 3.263 - delta_tsc = (s32)(low - stime_pcc); 3.264 + delta_tsc = (s32)(low - tsc_irq); 3.265 if ( unlikely(delta_tsc < 0) ) delta_tsc = 0; 3.266 delta = ((u64)delta_tsc * st_scale_f); 3.267 delta >>= 32; 3.268 delta += ((u64)delta_tsc * st_scale_i); 3.269 3.270 - return stime_now + delta; 3.271 + return stime_irq + delta; 3.272 } 3.273 3.274 s_time_t get_s_time(void) 3.275 @@ -303,25 +291,23 @@ s_time_t get_s_time(void) 3.276 } 3.277 3.278 3.279 -/* Wall Clock time */ 3.280 -struct timeval wall_clock_time; /* wall clock time at last update */ 3.281 -s_time_t wctime_st; /* system time at last update */ 3.282 - 3.283 void do_gettimeofday(struct timeval *tv) 3.284 { 3.285 unsigned long flags; 3.286 unsigned long usec, sec; 3.287 3.288 spin_lock_irqsave(&stime_lock, flags); 3.289 - usec = ((unsigned long)(__get_s_time() - wctime_st))/1000; 3.290 + usec = ((unsigned long)(__get_s_time() - stime_irq))/1000; 3.291 sec = wall_clock_time.tv_sec; 3.292 usec += wall_clock_time.tv_usec; 3.293 spin_unlock_irqrestore(&stime_lock, flags); 3.294 3.295 - while (usec >= 1000000) { 3.296 + while ( usec >= 1000000 ) 3.297 + { 3.298 usec -= 1000000; 3.299 sec++; 3.300 } 3.301 + 3.302 tv->tv_sec = sec; 3.303 tv->tv_usec = usec; 3.304 } 3.305 @@ -331,11 +317,11 @@ void do_settimeofday(struct timeval *tv) 3.306 printk("XXX: do_settimeofday not implemented\n"); 3.307 } 3.308 3.309 + 3.310 /*************************************************************************** 3.311 * Update times 3.312 ***************************************************************************/ 3.313 3.314 -/* update a domains notion of time */ 3.315 void update_dom_time(shared_info_t *si) 3.316 { 3.317 unsigned long flags; 3.318 @@ -343,15 +329,13 @@ void update_dom_time(shared_info_t *si) 3.319 spin_lock_irqsave(&stime_lock, flags); 3.320 si->cpu_freq = cpu_freq; 3.321 si->rdtsc_bitshift = rdtsc_bitshift; 3.322 - si->system_time = stime_now; 3.323 - si->st_timestamp = stime_pcc; 3.324 + si->system_time = stime_irq; 3.325 + si->st_timestamp = tsc_irq; 3.326 si->tv_sec = wall_clock_time.tv_sec; 3.327 si->tv_usec = wall_clock_time.tv_usec; 3.328 - si->wc_timestamp = wctime_st; 3.329 + si->wc_timestamp = stime_irq; 3.330 si->wc_version++; 3.331 spin_unlock_irqrestore(&stime_lock, flags); 3.332 - 3.333 - TRC(printk(" 0x%08X%08X\n", (u32)(wctime_st>>32), (u32)wctime_st)); 3.334 } 3.335 3.336 /* 3.337 @@ -362,21 +346,12 @@ void update_dom_time(shared_info_t *si) 3.338 * - index 0 -> go slower 3.339 * - index 1 -> frequency as determined during calibration 3.340 * - index 2 -> go faster 3.341 - */ 3.342 -/* 3.343 - * NB. The period is not a whole number of seconds since we want to avoid 3.344 - * being in sync with the CMOS update-in-progress flag, which causes this 3.345 - * routine to bail. 3.346 - */ 3.347 -/* 3.348 + * 3.349 * NB2. Note that update_scale is called from update_time with the stime_lock 3.350 * still held. This is because we must only slow down cpu_freq at a timebase 3.351 * change. If we did it in the middle of an update period then time would 3.352 * seem to jump backwards since BASE+OLD_FREQ*DIFF > BASE+NEW_FREQ*DIFF. 3.353 */ 3.354 -#define SCALE_UPDATE_PERIOD MILLISECS(50200) 3.355 -static unsigned long init_cmos_time; 3.356 -static u64 cpu_freqs[3]; 3.357 static void update_scale(void) 3.358 { 3.359 unsigned long cmos_time; 3.360 @@ -389,15 +364,18 @@ static void update_scale(void) 3.361 return; 3.362 3.363 ct = (u32)(cmos_time - init_cmos_time); 3.364 - st = (u32)(stime_now/SECONDS(1)); 3.365 + st = (u32)(stime_irq/SECONDS(1)); 3.366 dt = (s32)(ct - st); 3.367 3.368 - /* work out adjustment to scaling factor. allow +/- 1s drift */ 3.369 - if (dt < -1) freq_index = 0; /* go slower */ 3.370 - else if (dt > 1) freq_index = 2; /* go faster */ 3.371 - else freq_index = 1; /* correct speed */ 3.372 + /* Work out adjustment to scaling factor. Allow +/- 1s drift. */ 3.373 + if ( dt < -1 ) 3.374 + freq_index = 0; /* go slower */ 3.375 + else if ( dt > 1 ) 3.376 + freq_index = 2; /* go faster */ 3.377 + else 3.378 + freq_index = 1; /* correct speed */ 3.379 3.380 - if ((dt <= -10) || (dt >= 10)) 3.381 + if ( (dt <= -10) || (dt >= 10) ) 3.382 printk("Large time drift (cmos time - system time = %ds)\n", dt); 3.383 3.384 /* set new frequency */ 3.385 @@ -411,36 +389,32 @@ static void update_scale(void) 3.386 } 3.387 3.388 3.389 -/* 3.390 - * Update hypervisors notion of time 3.391 - * This is done periodically of it's own timer 3.392 - */ 3.393 -#define TIME_UPDATE_PERIOD MILLISECS(200) 3.394 -static struct ac_timer update_timer; 3.395 -static void update_time(unsigned long foo) 3.396 +static void update_time(unsigned long unused) 3.397 { 3.398 unsigned long flags; 3.399 s_time_t new_st; 3.400 unsigned long usec; 3.401 - u64 full_pcc; 3.402 + u64 full_tsc; 3.403 static int calls_since_scale_update = 0; 3.404 3.405 spin_lock_irqsave(&stime_lock, flags); 3.406 3.407 - /* Update system time. */ 3.408 - stime_now = new_st = __get_s_time(); 3.409 - rdtscll(full_pcc); 3.410 - stime_pcc = (u32)(full_pcc >> rdtsc_bitshift); 3.411 + rdtscll(full_tsc); 3.412 + new_st = __get_s_time(); 3.413 3.414 /* Update wall clock time. */ 3.415 - usec = ((unsigned long)(new_st - wctime_st))/1000; 3.416 + usec = ((unsigned long)(new_st - stime_irq))/1000; 3.417 usec += wall_clock_time.tv_usec; 3.418 - while (usec >= 1000000) { 3.419 + while ( usec >= 1000000 ) 3.420 + { 3.421 usec -= 1000000; 3.422 wall_clock_time.tv_sec++; 3.423 } 3.424 wall_clock_time.tv_usec = usec; 3.425 - wctime_st = new_st; 3.426 + 3.427 + /* Update system time. */ 3.428 + stime_irq = new_st; 3.429 + tsc_irq = (u32)(full_tsc >> rdtsc_bitshift); 3.430 3.431 /* Maybe update our rate to be in sync with the RTC. */ 3.432 if ( ++calls_since_scale_update >= 3.433 @@ -452,8 +426,8 @@ static void update_time(unsigned long fo 3.434 3.435 spin_unlock_irqrestore(&stime_lock, flags); 3.436 3.437 - TRC(printk("TIME[%02d] update time: stime_now=%lld now=%lld,wct=%ld:%ld\n", 3.438 - smp_processor_id(), stime_now, new_st, wall_clock_time.tv_sec, 3.439 + TRC(printk("TIME[%02d] update time: stime_irq=%lld now=%lld,wct=%ld:%ld\n", 3.440 + smp_processor_id(), stime_irq, new_st, wall_clock_time.tv_sec, 3.441 wall_clock_time.tv_usec)); 3.442 3.443 /* Reload the timer. */ 3.444 @@ -462,17 +436,12 @@ static void update_time(unsigned long fo 3.445 } 3.446 3.447 3.448 -/*************************************************************************** 3.449 - * Init Xeno Time 3.450 - * This has to be done after all CPUs have been booted 3.451 - ***************************************************************************/ 3.452 +/* Late init function (after all CPUs are booted). */ 3.453 int __init init_xeno_time() 3.454 { 3.455 - int cpu = smp_processor_id(); 3.456 - u32 cpu_cycle; /* time of one cpu cyle in pico-seconds */ 3.457 - u64 scale; /* scale factor */ 3.458 + u64 scale; 3.459 s64 freq_off; 3.460 - u64 full_pcc; 3.461 + u64 full_tsc; 3.462 unsigned int cpu_ghz; 3.463 3.464 spin_lock_init(&stime_lock); 3.465 @@ -481,61 +450,47 @@ int __init init_xeno_time() 3.466 for ( rdtsc_bitshift = 0; cpu_ghz != 0; rdtsc_bitshift++, cpu_ghz >>= 1 ) 3.467 continue; 3.468 3.469 - printk("Init Time[%02d]: %u\n", cpu, rdtsc_bitshift); 3.470 - 3.471 - /* System Time */ 3.472 - cpu_cycle = (u32) (1000000000LL/cpu_khz); /* in pico seconds */ 3.473 - 3.474 - /* calculate adjusted frequencies */ 3.475 - freq_off = cpu_freq/1000; /* .1% */ 3.476 + /* Calculate adjusted frequencies: +/- 0.1% */ 3.477 + freq_off = cpu_freq/1000; 3.478 cpu_freqs[0] = cpu_freq + freq_off; 3.479 cpu_freqs[1] = cpu_freq; 3.480 cpu_freqs[2] = cpu_freq - freq_off; 3.481 3.482 - scale = 1000000000LL << (32 + rdtsc_bitshift); 3.483 + scale = 1000000000LL << (32 + rdtsc_bitshift); 3.484 scale /= cpu_freq; 3.485 st_scale_f = scale & 0xffffffff; 3.486 st_scale_i = scale >> 32; 3.487 3.488 - /* Wall Clock time */ 3.489 - wall_clock_time.tv_sec = get_cmos_time(); 3.490 + /* System time ticks from zero. */ 3.491 + rdtscll(full_tsc); 3.492 + stime_irq = (s_time_t)0; 3.493 + tsc_irq = (u32)(full_tsc >> rdtsc_bitshift); 3.494 + 3.495 + /* Wallclock time starts as the initial RTC time. */ 3.496 + wall_clock_time.tv_sec = init_cmos_time = get_cmos_time(); 3.497 wall_clock_time.tv_usec = 0; 3.498 3.499 - /* init cmos_time for synchronising */ 3.500 - init_cmos_time = wall_clock_time.tv_sec; 3.501 - 3.502 - /* set starting times */ 3.503 - stime_now = (s_time_t)0; 3.504 - rdtscll(full_pcc); 3.505 - stime_pcc = (u32)(full_pcc >> rdtsc_bitshift); 3.506 - wctime_st = NOW(); 3.507 - 3.508 - /* start timer to update time periodically */ 3.509 + /* Start timer to periodically update time and frequency scale. */ 3.510 init_ac_timer(&update_timer, 0); 3.511 update_timer.data = 1; 3.512 update_timer.function = &update_time; 3.513 update_time(0); 3.514 3.515 - printk(".... System Time: %lldns\n", NOW()); 3.516 - printk(".....cpu_freq: %08X%08X\n", (u32)(cpu_freq>>32), (u32)cpu_freq); 3.517 - printk(".....cpu_cycle: %u ps\n", cpu_cycle); 3.518 - printk(".....scale: %08X%08X\n", (u32)(scale>>32), (u32)scale); 3.519 - printk(".... st_scale_f: %X\n", st_scale_f); 3.520 - printk(".... st_scale_i: %X\n", st_scale_i); 3.521 - printk(".... stime_pcc: %u\n", stime_pcc); 3.522 - 3.523 - printk(".... Wall Clock: %lds %ldus\n", wall_clock_time.tv_sec, 3.524 - wall_clock_time.tv_usec); 3.525 - printk(".... wctime_st: %lld\n", wctime_st); 3.526 + printk("Time init:\n"); 3.527 + printk(".... System Time: %lldns\n", 3.528 + NOW()); 3.529 + printk(".... cpu_freq: %08X:%08X\n", 3.530 + (u32)(cpu_freq>>32), (u32)cpu_freq); 3.531 + printk(".... scale: %08X:%08X\n", 3.532 + (u32)(scale>>32), (u32)scale); 3.533 + printk(".... Wall Clock: %lds %ldus\n", 3.534 + wall_clock_time.tv_sec, wall_clock_time.tv_usec); 3.535 3.536 return 0; 3.537 } 3.538 3.539 3.540 -/*************************************************************************** 3.541 - * Init 3.542 - ***************************************************************************/ 3.543 - 3.544 +/* Early init function. */ 3.545 void __init time_init(void) 3.546 { 3.547 unsigned long ticks_per_frac = calibrate_tsc();
4.1 --- a/xen/common/ac_timer.c Mon Jul 21 15:05:07 2003 +0000 4.2 +++ b/xen/common/ac_timer.c Tue Jul 22 13:25:32 2003 +0000 4.3 @@ -1,20 +1,15 @@ 4.4 /* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- 4.5 **************************************************************************** 4.6 - * (C) 2002 - Rolf Neugebauer - Intel Research Cambridge 4.7 + * (C) 2002-2003 - Rolf Neugebauer - Intel Research Cambridge 4.8 + * (C) 2002-2003 University of Cambridge 4.9 **************************************************************************** 4.10 * 4.11 * File: ac_timer.c 4.12 * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk) 4.13 - * Changes: 4.14 + * Keir Fraser (kaf24@cl.cam.ac.uk) 4.15 * 4.16 - * Date: Nov 2002 4.17 - * 4.18 * Environment: Xen Hypervisor 4.19 * Description: Accurate timer for the Hypervisor 4.20 - * 4.21 - **************************************************************************** 4.22 - * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $ 4.23 - **************************************************************************** 4.24 */ 4.25 4.26 #include <xeno/config.h> 4.27 @@ -38,10 +33,10 @@ 4.28 #define TRC(_x) 4.29 #endif 4.30 4.31 -/***************************************************************************** 4.32 +/* 4.33 * We pull handlers off the timer list this far in future, 4.34 * rather than reprogramming the time hardware. 4.35 - *****************************************************************************/ 4.36 + */ 4.37 #define TIMER_SLOP (50*1000) /* ns */ 4.38 4.39 /* A timer list per CPU */ 4.40 @@ -65,24 +60,29 @@ static inline unsigned long __add_ac_tim 4.41 /* 4.42 * Add timer to the list. If it gets added to the front we schedule 4.43 * a softirq. This will reprogram the timer, or handle the timer event 4.44 - * imemdiately, depending on whether alarm is sufficiently ahead in the 4.45 + * immediately, depending on whether alarm is sufficiently ahead in the 4.46 * future. 4.47 */ 4.48 - if (list_empty(&ac_timers[cpu].timers)) { 4.49 + if ( list_empty(&ac_timers[cpu].timers) ) 4.50 + { 4.51 list_add(&timer->timer_list, &ac_timers[cpu].timers); 4.52 goto send_softirq; 4.53 - } else { 4.54 + } 4.55 + else 4.56 + { 4.57 struct list_head *pos; 4.58 struct ac_timer *t; 4.59 4.60 - list_for_each(pos, &ac_timers[cpu].timers) { 4.61 + list_for_each ( pos, &ac_timers[cpu].timers ) 4.62 + { 4.63 t = list_entry(pos, struct ac_timer, timer_list); 4.64 - if (t->expires > timer->expires) 4.65 + if ( t->expires > timer->expires ) 4.66 break; 4.67 } 4.68 + 4.69 list_add(&(timer->timer_list), pos->prev); 4.70 4.71 - if (timer->timer_list.prev == &ac_timers[cpu].timers) 4.72 + if ( timer->timer_list.prev == &ac_timers[cpu].timers ) 4.73 goto send_softirq; 4.74 } 4.75 4.76 @@ -104,7 +104,8 @@ void add_ac_timer(struct ac_timer *timer 4.77 cpu_mask = __add_ac_timer(timer); 4.78 spin_unlock_irqrestore(&ac_timers[cpu].lock, flags); 4.79 4.80 - if ( cpu_mask ) smp_send_event_check_mask(cpu_mask); 4.81 + if ( cpu_mask ) 4.82 + smp_send_event_check_mask(cpu_mask); 4.83 } 4.84 4.85 4.86 @@ -135,11 +136,15 @@ static inline unsigned long __rem_ac_tim 4.87 4.88 detach_ac_timer(timer); 4.89 4.90 - if (timer->timer_list.prev == &ac_timers[cpu].timers) { 4.91 + if ( timer->timer_list.prev == &ac_timers[cpu].timers ) 4.92 + { 4.93 /* just removed the head */ 4.94 - if (list_empty(&ac_timers[cpu].timers)) { 4.95 + if ( list_empty(&ac_timers[cpu].timers) ) 4.96 + { 4.97 goto send_softirq; 4.98 - } else { 4.99 + } 4.100 + else 4.101 + { 4.102 timer = list_entry(ac_timers[cpu].timers.next, 4.103 struct ac_timer, timer_list); 4.104 if ( timer->expires > (NOW() + TIMER_SLOP) ) 4.105 @@ -165,7 +170,8 @@ void rem_ac_timer(struct ac_timer *timer 4.106 cpu_mask = __rem_ac_timer(timer); 4.107 spin_unlock_irqrestore(&ac_timers[cpu].lock, flags); 4.108 4.109 - if ( cpu_mask ) smp_send_event_check_mask(cpu_mask); 4.110 + if ( cpu_mask ) 4.111 + smp_send_event_check_mask(cpu_mask); 4.112 } 4.113 4.114 4.115 @@ -192,7 +198,8 @@ void mod_ac_timer(struct ac_timer *timer 4.116 4.117 spin_unlock_irqrestore(&ac_timers[cpu].lock, flags); 4.118 4.119 - if ( cpu_mask ) smp_send_event_check_mask(cpu_mask); 4.120 + if ( cpu_mask ) 4.121 + smp_send_event_check_mask(cpu_mask); 4.122 } 4.123 4.124 4.125 @@ -214,25 +221,31 @@ void do_ac_timer(void) 4.126 TRC(printk("ACT [%02d] do(): now=%lld\n", cpu, NOW())); 4.127 4.128 /* Sanity: is the timer list empty? */ 4.129 - if ( list_empty(&ac_timers[cpu].timers) ) goto out; 4.130 + if ( list_empty(&ac_timers[cpu].timers) ) 4.131 + goto out; 4.132 4.133 /* Handle all timeouts in the near future. */ 4.134 while ( !list_empty(&ac_timers[cpu].timers) ) 4.135 { 4.136 t = list_entry(ac_timers[cpu].timers.next,struct ac_timer, timer_list); 4.137 - if ( t->expires > (NOW() + TIMER_SLOP) ) break; 4.138 + if ( t->expires > (NOW() + TIMER_SLOP) ) 4.139 + break; 4.140 4.141 ASSERT(t->cpu == cpu); 4.142 4.143 - /* do some stats */ 4.144 + /* Do some stats collection. */ 4.145 diff = (now - t->expires); 4.146 - if (diff > 0x7fffffff) diff = 0x7fffffff; /* THIS IS BAD! */ 4.147 + if ( diff > 0x7fffffff ) 4.148 + diff = 0x7fffffff; /* THIS IS BAD! */ 4.149 max = perfc_valuea(ac_timer_max, cpu); 4.150 - if (diff > max) perfc_seta(ac_timer_max, cpu, diff); 4.151 + if ( diff > max ) 4.152 + perfc_seta(ac_timer_max, cpu, diff); 4.153 4.154 detach_ac_timer(t); 4.155 + 4.156 spin_unlock_irqrestore(&ac_timers[cpu].lock, flags); 4.157 - if ( t->function != NULL ) t->function(t->data); 4.158 + if ( t->function != NULL ) 4.159 + t->function(t->data); 4.160 spin_lock_irqsave(&ac_timers[cpu].lock, flags); 4.161 } 4.162 4.163 @@ -246,7 +259,9 @@ void do_ac_timer(void) 4.164 TRC(printk("ACT [%02d] do(): again\n", cpu)); 4.165 goto do_timer_again; 4.166 } 4.167 - } else { 4.168 + } 4.169 + else 4.170 + { 4.171 reprogram_ac_timer((s_time_t) 0); 4.172 } 4.173 4.174 @@ -288,10 +303,7 @@ static void ac_timer_softirq_action(stru 4.175 } 4.176 } 4.177 4.178 -/***************************************************************************** 4.179 - * debug dump_queue 4.180 - * arguments: queue head, name of queue 4.181 - *****************************************************************************/ 4.182 + 4.183 static void dump_tqueue(struct list_head *queue, char *name) 4.184 { 4.185 struct list_head *list; 4.186 @@ -300,7 +312,9 @@ static void dump_tqueue(struct list_head 4.187 4.188 printk ("QUEUE %s %lx n: %lx, p: %lx\n", name, (unsigned long)queue, 4.189 (unsigned long) queue->next, (unsigned long) queue->prev); 4.190 - list_for_each (list, queue) { 4.191 + 4.192 + list_for_each ( list, queue ) 4.193 + { 4.194 t = list_entry(list, struct ac_timer, timer_list); 4.195 printk (" %s %d : %lx ex=0x%08X%08X %lu n: %lx, p: %lx\n", 4.196 name, loop++, 4.197 @@ -308,10 +322,10 @@ static void dump_tqueue(struct list_head 4.198 (u32)(t->expires>>32), (u32)t->expires, t->data, 4.199 (unsigned long)list->next, (unsigned long)list->prev); 4.200 } 4.201 - return; 4.202 } 4.203 4.204 -void dump_timerq(u_char key, void *dev_id, struct pt_regs *regs) 4.205 + 4.206 +static void dump_timerq(u_char key, void *dev_id, struct pt_regs *regs) 4.207 { 4.208 u_long flags; 4.209 s_time_t now = NOW(); 4.210 @@ -319,14 +333,15 @@ void dump_timerq(u_char key, void *dev_i 4.211 4.212 printk("Dumping ac_timer queues: NOW=0x%08X%08X\n", 4.213 (u32)(now>>32), (u32)now); 4.214 - for (i = 0; i < smp_num_cpus; i++) { 4.215 + 4.216 + for ( i = 0; i < smp_num_cpus; i++ ) 4.217 + { 4.218 printk("CPU[%02d] ", i); 4.219 spin_lock_irqsave(&ac_timers[i].lock, flags); 4.220 dump_tqueue(&ac_timers[i].timers, "ac_time"); 4.221 spin_unlock_irqrestore(&ac_timers[i].lock, flags); 4.222 printk("\n"); 4.223 } 4.224 - return; 4.225 } 4.226 4.227 4.228 @@ -343,52 +358,6 @@ void __init ac_timer_init(void) 4.229 INIT_LIST_HEAD(&ac_timers[i].timers); 4.230 spin_lock_init(&ac_timers[i].lock); 4.231 } 4.232 + 4.233 + add_key_handler('a', dump_timerq, "dump ac_timer queues"); 4.234 } 4.235 - 4.236 - 4.237 -/***************************************************************************** 4.238 - * GRAVEYARD 4.239 - *****************************************************************************/ 4.240 - 4.241 -#if 0 4.242 - 4.243 -#ifdef AC_TIMER_STATS 4.244 -#define BUCKETS 1000 4.245 -#define MAX_STATS 4.246 -typedef struct act_stats_st 4.247 -{ 4.248 - u32 count; 4.249 - u32 times[2*(BUCKETS)]; 4.250 -} __cacheline_aligned act_stats_t; 4.251 -static act_stats_t act_stats[NR_CPUS]; 4.252 - 4.253 -#endif 4.254 - 4.255 -#ifdef AC_TIMER_STATS 4.256 - { 4.257 - XXX this is at the wrong place 4.258 - s32 diff; 4.259 - u32 i; 4.260 - diff = ((s32)(NOW() - t->expires)) / 1000; /* delta in us */ 4.261 - if (diff < -BUCKETS) 4.262 - diff = -BUCKETS; 4.263 - else if (diff > BUCKETS) 4.264 - diff = BUCKETS; 4.265 - act_stats[cpu].times[diff+BUCKETS]++; 4.266 - act_stats[cpu].count++; 4.267 - 4.268 - if (act_stats[cpu].count >= 5000) { 4.269 - printk("ACT Stats\n"); 4.270 - for (i=0; i < 2*BUCKETS; i++) { 4.271 - if (act_stats[cpu].times[i] != 0) 4.272 - printk("ACT [%02d]: %3dus: %5d\n", 4.273 - cpu,i-BUCKETS, act_stats[cpu].times[i]); 4.274 - act_stats[cpu].times[i]=0; 4.275 - } 4.276 - act_stats[cpu].count = 0; 4.277 - printk("\n"); 4.278 - } 4.279 - } 4.280 -#endif 4.281 - 4.282 -#endif /* 0 */
5.1 --- a/xen/common/keyhandler.c Mon Jul 21 15:05:07 2003 +0000 5.2 +++ b/xen/common/keyhandler.c Tue Jul 22 13:25:32 2003 +0000 5.3 @@ -116,7 +116,6 @@ void do_task_queues(u_char key, void *de 5.4 5.5 extern void perfc_printall (u_char key, void *dev_id, struct pt_regs *regs); 5.6 extern void perfc_reset (u_char key, void *dev_id, struct pt_regs *regs); 5.7 -extern void dump_timerq(u_char key, void *dev_id, struct pt_regs *regs); 5.8 extern void dump_runq(u_char key, void *dev_id, struct pt_regs *regs); 5.9 extern void print_sched_histo(u_char key, void *dev_id, struct pt_regs *regs); 5.10 extern void reset_sched_histo(u_char key, void *dev_id, struct pt_regs *regs); 5.11 @@ -131,7 +130,6 @@ void initialize_keytable() 5.12 key_table[i].handler = (key_handler *)NULL; 5.13 5.14 /* setup own handlers */ 5.15 - add_key_handler('a', dump_timerq, "dump ac_timer queues"); 5.16 add_key_handler('d', dump_registers, "dump registers"); 5.17 add_key_handler('h', show_handlers, "show this message"); 5.18 add_key_handler('l', print_sched_histo, "print sched latency histogram");
6.1 --- a/xen/include/asm-i386/time.h Mon Jul 21 15:05:07 2003 +0000 6.2 +++ b/xen/include/asm-i386/time.h Tue Jul 22 13:25:32 2003 +0000 6.3 @@ -5,16 +5,9 @@ 6.4 * 6.5 * File: time.h 6.6 * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk) 6.7 - * Changes: 6.8 - * 6.9 - * Date: Nov 2002 6.10 * 6.11 * Environment: Xen Hypervisor 6.12 * Description: Architecture dependent definition of time variables 6.13 - * 6.14 - **************************************************************************** 6.15 - * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $ 6.16 - **************************************************************************** 6.17 */ 6.18 6.19 #ifndef _ASM_TIME_H_ 6.20 @@ -23,28 +16,7 @@ 6.21 #include <asm/types.h> 6.22 #include <asm/msr.h> 6.23 6.24 -/* 6.25 - * Cycle Counter Time 6.26 - */ 6.27 -typedef u64 cc_time_t; 6.28 -static inline cc_time_t get_cc_time() 6.29 -{ 6.30 - u64 ret; 6.31 - rdtscll(ret); 6.32 - return ret; 6.33 -} 6.34 - 6.35 -/* 6.36 - * System Time 6.37 - */ 6.38 -typedef s64 s_time_t; /* System time */ 6.39 -extern u32 stime_pcc; /* cycle counter value at last timer irq */ 6.40 -extern s_time_t stime_now; /* time in ns at last timer IRQ */ 6.41 - 6.42 -/* 6.43 - * Domain Virtual Time 6.44 - */ 6.45 -typedef u64 dv_time_t; 6.46 +typedef s64 s_time_t; /* system time */ 6.47 6.48 extern int using_apic_timer; 6.49