ia64/xen-unstable

changeset 140:350c8a939f8d

bitkeeper revision 1.24 (3e49286b1h6iIeNsarUfoWbDnP6Ndw)

New time implementation. Does system and wallclock time for Xen and GuestOSes
author rn@wyvis.camb.intel-research.net
date Tue Feb 11 16:44:27 2003 +0000 (2003-02-11)
parents b0d356ed774b
children 2c1ef70cc49f
files xen-2.4.16/arch/i386/apic.c xen-2.4.16/arch/i386/entry.S xen-2.4.16/arch/i386/time.c xen-2.4.16/common/ac_timer.c xen-2.4.16/common/domain.c xen-2.4.16/common/kernel.c xen-2.4.16/common/schedule.c xen-2.4.16/common/timer.c xen-2.4.16/include/asm-i386/time.h xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h xen-2.4.16/include/xeno/sched.h xen-2.4.16/include/xeno/time.h xenolinux-2.4.16-sparse/arch/xeno/kernel/time.c
line diff
     1.1 --- a/xen-2.4.16/arch/i386/apic.c	Sat Feb 01 17:27:13 2003 +0000
     1.2 +++ b/xen-2.4.16/arch/i386/apic.c	Tue Feb 11 16:44:27 2003 +0000
     1.3 @@ -48,7 +48,6 @@
     1.4  
     1.5  #include <xeno/ac_timer.h>
     1.6  
     1.7 -
     1.8  #undef APIC_TIME_TRACE
     1.9  #ifdef APIC_TIME_TRACE
    1.10  #define TRC(_x) _x
    1.11 @@ -511,7 +510,7 @@ void __init init_apic_mappings(void)
    1.12  static unsigned int bus_freq;
    1.13  static u32          bus_cycle;   /* length of one bus cycle in pico-seconds */
    1.14  static u32          bus_scale;   /* scaling factor convert ns to bus cycles */
    1.15 -
    1.16 +u64 cpu_freq;
    1.17  
    1.18  /*
    1.19   * The timer chip is already set up at HZ interrupts per second here,
    1.20 @@ -643,6 +642,8 @@ int __init calibrate_APIC_clock(void)
    1.21             result/(1000000/HZ),
    1.22             result%(1000000/HZ));
    1.23  
    1.24 +	cpu_freq = (u64)(((t2-t1)/LOOPS)*HZ);
    1.25 +
    1.26  	/* set up multipliers for accurate timer code */
    1.27  	bus_freq   = result*HZ;
    1.28  	bus_cycle  = (u32) (1000000000000LL/bus_freq); /* in pico seconds */
    1.29 @@ -676,13 +677,12 @@ void __init setup_APIC_clocks (void)
    1.30  }
    1.31  
    1.32  #undef APIC_DIVISOR
    1.33 +
    1.34  /*
    1.35   * reprogram the APIC timer. Timeoutvalue is in ns from start of boot
    1.36   * returns 1 on success
    1.37   * returns 0 if the timeout value is too small or in the past.
    1.38   */
    1.39 -
    1.40 -
    1.41  int reprogram_ac_timer(s_time_t timeout)
    1.42  {
    1.43  	int 		cpu = smp_processor_id();
    1.44 @@ -695,8 +695,8 @@ int reprogram_ac_timer(s_time_t timeout)
    1.45  
    1.46  
    1.47  	if (expire <= 0) {
    1.48 -		printk("APICT[%02d] Timeout value in the past %lld > %lld\n", 
    1.49 -			   cpu, now, timeout);
    1.50 +		printk("APICT[%02d] Timeout in the past 0x%08X%08X > 0x%08X%08X\n", 
    1.51 +			   cpu, (u32)(now>>32), (u32)now, (u32)(timeout>>32),(u32)timeout);
    1.52  		return 0;		/* timeout value in the past */
    1.53  	}
    1.54  
    1.55 @@ -728,18 +728,27 @@ int reprogram_ac_timer(s_time_t timeout)
    1.56   * the timer APIC on CPU does not go off every 10ms or so the linux 
    1.57   * timers loose accuracy, but that shouldn't be a problem.
    1.58   */
    1.59 -
    1.60 -static s_time_t last_cpu0_tirq = 0;
    1.61 +//static s_time_t last_cpu0_tirq = 0;
    1.62  inline void smp_local_timer_interrupt(struct pt_regs * regs)
    1.63  {
    1.64  	int cpu = smp_processor_id();
    1.65 -	s_time_t diff, now;
    1.66 +	//s_time_t diff, now;
    1.67  
    1.68      /* if CPU 0 do old timer stuff  */
    1.69  	if (cpu == 0) {
    1.70 -		update_time();
    1.71 +
    1.72 +		/*
    1.73 +         * XXX RN: the following code should be moved here or somewhere
    1.74 +         * else. It's currently done using the 8255 timer interrupt, which
    1.75 +         * I'd like to disable. But, APIC initialisation relies on it,
    1.76 +         * e.g., timer interrupts coming in, jiffies going up, etc. Need to
    1.77 +         * clean this up. Also see ./arch/i386/time.c
    1.78 +         */
    1.79 +#if 0
    1.80 +		//update_time();/* XXX should use a timer for this */		
    1.81  		now = NOW();
    1.82  		diff = now - last_cpu0_tirq;
    1.83 +
    1.84  		/* this uses three 64bit divisions which should be avoided!! */
    1.85  		if (diff >= MILLISECS(10)) {
    1.86  			/* update jiffies */
    1.87 @@ -749,8 +758,9 @@ inline void smp_local_timer_interrupt(st
    1.88  			do_timer(regs);
    1.89  			last_cpu0_tirq = now;
    1.90  		}
    1.91 +#endif
    1.92  	}
    1.93 -	/* call timer function */
    1.94 +	/* call accurate timer function */
    1.95  	do_ac_timer();
    1.96  }
    1.97  
     2.1 --- a/xen-2.4.16/arch/i386/entry.S	Sat Feb 01 17:27:13 2003 +0000
     2.2 +++ b/xen-2.4.16/arch/i386/entry.S	Tue Feb 11 16:44:27 2003 +0000
     2.3 @@ -520,7 +520,7 @@ ENTRY(hypervisor_call_table)
     2.4          .long SYMBOL_NAME(do_stack_and_ldt_switch)
     2.5          .long SYMBOL_NAME(do_net_update)
     2.6          .long SYMBOL_NAME(do_fpu_taskswitch)
     2.7 -        .long SYMBOL_NAME(do_yield)
     2.8 +        .long SYMBOL_NAME(do_sched_op)
     2.9          .long SYMBOL_NAME(kill_domain)
    2.10          .long SYMBOL_NAME(do_dom0_op)
    2.11          .long SYMBOL_NAME(do_network_op)
     3.1 --- a/xen-2.4.16/arch/i386/time.c	Sat Feb 01 17:27:13 2003 +0000
     3.2 +++ b/xen-2.4.16/arch/i386/time.c	Tue Feb 11 16:44:27 2003 +0000
     3.3 @@ -11,7 +11,8 @@
     3.4   * 
     3.5   * Environment: Xen Hypervisor
     3.6   * Description: modified version of Linux' time.c
     3.7 - *              implement system and wall clock time.
     3.8 + *              implements system and wall clock time.
     3.9 + *				based on freebsd's implementation.
    3.10   *
    3.11   ****************************************************************************
    3.12   * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
    3.13 @@ -53,11 +54,6 @@ unsigned long ticks_per_usec; /* TSC tic
    3.14  
    3.15  spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
    3.16  
    3.17 -
    3.18 -/*
    3.19 - * timer_interrupt() needs to keep up the real-time clock,
    3.20 - * as well as call the "do_timer()" routine every clocktick
    3.21 - */
    3.22  int timer_ack=0;
    3.23  extern spinlock_t i8259A_lock;
    3.24  static inline void do_timer_interrupt(int irq, 
    3.25 @@ -78,6 +74,8 @@ static inline void do_timer_interrupt(in
    3.26          spin_unlock(&i8259A_lock);
    3.27      }
    3.28  #endif
    3.29 +
    3.30 +	/* XXX RN: Want to remove this but APIC-SMP code seems to rely on it */
    3.31      do_timer(regs);
    3.32  }
    3.33  
    3.34 @@ -235,30 +233,59 @@ static unsigned long get_cmos_time(void)
    3.35  }
    3.36  
    3.37  /***************************************************************************
    3.38 - * System time
    3.39 + * Time
    3.40 + * XXX RN: Will be able to remove some of the locking once the time is
    3.41 + * update by the APIC on only one CPU. 
    3.42   ***************************************************************************/
    3.43 -u32					stime_pcc;	 /* cycle counter value at last timer irq */
    3.44 -u32					stime_scale; /* scale factor for converting cc to ns */
    3.45 -s_time_t			stime_now;   /* time in ns at last timer IRQ */
    3.46 +
    3.47 +static spinlock_t stime_lock;
    3.48 +static u32	st_scale_f;
    3.49 +static u32	st_scale_i;
    3.50 +u32			stime_pcc;	 /* cycle counter value at last timer irq */
    3.51 +s_time_t	stime_now;   /* time in ns at last timer IRQ */
    3.52 +
    3.53 +s_time_t get_s_time(void)
    3.54 +{
    3.55 +	unsigned long flags;
    3.56 +    u32 	 delta_tsc, low, pcc;
    3.57 +	u64      delta;
    3.58 +	s_time_t now;
    3.59 +
    3.60 +	spin_lock_irqsave(&stime_lock, flags);
    3.61  
    3.62 -/***************************************************************************
    3.63 - * Wall Clock time 
    3.64 - ***************************************************************************/
    3.65 -static rwlock_t wctime_lock = RW_LOCK_UNLOCKED;
    3.66 -struct timeval  wall_clock_time;	/* wall clock time at last update */
    3.67 -s_time_t	    wctime_st;       /* system time at last update */
    3.68 +    pcc = stime_pcc;		
    3.69 +    now = stime_now;
    3.70 +
    3.71 +    /* only use bottom 32bits of TSC. This should be sufficient */
    3.72 +	rdtscl(low);
    3.73 +    delta_tsc = low - pcc;
    3.74 +	delta = ((u64)delta_tsc * st_scale_f);
    3.75 +	delta >>= 32;
    3.76 +	delta += ((u64)delta_tsc * st_scale_i);
    3.77 +
    3.78 +	spin_unlock_irqrestore(&stime_lock, flags);
    3.79 +
    3.80 +    return now + delta; 
    3.81 +}
    3.82 +
    3.83 +
    3.84 +/* Wall Clock time */
    3.85 +static spinlock_t wctime_lock;
    3.86 +struct timeval    wall_clock_time; /* wall clock time at last update */
    3.87 +s_time_t	      wctime_st;       /* system time at last update */
    3.88  
    3.89  void do_gettimeofday(struct timeval *tv)
    3.90  {
    3.91  	unsigned long flags;
    3.92  	unsigned long usec, sec;
    3.93  
    3.94 -	read_lock_irqsave(&wctime_lock, flags);
    3.95 +	spin_lock_irqsave(&wctime_lock, flags);
    3.96  
    3.97  	usec = ((unsigned long)(NOW() - wctime_st))/1000;
    3.98  	sec = wall_clock_time.tv_sec;
    3.99  	usec += wall_clock_time.tv_usec;
   3.100 -	read_unlock_irqrestore(&wctime_lock, flags);
   3.101 +
   3.102 +	spin_unlock_irqrestore(&wctime_lock, flags);
   3.103  
   3.104  	while (usec >= 1000000) {
   3.105  		usec -= 1000000;
   3.106 @@ -276,22 +303,26 @@ void do_settimeofday(struct timeval *tv)
   3.107  /***************************************************************************
   3.108   * Update times
   3.109   ***************************************************************************/
   3.110 -
   3.111  /* update hypervisors notion of time */
   3.112  void update_time(void) {
   3.113 -	u32		      new_pcc;
   3.114 -	s_time_t      new_st;
   3.115 -	unsigned long usec;
   3.116 +	unsigned long  flags;
   3.117 +	u32		       new_pcc;
   3.118 +	s_time_t       new_st;
   3.119 +	unsigned long  usec;
   3.120  
   3.121 -	/* update system time */
   3.122 +	new_st = NOW();
   3.123  	rdtscl(new_pcc);
   3.124 -	stime_now = stime_now+((((s_time_t)stime_scale)*
   3.125 -							(new_pcc-stime_pcc))>>10);
   3.126 +
   3.127 +	/* update system time  */
   3.128 +	spin_lock_irqsave(&stime_lock, flags);
   3.129 +
   3.130 +	stime_now = new_st;
   3.131  	stime_pcc=new_pcc;
   3.132  
   3.133 +	spin_unlock_irqrestore(&stime_lock, flags);
   3.134 +
   3.135  	/* update wall clock time  */
   3.136 -	write_lock(&wctime_lock);
   3.137 -	new_st = NOW();
   3.138 +	spin_lock_irqsave(&wctime_lock, flags);
   3.139  	usec = ((unsigned long)(new_st - wctime_st))/1000;
   3.140  	usec += wall_clock_time.tv_usec;
   3.141  	while (usec >= 1000000) {
   3.142 @@ -300,10 +331,10 @@ void update_time(void) {
   3.143  	}
   3.144  	wall_clock_time.tv_usec = usec;
   3.145  	wctime_st = new_st;
   3.146 -	write_unlock(&wctime_lock);
   3.147 +	spin_unlock_irqrestore(&wctime_lock, flags);
   3.148  
   3.149 -	TRC(printk("TIME[%02d] update time: stime_now=%lld now=%lld, wct=%ld:%ld\n"
   3.150 -			   cpu, stime_now, new_st, wall_clock_time.tv_sec,
   3.151 +	TRC(printk("TIME[%02d] update time: stime_now=%lld now=%lld,wct=%ld:%ld\n",
   3.152 +			   smp_processor_id(), stime_now, new_st, wall_clock_time.tv_sec,
   3.153  			   wall_clock_time.tv_usec));
   3.154  }
   3.155  
   3.156 @@ -311,13 +342,20 @@ void update_time(void) {
   3.157  void update_dom_time(shared_info_t *si)
   3.158  {
   3.159  	unsigned long flags;
   3.160 -	read_lock_irqsave(&wctime_lock, flags);
   3.161 +
   3.162 +	spin_lock_irqsave(&stime_lock, flags);
   3.163  	si->system_time  = stime_now;
   3.164  	si->st_timestamp = stime_pcc;
   3.165 +	spin_unlock_irqrestore(&stime_lock, flags);
   3.166 +
   3.167 +	spin_lock_irqsave(&wctime_lock, flags);
   3.168  	si->tv_sec       = wall_clock_time.tv_sec;
   3.169  	si->tv_usec      = wall_clock_time.tv_usec;
   3.170  	si->wc_timestamp = wctime_st;
   3.171 -	read_unlock_irqrestore(&wctime_lock, flags);	
   3.172 +	si->wc_version++;
   3.173 +	spin_unlock_irqrestore(&wctime_lock, flags);	
   3.174 +
   3.175 +	TRC(printk(" 0x%08X%08X\n", (u32)(wctime_st>>32), (u32)wctime_st));
   3.176  }
   3.177  
   3.178  /***************************************************************************
   3.179 @@ -328,17 +366,26 @@ int __init init_xeno_time()
   3.180  {
   3.181  	int cpu = smp_processor_id();
   3.182  	u32	cpu_cycle;	 /* time of one cpu cyle in pico-seconds */
   3.183 +	u64 scale;
   3.184 +
   3.185 +	spin_lock_init(&stime_lock);
   3.186 +	spin_lock_init(&wctime_lock);
   3.187  
   3.188  	/* System Time */
   3.189  	cpu_cycle   = (u32) (1000000000LL/cpu_khz); /* in pico seconds */
   3.190 -	stime_scale = (cpu_cycle * 1024) / 1000;
   3.191 +	scale = 1000000000LL << 32;
   3.192 +	scale /= cpu_freq;
   3.193 +	st_scale_f = scale & 0xffffffff;
   3.194 +	st_scale_i = scale >> 32;
   3.195  
   3.196  	stime_now = (s_time_t)0;
   3.197  	rdtscl(stime_pcc);
   3.198  	
   3.199  	printk("Init Time[%02d]:\n", cpu);
   3.200  	printk(".... System Time: %lldns\n", NOW());
   3.201 -	printk(".... stime_scale: %u\n",   stime_scale);
   3.202 +	printk(".....cpu_cycle:   %u ps\n", cpu_cycle);
   3.203 +	printk(".... st_scale_f:  %X\n",   st_scale_f);
   3.204 +	printk(".... st_scale_i:  %X\n",   st_scale_i);
   3.205  	printk(".... stime_pcc:   %u\n",   stime_pcc);
   3.206  
   3.207  	/* Wall Clock time */
   3.208 @@ -367,7 +414,6 @@ void __init time_init(void)
   3.209      ticks_per_usec = ticks_per_frac / (1000000/CALIBRATE_FRAC);
   3.210      cpu_khz = ticks_per_frac / (1000/CALIBRATE_FRAC);
   3.211  
   3.212 -
   3.213      printk("Detected %lu.%03lu MHz processor.\n", 
   3.214             cpu_khz / 1000, cpu_khz % 1000);
   3.215  
     4.1 --- a/xen-2.4.16/common/ac_timer.c	Sat Feb 01 17:27:13 2003 +0000
     4.2 +++ b/xen-2.4.16/common/ac_timer.c	Tue Feb 11 16:44:27 2003 +0000
     4.3 @@ -91,7 +91,9 @@ int add_ac_timer(struct ac_timer *timer)
     4.4  	TRC(printk("ACT  [%02d] add(): now=%lld timo=%lld\n",
     4.5  			   cpu, now, timer->expires));
     4.6  	if (timer->expires <= now) {	
     4.7 -		printk("ACT[%02d] add_ac_timer(): timeout value in the past\n", cpu);
     4.8 +		printk("ACT[%02d] add_ac_timer: now=0x%08X%08X > expire=0x%08X%08X\n",
     4.9 +			   cpu, (u32)(now>>32), (u32)now,
    4.10 +			   (u32)(timer->expires>>32), (u32)timer->expires);
    4.11  		return 1;
    4.12  	}
    4.13  
    4.14 @@ -100,7 +102,8 @@ int add_ac_timer(struct ac_timer *timer)
    4.15  	/* check if timer would be inserted at start of list */
    4.16  	if ((list_empty(&ac_timers[cpu].timers)) ||
    4.17  		(timer->expires <
    4.18 -		(list_entry(&ac_timers[cpu].timers, struct ac_timer, timer_list))->expires)) {
    4.19 +		(list_entry(&ac_timers[cpu].timers,
    4.20 +					struct ac_timer, timer_list))->expires)) {
    4.21  
    4.22  		TRC(printk("ACT  [%02d] add(): add at head\n", cpu));
    4.23  		/* Reprogramm and add to head of list */
     5.1 --- a/xen-2.4.16/common/domain.c	Sat Feb 01 17:27:13 2003 +0000
     5.2 +++ b/xen-2.4.16/common/domain.c	Tue Feb 11 16:44:27 2003 +0000
     5.3 @@ -8,6 +8,7 @@
     5.4  #include <xeno/interrupt.h>
     5.5  #include <xeno/delay.h>
     5.6  #include <xeno/event.h>
     5.7 +#include <xeno/time.h>
     5.8  #include <xeno/dom0_ops.h>
     5.9  #include <asm/io.h>
    5.10  #include <asm/domain_page.h>
    5.11 @@ -160,8 +161,7 @@ void release_task(struct task_struct *p)
    5.12      free_task_struct(p);
    5.13  }
    5.14  
    5.15 -
    5.16 -static unsigned int alloc_new_dom_mem(struct task_struct *p, unsigned int kbytes)
    5.17 +unsigned int alloc_new_dom_mem(struct task_struct *p, unsigned int kbytes)
    5.18  {
    5.19      struct list_head *temp;
    5.20      struct pfn_info *pf, *pf_head;
    5.21 @@ -233,7 +233,6 @@ int final_setup_guestos(struct task_stru
    5.22      l1_pgentry_t * l1tab;
    5.23      start_info_t * virt_startinfo_addr;
    5.24      unsigned long virt_stack_addr;
    5.25 -    unsigned long long time;
    5.26      unsigned long phys_l2tab;
    5.27      page_update_request_t * pgt_updates;
    5.28      unsigned long curr_update_phys;
    5.29 @@ -285,10 +284,9 @@ int final_setup_guestos(struct task_stru
    5.30      unmap_domain_mem((void *)((unsigned long)l1tab & PAGE_MASK));
    5.31  
    5.32      /* set up the shared info structure */
    5.33 -    rdtscll(time);
    5.34 -    p->shared_info->wall_time    = time;
    5.35 -    p->shared_info->domain_time  = time;
    5.36 -    p->shared_info->ticks_per_ms = ticks_per_usec * 1000;
    5.37 +	update_dom_time(p->shared_info);
    5.38 +	p->shared_info->cpu_freq	 = cpu_freq;
    5.39 +    p->shared_info->domain_time  = 0;
    5.40  
    5.41      /* we pass start info struct to guest os as function parameter on stack */
    5.42      virt_startinfo_addr = (start_info_t *)meminfo->virt_startinfo_addr;
    5.43 @@ -389,7 +387,6 @@ int setup_guestos(struct task_struct *p,
    5.44      unsigned long virt_load_address, virt_stack_address, virt_shinfo_address;
    5.45      unsigned long virt_ftable_start, virt_ftable_end, ft_mapping;
    5.46      start_info_t  *virt_startinfo_address;
    5.47 -    unsigned long long time;
    5.48      unsigned long count;
    5.49      unsigned long alloc_index;
    5.50      unsigned long ft_pages;
    5.51 @@ -521,10 +518,10 @@ int setup_guestos(struct task_struct *p,
    5.52      unmap_domain_mem(l1start);
    5.53  
    5.54      /* Set up shared info area. */
    5.55 -    rdtscll(time);
    5.56 -    p->shared_info->wall_time    = time;
    5.57 -    p->shared_info->domain_time  = time;
    5.58 -    p->shared_info->ticks_per_ms = ticks_per_usec * 1000;
    5.59 +	update_dom_time(p->shared_info);
    5.60 +	p->shared_info->cpu_freq	 = cpu_freq;
    5.61 +    p->shared_info->domain_time  = 0;
    5.62 +
    5.63  
    5.64      virt_startinfo_address = (start_info_t *)
    5.65          (virt_load_address + ((alloc_index - 1) << PAGE_SHIFT));
    5.66 @@ -640,11 +637,6 @@ int setup_guestos(struct task_struct *p,
    5.67  void __init domain_init(void)
    5.68  {
    5.69  	printk("Initialising domains\n");
    5.70 -//	scheduler_init();
    5.71  }
    5.72  
    5.73  
    5.74 -
    5.75 -#if 0
    5.76 -    }
    5.77 -}
     6.1 --- a/xen-2.4.16/common/kernel.c	Sat Feb 01 17:27:13 2003 +0000
     6.2 +++ b/xen-2.4.16/common/kernel.c	Tue Feb 11 16:44:27 2003 +0000
     6.3 @@ -182,6 +182,7 @@ void cmain (unsigned long magic, multibo
     6.4      {
     6.5          panic("Could not set up DOM0 guest OS\n");
     6.6      }
     6.7 +	update_dom_time(new_dom->shared_info);
     6.8      wake_up(new_dom);
     6.9  
    6.10      cpu_idle();
     7.1 --- a/xen-2.4.16/common/schedule.c	Sat Feb 01 17:27:13 2003 +0000
     7.2 +++ b/xen-2.4.16/common/schedule.c	Tue Feb 11 16:44:27 2003 +0000
     7.3 @@ -275,8 +275,7 @@ asmlinkage void schedule(void)
     7.4      if ( prev->state == TASK_DYING ) release_task(prev);
     7.5  
     7.6   same_process:
     7.7 -
     7.8 -	update_dom_time(next->shared_info);
     7.9 +	update_dom_time(current->shared_info);
    7.10  
    7.11      if ( test_bit(_HYP_EVENT_NEED_RESCHED, &current->hyp_events) )
    7.12          goto need_resched_back;
    7.13 @@ -294,20 +293,22 @@ static void sched_timer(unsigned long fo
    7.14  	if (count[cpu] >= 5) {
    7.15  		set_bit(_HYP_EVENT_NEED_RESCHED, &curr->hyp_events);
    7.16  		count[cpu] = 0;
    7.17 +		if (cpu == 0)
    7.18 +			update_time(); /* XXX RN: Should be moved on its own timer */
    7.19  	}
    7.20  	count[cpu]++;
    7.21  
    7.22   again:
    7.23  	now = NOW();
    7.24  	s_timer[cpu].expires  = now + MILLISECS(10);
    7.25 +	res=add_ac_timer(&s_timer[cpu]);
    7.26  
    7.27   	TRC(printk("SCHED[%02d] timer(): now=0x%08X%08X timo=0x%08X%08X\n",
    7.28   			   cpu, (u32)(now>>32), (u32)now,
    7.29   			   (u32)(s_timer[cpu].expires>>32), (u32)s_timer[cpu].expires));
    7.30 -	res=add_ac_timer(&s_timer[cpu]);
    7.31 -	if (res==1) {
    7.32 +	if (res==1)
    7.33  		goto again;
    7.34 -	}
    7.35 +
    7.36  }
    7.37  /*
    7.38   * Initialise the data structures
    7.39 @@ -340,6 +341,6 @@ void schedulers_start(void) {
    7.40  	printk("Start schedulers\n");
    7.41  	__cli();
    7.42  	sched_timer(0);
    7.43 -	smp_call_function(sched_timer, (void*)0, 1, 1);
    7.44 +	smp_call_function(sched_timer, NULL, 1, 1);
    7.45  	__sti();
    7.46  }
     8.1 --- a/xen-2.4.16/common/timer.c	Sat Feb 01 17:27:13 2003 +0000
     8.2 +++ b/xen-2.4.16/common/timer.c	Tue Feb 11 16:44:27 2003 +0000
     8.3 @@ -588,7 +588,6 @@ void do_timer(struct pt_regs *regs)
     8.4  {
     8.5      struct task_struct *p;
     8.6      shared_info_t *s;
     8.7 -    unsigned long long wall;
     8.8      unsigned long cpu_mask = 0;
     8.9  
    8.10      (*(unsigned long *)&jiffies)++;
    8.11 @@ -596,8 +595,7 @@ void do_timer(struct pt_regs *regs)
    8.12      if ( !using_apic_timer )
    8.13          update_process_times(user_mode(regs));
    8.14  
    8.15 -    rdtscll(wall);
    8.16 -
    8.17 +	/* XXX RN: Move this for virtual domain time timer interrupts */
    8.18      read_lock(&tasklist_lock);
    8.19      p = &idle0_task;
    8.20      do {
     9.1 --- a/xen-2.4.16/include/asm-i386/time.h	Sat Feb 01 17:27:13 2003 +0000
     9.2 +++ b/xen-2.4.16/include/asm-i386/time.h	Tue Feb 11 16:44:27 2003 +0000
     9.3 @@ -37,37 +37,9 @@ static inline cc_time_t get_cc_time()
     9.4  /*
     9.5   * System Time
     9.6   */
     9.7 -typedef s64      s_time_t;	   /* System time */
     9.8 -extern  u32      stime_pcc;    /* cycle counter value at last timer irq */
     9.9 -extern  s_time_t stime_now;    /* time in ns at last timer IRQ */
    9.10 -extern  u32      stime_scale;  /* scale factur for converting cc to ns */
    9.11 -
    9.12 -
    9.13 -/*
    9.14 - * This is the Nemesis implementation.
    9.15 - * The variables are all set in apic.c
    9.16 - * Every timer IRQ time_now and time_pcc is set to the current values
    9.17 - * At callibration time_scale is set
    9.18 - */
    9.19 -static s_time_t get_s_time(void)
    9.20 -{
    9.21 -    u32 	 delta, low, pcc;
    9.22 -	s_time_t now;
    9.23 -	s_time_t incr;
    9.24 -
    9.25 -	/* read two values (pcc, now) "atomically" */
    9.26 -again:
    9.27 -    pcc = stime_pcc;		
    9.28 -    now = stime_now;
    9.29 -	if (stime_pcc != pcc) goto again;
    9.30 -
    9.31 -    /* only use bottom 32bits of TSC. This should be sufficient */
    9.32 -	rdtscl(low);
    9.33 -    delta = low - pcc;
    9.34 -
    9.35 -	incr = ((s_time_t)(stime_scale) * delta) >> 10;
    9.36 -    return now + incr; 
    9.37 -}
    9.38 +typedef s64      s_time_t;	     /* System time */
    9.39 +extern  u32      stime_pcc;      /* cycle counter value at last timer irq */
    9.40 +extern  s_time_t stime_now;      /* time in ns at last timer IRQ */
    9.41  
    9.42  /* update time variables once in a while */
    9.43  extern void update_time(void);
    10.1 --- a/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h	Sat Feb 01 17:27:13 2003 +0000
    10.2 +++ b/xen-2.4.16/include/hypervisor-ifs/hypervisor-if.h	Tue Feb 11 16:44:27 2003 +0000
    10.3 @@ -72,7 +72,7 @@ typedef struct
    10.4  #define __HYPERVISOR_stack_and_ldt_switch  4
    10.5  #define __HYPERVISOR_net_update            5
    10.6  #define __HYPERVISOR_fpu_taskswitch        6
    10.7 -#define __HYPERVISOR_yield                 7
    10.8 +#define __HYPERVISOR_sched_op              7
    10.9  #define __HYPERVISOR_exit                  8
   10.10  #define __HYPERVISOR_dom0_op               9
   10.11  #define __HYPERVISOR_network_op           10
   10.12 @@ -160,16 +160,20 @@ typedef struct shared_info_st {
   10.13       * The following abstractions are exposed: System Time, Wall Clock 
   10.14       * Time, Domain Virtual Time. Domains can access Cycle counter time
   10.15       * directly. 
   10.16 +	 * XXX RN: Need something to pass NTP scaling to GuestOS.
   10.17       */
   10.18  
   10.19 +	u64           cpu_freq;	    /* to calculate ticks -> real time */
   10.20 +
   10.21  	/* System Time */
   10.22 -	long long          system_time;		/* in ns */
   10.23 -	unsigned long      st_timestamp;	/* cyclecounter at last update */
   10.24 -	unsigned long      ticks_per_ms;    /* CPU ticks per millisecond */
   10.25 +	long long          system_time;     /* in ns */
   10.26 +	unsigned long      st_timestamp;    /* cyclecounter at last update */
   10.27 +
   10.28  	/* Wall Clock Time */
   10.29 -	long	  tv_sec;					/* essentially a struct timeval */
   10.30 -	long	  tv_usec;
   10.31 -	long long wc_timestamp;				/* system time at last update */
   10.32 +	u32                wc_version;      /* a version number for info below */
   10.33 +	long               tv_sec;          /* essentially a struct timeval */
   10.34 +	long               tv_usec;
   10.35 +	long long          wc_timestamp;    /* system time at last update */
   10.36  
   10.37  	/* Domain Virtual Time */
   10.38  	unsigned long long domain_time;
    11.1 --- a/xen-2.4.16/include/xeno/sched.h	Sat Feb 01 17:27:13 2003 +0000
    11.2 +++ b/xen-2.4.16/include/xeno/sched.h	Tue Feb 11 16:44:27 2003 +0000
    11.3 @@ -193,7 +193,7 @@ extern unsigned long wait_init_idle;
    11.4  #define set_current_state(_s) do { current->state = (_s); } while (0)
    11.5  #define MAX_SCHEDULE_TIMEOUT LONG_MAX
    11.6  void scheduler_init(void);
    11.7 -void start_scheduler(void);
    11.8 +void schedulers_start(void);
    11.9  void sched_add_domain(struct task_struct *p);
   11.10  void sched_rem_domain(struct task_struct *p);
   11.11  int  wake_up(struct task_struct *p);
    12.1 --- a/xen-2.4.16/include/xeno/time.h	Sat Feb 01 17:27:13 2003 +0000
    12.2 +++ b/xen-2.4.16/include/xeno/time.h	Tue Feb 11 16:44:27 2003 +0000
    12.3 @@ -32,10 +32,17 @@
    12.4  #include <xeno/types.h>
    12.5  
    12.6  /*
    12.7 + * Init time
    12.8 + */
    12.9 +extern int init_xeno_time();
   12.10 +
   12.11 +/*
   12.12   * Cycle Counter Time (defined in asm/time.h)
   12.13   */
   12.14  
   12.15  
   12.16 +extern u64	cpu_freq;
   12.17 +
   12.18  /*
   12.19   * System Time
   12.20   * 64 bit value containing the nanoseconds elapsed since boot time.
   12.21 @@ -44,6 +51,9 @@
   12.22   * The other macros are for convenience to approximate short intervals
   12.23   * of real time into system time 
   12.24   */
   12.25 +
   12.26 +s_time_t get_s_time(void);
   12.27 +
   12.28  #define NOW()				((s_time_t)get_s_time())
   12.29  #define SECONDS(_s)			(((s_time_t)(_s))  * 1000000000UL )
   12.30  #define TENTHS(_ts)			(((s_time_t)(_ts)) * 100000000UL )
   12.31 @@ -79,6 +89,9 @@ extern void (*do_get_fast_time)(struct t
   12.32  /* XXX Interface for getting and setting still missing */
   12.33  
   12.34  
   12.35 +/* update the per domain time information */
   12.36 +extern void update_dom_time(shared_info_t *si);
   12.37 +
   12.38  /* XXX move this  */
   12.39  extern void do_timer(struct pt_regs *regs);
   12.40  
    13.1 --- a/xenolinux-2.4.16-sparse/arch/xeno/kernel/time.c	Sat Feb 01 17:27:13 2003 +0000
    13.2 +++ b/xenolinux-2.4.16-sparse/arch/xeno/kernel/time.c	Tue Feb 11 16:44:27 2003 +0000
    13.3 @@ -1,3 +1,25 @@
    13.4 +/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
    13.5 + ****************************************************************************
    13.6 + * (C) 2002 - Rolf Neugebauer - Intel Research Cambridge
    13.7 + ****************************************************************************
    13.8 + *
    13.9 + *        File: arch.xeno/time.c
   13.10 + *      Author: Rolf Neugebauer
   13.11 + *     Changes: 
   13.12 + *              
   13.13 + *        Date: Nov 2002
   13.14 + * 
   13.15 + * Environment: XenoLinux
   13.16 + * Description: Interface with Hypervisor to get correct notion of time
   13.17 + *              Currently supports Systemtime and WallClock time.
   13.18 + *
   13.19 + * (This has hardly any resemblence with the Linux code but left the
   13.20 + *  copyright notice anyway. Ignore the comments in the copyright notice.)
   13.21 + ****************************************************************************
   13.22 + * $Id: c-insert.c,v 1.7 2002/11/08 16:04:34 rn Exp $
   13.23 + ****************************************************************************
   13.24 + */
   13.25 +
   13.26  /*
   13.27   *  linux/arch/i386/kernel/time.c
   13.28   *
   13.29 @@ -30,19 +52,6 @@
   13.30   *	serialize accesses to xtime/lost_ticks).
   13.31   */
   13.32  
   13.33 -#include <linux/errno.h>
   13.34 -#include <linux/sched.h>
   13.35 -#include <linux/kernel.h>
   13.36 -#include <linux/param.h>
   13.37 -#include <linux/string.h>
   13.38 -#include <linux/mm.h>
   13.39 -#include <linux/interrupt.h>
   13.40 -#include <linux/time.h>
   13.41 -#include <linux/delay.h>
   13.42 -#include <linux/init.h>
   13.43 -#include <linux/smp.h>
   13.44 -
   13.45 -#include <asm/io.h>
   13.46  #include <asm/smp.h>
   13.47  #include <asm/irq.h>
   13.48  #include <asm/msr.h>
   13.49 @@ -51,94 +60,110 @@
   13.50  #include <asm/uaccess.h>
   13.51  #include <asm/processor.h>
   13.52  
   13.53 -#include <linux/mc146818rtc.h>
   13.54 -#include <linux/timex.h>
   13.55 -#include <linux/config.h>
   13.56 -
   13.57 +#include <asm/div64.h>
   13.58  #include <asm/hypervisor.h>
   13.59  
   13.60 +#include <linux/kernel.h>
   13.61 +#include <linux/interrupt.h>
   13.62 +#include <linux/time.h>
   13.63 +#include <linux/init.h>
   13.64 +#include <linux/smp.h>
   13.65  #include <linux/irq.h>
   13.66  
   13.67 -
   13.68 -unsigned long cpu_khz;	/* Detected as we calibrate the TSC */
   13.69 -
   13.70 -/* Cached *multiplier* to convert TSC counts to microseconds.
   13.71 - * (see the equation below).
   13.72 - * Equal to 2^32 * (1 / (clocks per usec) ).
   13.73 - * Initialized in time_init.
   13.74 - */
   13.75 -unsigned long fast_gettimeoffset_quotient;
   13.76 -
   13.77 -extern rwlock_t xtime_lock;
   13.78 -extern unsigned long wall_jiffies;
   13.79 +#undef XENO_TIME_DEBUG	/* adds sanity checks and periodic printouts */
   13.80  
   13.81  spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
   13.82 -
   13.83 -static inline unsigned long ticks_to_secs(unsigned long long ticks)
   13.84 -{
   13.85 -    unsigned long lo, hi;
   13.86 -    unsigned long little_ticks;
   13.87 -
   13.88 -    little_ticks = ticks /* XXX URK! XXX / 1000000ULL */;
   13.89 +extern rwlock_t xtime_lock;
   13.90  
   13.91 -    __asm__ __volatile__ (
   13.92 -        "mull %2"
   13.93 -        : "=a" (lo), "=d" (hi)
   13.94 -        : "rm" (fast_gettimeoffset_quotient), "0" (little_ticks) );
   13.95 +unsigned long cpu_khz;	/* get this from Xen, used elsewhere */
   13.96 +static spinlock_t hyp_stime_lock = SPIN_LOCK_UNLOCKED;
   13.97 +static spinlock_t hyp_wctime_lock = SPIN_LOCK_UNLOCKED;
   13.98  
   13.99 -    return(hi);
  13.100 -}
  13.101 -
  13.102 -/* NB. Only 32 bits of ticks are considered here. */
  13.103 -static inline unsigned long ticks_to_us(unsigned long ticks)
  13.104 -{
  13.105 -    unsigned long lo, hi;
  13.106 +static u32 st_scale_f;
  13.107 +static u32 st_scale_i;
  13.108 +static u32 shadow_st_pcc;
  13.109 +static s64 shadow_st;
  13.110  
  13.111 -    __asm__ __volatile__ (
  13.112 -        "mull %2"
  13.113 -        : "=a" (lo), "=d" (hi)
  13.114 -        : "rm" (fast_gettimeoffset_quotient), "0" (ticks) );
  13.115 -
  13.116 -    return(hi);
  13.117 -}
  13.118 -
  13.119 -static long long get_s_time(void)
  13.120 +/*
  13.121 + * System time.
  13.122 + * Although the rest of the Linux kernel doesn't know about this, we
  13.123 + * we use it to extrapolate passage of wallclock time.
  13.124 + * We need to read the values from the shared info page "atomically" 
  13.125 + * and use the cycle counter value as the "version" number. Clashes
  13.126 + * should be very rare.
  13.127 + */
  13.128 +static inline long long get_s_time(void)
  13.129  {
  13.130 -    u32 	  delta, low, pcc;
  13.131 -	long long now;
  13.132 -	long long incr;
  13.133 +	unsigned long flags;
  13.134 +    u32           delta_tsc, low, pcc;
  13.135 +	u64           delta;
  13.136 +	s64           now;
  13.137 +
  13.138 +	spin_lock_irqsave(&hyp_stime_lock, flags);
  13.139  
  13.140 -	/* read two values (pcc, now) "atomically" */
  13.141 -again:
  13.142      pcc = HYPERVISOR_shared_info->st_timestamp;
  13.143 -    now = HYPERVISOR_shared_info->system_time;
  13.144 -	if (HYPERVISOR_shared_info->st_timestamp != pcc) goto again;
  13.145 +	mb();	
  13.146 +	if (pcc != shadow_st_pcc) {
  13.147 +st_again:
  13.148 +		shadow_st_pcc = HYPERVISOR_shared_info->st_timestamp;
  13.149 +		shadow_st     = HYPERVISOR_shared_info->system_time;
  13.150 +		pcc = HYPERVISOR_shared_info->st_timestamp;
  13.151 +		mb();
  13.152 +		if (pcc != shadow_st_pcc)
  13.153 +			goto st_again;
  13.154 +	}
  13.155  
  13.156 +    now = shadow_st;
  13.157      /* only use bottom 32bits of TSC. This should be sufficient */
  13.158  	rdtscl(low);
  13.159 -    delta = low - pcc;
  13.160 +    delta_tsc = low - pcc;
  13.161 +	delta = ((u64)delta_tsc * st_scale_f);
  13.162 +	delta >>= 32;
  13.163 +	delta += ((u64)delta_tsc * st_scale_i);
  13.164 +	spin_unlock_irqrestore(&hyp_time_lock, flags);
  13.165 +    return now + delta; 
  13.166  
  13.167 -	incr = ((long long)(ticks_to_us(delta)*1000));
  13.168 -    return now + incr; 
  13.169  }
  13.170  #define NOW()				((long long)get_s_time())
  13.171  
  13.172  /*
  13.173 - * This version of gettimeofday has microsecond resolution
  13.174 - * and better than microsecond precision on fast x86 machines with TSC.
  13.175 + * Wallclock time.
  13.176 + * Based on what the hypervisor tells us, extrapolated using system time.
  13.177 + * Again need to read a number of values from the shared page "atomically".
  13.178 + * this time using a version number.
  13.179   */
  13.180 +static u32        shadow_wc_version=0;
  13.181 +static long       shadow_tv_sec;
  13.182 +static long       shadow_tv_usec;
  13.183 +static long long  shadow_wc_timestamp;
  13.184  void do_gettimeofday(struct timeval *tv)
  13.185  {
  13.186 -    unsigned long flags;
  13.187 -    unsigned long usec, sec;
  13.188 +	unsigned long flags;
  13.189 +    long          usec, sec;
  13.190 +	u32	          version;
  13.191 +	u64           now;
  13.192  
  13.193 -    read_lock_irqsave(&xtime_lock, flags);
  13.194 +	spin_lock_irqsave(&hyp_wctime_lock, flags);
  13.195  
  13.196 -	usec  = ((unsigned long)(NOW()-HYPERVISOR_shared_info->wc_timestamp))/1000;
  13.197 -	sec   = HYPERVISOR_shared_info->tv_sec;
  13.198 -	usec += HYPERVISOR_shared_info->tv_usec;
  13.199 +	version = HYPERVISOR_shared_info->wc_version;
  13.200 +	mb();
  13.201 +	if (version != shadow_wc_version) {
  13.202 +	wc_again:
  13.203 +		shadow_wc_version   = HYPERVISOR_shared_info->wc_version;
  13.204 +		shadow_tv_sec       = HYPERVISOR_shared_info->tv_sec;
  13.205 +		shadow_tv_usec      = HYPERVISOR_shared_info->tv_usec;
  13.206 +		shadow_wc_timestamp = HYPERVISOR_shared_info->wc_timestamp;
  13.207 +		shadow_wc_version   = HYPERVISOR_shared_info->wc_version;
  13.208 +		version =  HYPERVISOR_shared_info->wc_version;
  13.209 +		mb();
  13.210 +		if (version != shadow_wc_version)
  13.211 +			goto wc_again;
  13.212 +	}
  13.213  
  13.214 -	read_unlock_irqrestore(&xtime_lock, flags);
  13.215 +	now   = NOW();
  13.216 +	usec  = ((unsigned long)(now-shadow_wc_timestamp))/1000;
  13.217 +	sec   = shadow_tv_sec;
  13.218 +	usec += shadow_tv_usec;
  13.219  
  13.220      while ( usec >= 1000000 ) 
  13.221      {
  13.222 @@ -148,11 +173,39 @@ void do_gettimeofday(struct timeval *tv)
  13.223  
  13.224      tv->tv_sec = sec;
  13.225      tv->tv_usec = usec;
  13.226 +
  13.227 +	spin_unlock_irqrestore(&hyp_time_lock, flags);
  13.228 +
  13.229 +#ifdef XENO_TIME_DEBUG
  13.230 +	{
  13.231 +		static long long old_now=0;
  13.232 +		static long long wct=0, old_wct=0;
  13.233 +
  13.234 +		/* This debug code checks if time increase over two subsequent calls */
  13.235 +		wct=(((long long)sec) * 1000000) + usec;
  13.236 +		/* wall clock time going backwards */
  13.237 +		if ((wct < old_wct) ) {	
  13.238 +			printk("Urgh1: wc diff=%6ld, usec = %ld (0x%lX)\n",
  13.239 +				   (long)(wct-old_wct), usec, usec);		
  13.240 +			printk("       st diff=%lld cur st=0x%016llX old st=0x%016llX\n",
  13.241 +				   now-old_now, now, old_now);
  13.242 +		}
  13.243 +
  13.244 +		/* system time going backwards */
  13.245 +		if (now<=old_now) {
  13.246 +			printk("Urgh2: st diff=%lld cur st=0x%016llX old st=0x%016llX\n",
  13.247 +				   now-old_now, now, old_now);
  13.248 +		}
  13.249 +		old_wct  = wct;
  13.250 +		old_now  = now;
  13.251 +	}
  13.252 +#endif
  13.253 +
  13.254  }
  13.255  
  13.256  void do_settimeofday(struct timeval *tv)
  13.257  {
  13.258 -/* XXX RN: shoudl do something special here for dom0 */
  13.259 +/* XXX RN: should do something special here for dom0 */
  13.260  #if 0
  13.261      write_lock_irq(&xtime_lock);
  13.262      /*
  13.263 @@ -181,25 +234,68 @@ void do_settimeofday(struct timeval *tv)
  13.264  
  13.265  
  13.266  /*
  13.267 - * timer_interrupt() needs to keep up the real-time clock,
  13.268 - * as well as call the "do_timer()" routine every clocktick
  13.269 + * Timer ISR. 
  13.270 + * Unlike normal Linux these don't come in at a fixed rate of HZ. 
  13.271 + * In here we wrok out how often it should have been called and then call
  13.272 + * the architecture independent part (do_timer()) the appropriate number of
  13.273 + * times. A bit of a nasty hack, to keep the "other" notion of wallclock time
  13.274 + * happy.
  13.275   */
  13.276 -static inline void do_timer_interrupt(
  13.277 -    int irq, void *dev_id, struct pt_regs *regs)
  13.278 +static long long us_per_tick=1000000/HZ;
  13.279 +static long long last_irq;
  13.280 +static inline void do_timer_interrupt(int irq, void *dev_id,
  13.281 +									  struct pt_regs *regs)
  13.282  {
  13.283 -    do_timer(regs);
  13.284 +	struct timeval tv;
  13.285 +	long long time, delta;
  13.286 +
  13.287 +#ifdef XENO_TIME_DEBUG
  13.288 +	static u32 foo_count = 0;
  13.289 +	foo_count++;		
  13.290 +	if (foo_count>= 10000) {
  13.291 +		s64 n = NOW();
  13.292 +		struct timeval tv;
  13.293 +		do_gettimeofday(&tv);
  13.294 +		printk("0x%08X%08X %ld:%ld\n",
  13.295 +			   (u32)(n>>32), (u32)n, tv.tv_sec, tv.tv_usec);
  13.296 +		foo_count = 0;
  13.297 +	}
  13.298 +#endif
  13.299 +
  13.300 +    /*
  13.301 +     * The next bit really sucks:
  13.302 +     * Linux not only uses do_gettimeofday() to keep a notion of
  13.303 +     * wallclock time, but also maintains the xtime struct and jiffies.
  13.304 +     * (Even worse some userland code accesses this via the sys_time()
  13.305 +     * system call)
  13.306 +     * Unfortunately, xtime is maintain in the architecture independent
  13.307 +     * part of the timer ISR (./kernel/timer.c sic!). So, although we have
  13.308 +     * perfectly valid notion of wallclock time from the hypervisor we here
  13.309 +     * fake missed timer interrupts so that the arch independent part of
  13.310 +     * the Timer ISR updates jiffies for us *and* once the bh gets run
  13.311 +     * updates xtime accordingly. Yuck!
  13.312 +     */
  13.313 +
  13.314 +	/* work out the number of jiffies past and update them */
  13.315 +	do_gettimeofday(&tv);
  13.316 +	time = (((long long)tv.tv_sec) * 1000000) + tv.tv_usec;
  13.317 +	delta = time - last_irq;
  13.318 +	if (delta <= 0) {
  13.319 +		printk ("Timer ISR: Time went backwards: %lld\n", delta);
  13.320 +		return;
  13.321 +	}
  13.322 +	while (delta >= us_per_tick) {
  13.323 +		do_timer(regs);
  13.324 +		delta    -= us_per_tick;
  13.325 +		last_irq += us_per_tick;
  13.326 +	}
  13.327 +
  13.328  #if 0
  13.329      if (!user_mode(regs))
  13.330          x86_do_profile(regs->eip);
  13.331  #endif
  13.332  }
  13.333  
  13.334 -
  13.335 -/*
  13.336 - * This is the same as the above, except we _also_ save the current
  13.337 - * Time Stamp Counter value at the time of the timer interrupt, so that
  13.338 - * we later on can estimate the time of day more exactly.
  13.339 - */
  13.340  static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  13.341  {
  13.342      write_lock(&xtime_lock);
  13.343 @@ -216,42 +312,32 @@ static struct irqaction irq_timer = {
  13.344      NULL
  13.345  };
  13.346  
  13.347 -
  13.348 -
  13.349 -/* Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset(). */
  13.350 -static unsigned long __init calibrate_tsc(void)
  13.351 -{
  13.352 -    unsigned long quo, rem;
  13.353 -
  13.354 -    /* quotient == (1000 * 2^32) / ticks_per ms */
  13.355 -    __asm__ __volatile__ (
  13.356 -        "divl %2"
  13.357 -        : "=a" (quo), "=d" (rem)
  13.358 -        : "r" (HYPERVISOR_shared_info->ticks_per_ms), "0" (0), "1" (1000) );
  13.359 -
  13.360 -    return(quo);
  13.361 -}
  13.362 -
  13.363  void __init time_init(void)
  13.364  {
  13.365      unsigned long long alarm;
  13.366 -	
  13.367 -    fast_gettimeoffset_quotient = calibrate_tsc();
  13.368 +	u64	cpu_freq = HYPERVISOR_shared_info->cpu_freq;
  13.369 +	u64 scale;
  13.370 +
  13.371 +	do_get_fast_time = do_gettimeofday;
  13.372 +
  13.373 +	cpu_khz = (u32)cpu_freq/1000;
  13.374 +	printk("Xen reported: %lu.%03lu MHz processor.\n", 
  13.375 +		   cpu_khz / 1000, cpu_khz % 1000);
  13.376  
  13.377 -    /* report CPU clock rate in Hz.
  13.378 -     * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
  13.379 -     * clock/second. Our precision is about 100 ppm.
  13.380 -     */
  13.381 -    {	
  13.382 -        unsigned long eax=0, edx=1000;
  13.383 -        __asm__ __volatile__
  13.384 -            ("divl %2"
  13.385 -             :"=a" (cpu_khz), "=d" (edx)
  13.386 -             :"r" (fast_gettimeoffset_quotient),
  13.387 -             "0" (eax), "1" (edx));
  13.388 -        printk("Detected %lu.%03lu MHz processor.\n", 
  13.389 -               cpu_khz / 1000, cpu_khz % 1000);
  13.390 -    }
  13.391 +	/*
  13.392 +     * calculate systemtime scaling factor
  13.393 +	 * XXX RN: have to cast cpu_freq to u32 limits it to 4.29 GHz. 
  13.394 +	 *     Get a better do_div!
  13.395 +	 */
  13.396 +	scale = 1000000000LL << 32;
  13.397 +	do_div(scale,(u32)cpu_freq);
  13.398 +	st_scale_f = scale & 0xffffffff;
  13.399 +	st_scale_i = scale >> 32;
  13.400 +	printk("System Time scale: %X %X\n",st_scale_i, st_scale_f);
  13.401 +
  13.402 +	do_gettimeofday(&xtime);
  13.403 +	last_irq = (((long long)xtime.tv_sec) * 1000000) + xtime.tv_usec;
  13.404 +	printk("last: %lld\n", last_irq);
  13.405  
  13.406      setup_irq(TIMER_IRQ, &irq_timer);
  13.407  
  13.408 @@ -260,12 +346,14 @@ void __init time_init(void)
  13.409       * 'domain' time. This means that clock sshould run at the correct
  13.410       * rate. For things like scheduling, it's not clear whether it
  13.411       * matters which sort of time we use.
  13.412 +	 * XXX RN: unimplemented.
  13.413       */
  13.414 +
  13.415      rdtscll(alarm);
  13.416 +#if 0
  13.417      alarm += (1000/HZ)*HYPERVISOR_shared_info->ticks_per_ms;
  13.418      HYPERVISOR_shared_info->wall_timeout   = alarm;
  13.419      HYPERVISOR_shared_info->domain_timeout = ~0ULL;
  13.420 +#endif
  13.421      clear_bit(_EVENT_TIMER, &HYPERVISOR_shared_info->events);
  13.422 -
  13.423 -	do_gettimeofday(&xtime);
  13.424  }