ia64/xen-unstable

changeset 183:db2f43dad304

bitkeeper revision 1.33.2.1 (3e4e80bfKovSGNhpWOvbDx2coqfMIw)

clean up of time/timer code: No PIT timer anymore and bugfixes to timer code
author rn@wyvis.camb.intel-research.net
date Sat Feb 15 18:02:39 2003 +0000 (2003-02-15)
parents 53760d4155cf
children 30e08b71439f
files xen-2.4.16/arch/i386/apic.c xen-2.4.16/arch/i386/i8259.c xen-2.4.16/arch/i386/setup.c xen-2.4.16/arch/i386/time.c xen-2.4.16/common/ac_timer.c xen-2.4.16/common/schedule.c xen-2.4.16/common/timer.c xen-2.4.16/include/asm-i386/time.h
line diff
     1.1 --- a/xen-2.4.16/arch/i386/apic.c	Fri Feb 14 13:18:19 2003 +0000
     1.2 +++ b/xen-2.4.16/arch/i386/apic.c	Sat Feb 15 18:02:39 2003 +0000
     1.3 @@ -697,37 +697,29 @@ int reprogram_ac_timer(s_time_t timeout)
     1.4   * the timer APIC on CPU does not go off every 10ms or so the linux 
     1.5   * timers loose accuracy, but that shouldn't be a problem.
     1.6   */
     1.7 -//static s_time_t last_cpu0_tirq = 0;
     1.8 +static s_time_t last_cpu0_tirq = 0;
     1.9  inline void smp_local_timer_interrupt(struct pt_regs * regs)
    1.10  {
    1.11  	int cpu = smp_processor_id();
    1.12 -	//s_time_t diff, now;
    1.13 +	s_time_t diff, now;
    1.14 +
    1.15  
    1.16      /* if CPU 0 do old timer stuff  */
    1.17  	if (cpu == 0) {
    1.18  
    1.19 -		/*
    1.20 -         * XXX RN: the following code should be moved here or somewhere
    1.21 -         * else. It's currently done using the 8255 timer interrupt, which
    1.22 -         * I'd like to disable. But, APIC initialisation relies on it,
    1.23 -         * e.g., timer interrupts coming in, jiffies going up, etc. Need to
    1.24 -         * clean this up. Also see ./arch/i386/time.c
    1.25 -         */
    1.26 -#if 0
    1.27 -		//update_time();/* XXX should use a timer for this */		
    1.28  		now = NOW();
    1.29  		diff = now - last_cpu0_tirq;
    1.30  
    1.31 -		/* this uses three 64bit divisions which should be avoided!! */
    1.32 -		if (diff >= MILLISECS(10)) {
    1.33 -			/* update jiffies */
    1.34 -			(*(unsigned long *)&jiffies) += diff / MILLISECS(10);
    1.35 +		if (diff <= 0) {
    1.36 +			printk ("System Time went backwards: %lld\n", diff);
    1.37 +			return;
    1.38 +		}
    1.39  
    1.40 -			/* do traditional linux timers */
    1.41 +		while (diff >= MILLISECS(10)) {
    1.42  			do_timer(regs);
    1.43 -			last_cpu0_tirq = now;
    1.44 +			diff           -= MILLISECS(10);
    1.45 +			last_cpu0_tirq += MILLISECS(10);
    1.46  		}
    1.47 -#endif
    1.48  	}
    1.49  	/* call accurate timer function */
    1.50  	do_ac_timer();
     2.1 --- a/xen-2.4.16/arch/i386/i8259.c	Fri Feb 14 13:18:19 2003 +0000
     2.2 +++ b/xen-2.4.16/arch/i386/i8259.c	Sat Feb 15 18:02:39 2003 +0000
     2.3 @@ -467,3 +467,15 @@ void __init init_IRQ(void)
     2.4  
     2.5      setup_irq(2, &irq2);
     2.6  }
     2.7 +
     2.8 +/*
     2.9 + * we only need the timer interrupt for callibrating the tsc<->time<->bus cycle
    2.10 + * mappings. After this all timeing related functions should be run of the 
    2.11 + * APIC timers. This function allows us to disable the 
    2.12 + */
    2.13 +void __init disable_pit(void)
    2.14 +{
    2.15 +        printk("Disable PIT. Not needed anymore\n");
    2.16 +        /* This is not the most elegant way, but hey. */
    2.17 +        disable_irq(0);
    2.18 +}
     3.1 --- a/xen-2.4.16/arch/i386/setup.c	Fri Feb 14 13:18:19 2003 +0000
     3.2 +++ b/xen-2.4.16/arch/i386/setup.c	Sat Feb 15 18:02:39 2003 +0000
     3.3 @@ -280,6 +280,7 @@ void __init start_of_day(void)
     3.4      extern void tqueue_bh(void);
     3.5      extern void immediate_bh(void);
     3.6      extern void init_timervecs(void);
     3.7 +	extern void disable_pit(void);
     3.8  	extern void ac_timer_init(void);
     3.9      extern int  setup_network_devices(void);
    3.10      extern void net_init(void);
    3.11 @@ -329,8 +330,11 @@ void __init start_of_day(void)
    3.12                        * fall thru to 8259A if we have to (but slower).
    3.13                        */
    3.14  #endif
    3.15 +    initialize_keytable(); /* call back handling for key codes      */
    3.16 +
    3.17 +	disable_pit();		/* not needed anymore */
    3.18 +	ac_timer_init();    /* init accurate timers */
    3.19  	init_xeno_time();	/* initialise the time */
    3.20 -	ac_timer_init();    /* init accurate timers */
    3.21  	schedulers_start(); /* start scheduler for each CPU */
    3.22  
    3.23      sti();
    3.24 @@ -343,7 +347,7 @@ void __init start_of_day(void)
    3.25  #endif
    3.26      do_initcalls();
    3.27  
    3.28 -    initialize_keytable(); /* call back handling for key codes      */
    3.29 +
    3.30      initialize_serial();   /* setup serial 'driver' (for debugging) */
    3.31      initialize_keyboard(); /* setup keyboard (also for debugging)   */
    3.32  
     4.1 --- a/xen-2.4.16/arch/i386/time.c	Fri Feb 14 13:18:19 2003 +0000
     4.2 +++ b/xen-2.4.16/arch/i386/time.c	Sat Feb 15 18:02:39 2003 +0000
     4.3 @@ -31,6 +31,7 @@
     4.4  #include <xeno/init.h>
     4.5  #include <xeno/interrupt.h>
     4.6  #include <xeno/time.h>
     4.7 +#include <xeno/ac_timer.h>
     4.8  
     4.9  #include <asm/io.h>
    4.10  #include <xeno/smp.h>
    4.11 @@ -74,15 +75,12 @@ static inline void do_timer_interrupt(in
    4.12          spin_unlock(&i8259A_lock);
    4.13      }
    4.14  #endif
    4.15 -
    4.16 -	/* XXX RN: Want to remove this but APIC-SMP code seems to rely on it */
    4.17      do_timer(regs);
    4.18  }
    4.19  
    4.20  /*
    4.21 - * This is the same as the above, except we _also_ save the current
    4.22 - * Time Stamp Counter value at the time of the timer interrupt, so that
    4.23 - * we later on can estimate the time of day more exactly.
    4.24 + * This is only temporarily. Once the APIC s up and running this 
    4.25 + * timer interrupt is turned off.
    4.26   */
    4.27  static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    4.28  {
    4.29 @@ -303,8 +301,34 @@ void do_settimeofday(struct timeval *tv)
    4.30  /***************************************************************************
    4.31   * Update times
    4.32   ***************************************************************************/
    4.33 -/* update hypervisors notion of time */
    4.34 -void update_time(void) {
    4.35 +
    4.36 +/* update a domains notion of time */
    4.37 +void update_dom_time(shared_info_t *si)
    4.38 +{
    4.39 +	unsigned long flags;
    4.40 +
    4.41 +	spin_lock_irqsave(&stime_lock, flags);
    4.42 +	si->system_time  = stime_now;
    4.43 +	si->st_timestamp = stime_pcc;
    4.44 +	spin_unlock_irqrestore(&stime_lock, flags);
    4.45 +
    4.46 +	spin_lock_irqsave(&wctime_lock, flags);
    4.47 +	si->tv_sec       = wall_clock_time.tv_sec;
    4.48 +	si->tv_usec      = wall_clock_time.tv_usec;
    4.49 +	si->wc_timestamp = wctime_st;
    4.50 +	si->wc_version++;
    4.51 +	spin_unlock_irqrestore(&wctime_lock, flags);	
    4.52 +
    4.53 +	TRC(printk(" 0x%08X%08X\n", (u32)(wctime_st>>32), (u32)wctime_st));
    4.54 +}
    4.55 +
    4.56 +/*
    4.57 + * Update hypervisors notion of time
    4.58 + * This is done periodically of it's own timer
    4.59 + */
    4.60 +static struct ac_timer update_timer;
    4.61 +static void update_time(unsigned long foo)
    4.62 +{
    4.63  	unsigned long  flags;
    4.64  	u32		       new_pcc;
    4.65  	s_time_t       new_st;
    4.66 @@ -336,26 +360,12 @@ void update_time(void) {
    4.67  	TRC(printk("TIME[%02d] update time: stime_now=%lld now=%lld,wct=%ld:%ld\n",
    4.68  			   smp_processor_id(), stime_now, new_st, wall_clock_time.tv_sec,
    4.69  			   wall_clock_time.tv_usec));
    4.70 -}
    4.71 -
    4.72 -/* update a domains notion of time */
    4.73 -void update_dom_time(shared_info_t *si)
    4.74 -{
    4.75 -	unsigned long flags;
    4.76 -
    4.77 -	spin_lock_irqsave(&stime_lock, flags);
    4.78 -	si->system_time  = stime_now;
    4.79 -	si->st_timestamp = stime_pcc;
    4.80 -	spin_unlock_irqrestore(&stime_lock, flags);
    4.81 -
    4.82 -	spin_lock_irqsave(&wctime_lock, flags);
    4.83 -	si->tv_sec       = wall_clock_time.tv_sec;
    4.84 -	si->tv_usec      = wall_clock_time.tv_usec;
    4.85 -	si->wc_timestamp = wctime_st;
    4.86 -	si->wc_version++;
    4.87 -	spin_unlock_irqrestore(&wctime_lock, flags);	
    4.88 -
    4.89 -	TRC(printk(" 0x%08X%08X\n", (u32)(wctime_st>>32), (u32)wctime_st));
    4.90 +	/* reload timer */
    4.91 + again:
    4.92 +	update_timer.expires  = new_st + MILLISECS(200);
    4.93 +	if(add_ac_timer(&update_timer) == 1) {
    4.94 +		goto again;
    4.95 +	}
    4.96  }
    4.97  
    4.98  /***************************************************************************
    4.99 @@ -364,13 +374,15 @@ void update_dom_time(shared_info_t *si)
   4.100   ***************************************************************************/
   4.101  int __init init_xeno_time()
   4.102  {
   4.103 -	int cpu = smp_processor_id();
   4.104 -	u32	cpu_cycle;	 /* time of one cpu cyle in pico-seconds */
   4.105 -	u64 scale;
   4.106 +	int      cpu = smp_processor_id();
   4.107 +	u32	     cpu_cycle;  /* time of one cpu cyle in pico-seconds */
   4.108 +	u64      scale;      /* scale factor  */
   4.109  
   4.110  	spin_lock_init(&stime_lock);
   4.111  	spin_lock_init(&wctime_lock);
   4.112  
   4.113 +	printk("Init Time[%02d]:\n", cpu);
   4.114 +
   4.115  	/* System Time */
   4.116  	cpu_cycle   = (u32) (1000000000LL/cpu_khz); /* in pico seconds */
   4.117  	scale = 1000000000LL << 32;
   4.118 @@ -378,24 +390,30 @@ int __init init_xeno_time()
   4.119  	st_scale_f = scale & 0xffffffff;
   4.120  	st_scale_i = scale >> 32;
   4.121  
   4.122 -	stime_now = (s_time_t)0;
   4.123 -	rdtscl(stime_pcc);
   4.124 -	
   4.125 -	printk("Init Time[%02d]:\n", cpu);
   4.126 -	printk(".... System Time: %lldns\n", NOW());
   4.127 -	printk(".....cpu_cycle:   %u ps\n", cpu_cycle);
   4.128 -	printk(".... st_scale_f:  %X\n",   st_scale_f);
   4.129 -	printk(".... st_scale_i:  %X\n",   st_scale_i);
   4.130 -	printk(".... stime_pcc:   %u\n",   stime_pcc);
   4.131 -
   4.132  	/* Wall Clock time */
   4.133  	wall_clock_time.tv_sec  = get_cmos_time();
   4.134  	wall_clock_time.tv_usec = 0;
   4.135 +
   4.136 +	/* set starting times */
   4.137 +	stime_now = (s_time_t)0;
   4.138 +	rdtscl(stime_pcc);
   4.139  	wctime_st = NOW();
   4.140  
   4.141 +	/* start timer to update time periodically */
   4.142 +	init_ac_timer(&update_timer);
   4.143 +	update_timer.function = &update_time;
   4.144 +	update_time(0);
   4.145 +
   4.146 +	printk(".... System Time: %lldns\n", NOW());
   4.147 +	printk(".....cpu_cycle:   %u ps\n",  cpu_cycle);
   4.148 +	printk(".... st_scale_f:  %X\n",     st_scale_f);
   4.149 +	printk(".... st_scale_i:  %X\n",     st_scale_i);
   4.150 +	printk(".... stime_pcc:   %u\n",     stime_pcc);
   4.151 +
   4.152  	printk(".... Wall Clock:  %lds %ldus\n", wall_clock_time.tv_sec,
   4.153  		   wall_clock_time.tv_usec);
   4.154  	printk(".... wctime_st:   %lld\n", wctime_st);
   4.155 +
   4.156  	return 0;
   4.157  }
   4.158  
     5.1 --- a/xen-2.4.16/common/ac_timer.c	Fri Feb 14 13:18:19 2003 +0000
     5.2 +++ b/xen-2.4.16/common/ac_timer.c	Sat Feb 15 18:02:39 2003 +0000
     5.3 @@ -29,6 +29,7 @@
     5.4  
     5.5  #include <xeno/time.h>
     5.6  #include <xeno/ac_timer.h>
     5.7 +#include <xeno/keyhandler.h>
     5.8  
     5.9  #include <asm/system.h>
    5.10  #include <asm/desc.h>
    5.11 @@ -80,8 +81,6 @@ int add_ac_timer(struct ac_timer *timer)
    5.12  {
    5.13  	int 			 cpu = smp_processor_id();
    5.14  	unsigned long 	 flags;
    5.15 -	struct list_head *tmp, *prev;
    5.16 -	struct ac_timer	 *t;
    5.17  	s_time_t		 now;
    5.18  
    5.19  	/* sanity checks */
    5.20 @@ -96,42 +95,54 @@ int add_ac_timer(struct ac_timer *timer)
    5.21  			   (u32)(timer->expires>>32), (u32)timer->expires);
    5.22  		return 1;
    5.23  	}
    5.24 -
    5.25 -	local_irq_save(flags);
    5.26 -
    5.27 -	/* check if timer would be inserted at start of list */
    5.28 -	if ((list_empty(&ac_timers[cpu].timers)) ||
    5.29 -		(timer->expires <
    5.30 -		(list_entry(&ac_timers[cpu].timers,
    5.31 -					struct ac_timer, timer_list))->expires)) {
    5.32 -
    5.33 -		TRC(printk("ACT  [%02d] add(): add at head\n", cpu));
    5.34 +	spin_lock_irqsave(&ac_timers[cpu].lock, flags);
    5.35 +	/*
    5.36 +     * Add timer to the list. If it gets added to the front we have to
    5.37 +     * reprogramm the timer
    5.38 +     */
    5.39 +	if (list_empty(&ac_timers[cpu].timers)) {
    5.40  		/* Reprogramm and add to head of list */
    5.41  		if (!reprogram_ac_timer(timer->expires)) {
    5.42  			/* failed */
    5.43 -			TRC(printk("ACT  [%02d] add(): add at head failed\n", cpu));
    5.44 -			local_irq_restore(flags);
    5.45 +			printk("ACT  [%02d] add(): add at head failed\n", cpu);
    5.46 +			spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
    5.47  			return 1;
    5.48  		}
    5.49  		list_add(&timer->timer_list, &ac_timers[cpu].timers);
    5.50 -		
    5.51 +		TRC(printk("ACT  [%02d] add(0x%08X%08X): added at head\n", cpu,
    5.52 +				   (u32)(timer->expires>>32), (u32)timer->expires));
    5.53  	} else {
    5.54 -		/* find correct entry and add timer */
    5.55 -		prev = &ac_timers[cpu].timers;
    5.56 -		list_for_each(tmp, &ac_timers[cpu].timers) {
    5.57 -			t = list_entry(tmp, struct ac_timer, timer_list);
    5.58 -			if (t->expires < timer->expires) {
    5.59 -				list_add(&timer->timer_list, prev);
    5.60 -				TRC(printk("ACT  [%02d] add(): added between %lld and %lld\n",
    5.61 +		struct list_head *pos;
    5.62 +		struct ac_timer	 *t;
    5.63 +		for (pos = ac_timers[cpu].timers.next;
    5.64 +			 pos != &ac_timers[cpu].timers;
    5.65 +			 pos = pos->next) {
    5.66 +			t = list_entry(pos, struct ac_timer, timer_list);
    5.67 +			if (t->expires > timer->expires)
    5.68 +				break;
    5.69 +		}
    5.70 +
    5.71 +		if (pos->prev == &ac_timers[cpu].timers) {
    5.72 +			/* added to head, reprogramm timer */
    5.73 +			if (!reprogram_ac_timer(timer->expires)) {
    5.74 +				/* failed */
    5.75 +				TRC(printk("ACT  [%02d] add(): add at head failed\n", cpu));
    5.76 +				spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
    5.77 +				return 1;
    5.78 +			}
    5.79 +			list_add (&(timer->timer_list), pos->prev);
    5.80 +			TRC(printk("ACT  [%02d] add(0x%08X%08X): added at head\n", cpu,
    5.81 +					   (u32)(timer->expires>>32), (u32)timer->expires));
    5.82 +		} else {
    5.83 +			list_add (&(timer->timer_list), pos->prev);
    5.84 +			TRC(printk("ACT  [%02d] add(0x%08X%08X): add < exp=0x%08X%08X\n",
    5.85  					   cpu,
    5.86 -					   list_entry(prev,struct ac_timer,timer_list)->expires,
    5.87 -					   list_entry(tmp,struct ac_timer,timer_list)->expires));
    5.88 -				break;
    5.89 -			}
    5.90 -			prev = tmp;
    5.91 +					   (u32)(timer->expires>>32), (u32)timer->expires,
    5.92 +					   (u32)(t->expires>>32), (u32)t->expires));
    5.93  		}
    5.94 +
    5.95  	}
    5.96 -	local_irq_restore(flags);
    5.97 +	spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
    5.98  	return 0;
    5.99  }
   5.100  
   5.101 @@ -158,16 +169,17 @@ static int detach_ac_timer(struct ac_tim
   5.102   */
   5.103  int rem_ac_timer(struct ac_timer *timer)
   5.104  {
   5.105 -	int res;
   5.106 +	int 		  cpu = smp_processor_id();
   5.107 +	int           res;
   5.108  	unsigned long flags;
   5.109 -	TRC(int cpu = smp_processor_id());
   5.110  
   5.111  	TRC(printk("ACT  [%02d] remove(): timo=%lld \n", cpu, timer->expires));
   5.112  	/* sanity checks */
   5.113  
   5.114 -	local_irq_save(flags);
   5.115 +	spin_lock_irqsave(&ac_timers[cpu].lock, flags);
   5.116  	res = detach_ac_timer(timer);	
   5.117 -	local_irq_restore(flags);
   5.118 +	spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
   5.119 +
   5.120  	return res;
   5.121  }
   5.122  
   5.123 @@ -199,7 +211,7 @@ void do_ac_timer(void)
   5.124  	struct ac_timer	 *t;
   5.125  	struct list_head *tmp;
   5.126  
   5.127 -	local_irq_save(flags);
   5.128 +	spin_lock_irqsave(&ac_timers[cpu].lock, flags);
   5.129  
   5.130   do_timer_again:
   5.131  
   5.132 @@ -210,7 +222,7 @@ void do_ac_timer(void)
   5.133      /* empty time list  */
   5.134  	if (list_empty(&ac_timers[cpu].timers)) {
   5.135  		printk("ACT[%02d] do_ac_timer(): timer irq without timer\n", cpu);
   5.136 -		local_irq_restore(flags);
   5.137 +		spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
   5.138  		return;
   5.139  	}
   5.140  
   5.141 @@ -219,6 +231,8 @@ void do_ac_timer(void)
   5.142  	t = list_entry(ac_timers[cpu].timers.next, struct ac_timer, timer_list);
   5.143  	detach_ac_timer(t);
   5.144  
   5.145 +	spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
   5.146 +
   5.147  
   5.148  #ifdef AC_TIMER_STATS
   5.149  	{
   5.150 @@ -258,6 +272,9 @@ void do_ac_timer(void)
   5.151  
   5.152  	/* check if there are other timer functions on the list */
   5.153  	now = NOW();
   5.154 +
   5.155 +	spin_lock_irqsave(&ac_timers[cpu].lock, flags);
   5.156 +
   5.157  	if (!list_empty(&ac_timers[cpu].timers)) {
   5.158  		list_for_each(tmp, &ac_timers[cpu].timers) {
   5.159  			t = list_entry(tmp, struct ac_timer, timer_list);
   5.160 @@ -265,8 +282,10 @@ void do_ac_timer(void)
   5.161  					   cpu, now, t->expires));
   5.162  			if (t->expires <= now) {
   5.163  				detach_ac_timer(t);
   5.164 +				spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
   5.165  				if (t->function != NULL)
   5.166  					t->function(t->data);
   5.167 +				spin_lock_irqsave(&ac_timers[cpu].lock, flags);
   5.168  				now = NOW();
   5.169  			} else {
   5.170  				TRC(printk("ACT  [%02d] do(): break1\n", cpu));
   5.171 @@ -286,7 +305,47 @@ void do_ac_timer(void)
   5.172  			}
   5.173  		}
   5.174  	}
   5.175 -	local_irq_restore(flags);
   5.176 +	spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
   5.177 +	TRC(printk("ACT  [%02d] do(): end\n", cpu));
   5.178 +}
   5.179 +
   5.180 +/*
   5.181 + * debug dump_queue
   5.182 + * arguments: queue head, name of queue
   5.183 + */
   5.184 +static void dump_tqueue(struct list_head *queue, char *name)
   5.185 +{
   5.186 +    struct list_head *list;
   5.187 +    int loop = 0;
   5.188 +	struct ac_timer	 *t;
   5.189 +
   5.190 +    printk ("QUEUE %s %lx   n: %lx, p: %lx\n", name,  (unsigned long)queue,
   5.191 +            (unsigned long) queue->next, (unsigned long) queue->prev);
   5.192 +    list_for_each (list, queue) {
   5.193 +		t = list_entry(list, struct ac_timer, timer_list);
   5.194 +        printk ("  %s %d : %lx ex=0x%08X%08X %lu  n: %lx, p: %lx\n",
   5.195 +				name, loop++, 
   5.196 +                (unsigned long)list,
   5.197 +				(u32)(t->expires>>32), (u32)t->expires, t->data,
   5.198 +                (unsigned long)list->next, (unsigned long)list->prev);
   5.199 +    }
   5.200 +    return; 
   5.201 +}
   5.202 +
   5.203 +
   5.204 +static void dump_timerq(u_char key, void *dev_id, struct pt_regs *regs)
   5.205 +{
   5.206 +    u_long   flags; 
   5.207 +	s_time_t now = NOW();
   5.208 +
   5.209 +    printk("Dumping ac_timer queues for cpu 0: NOW=0x%08X%08X\n",
   5.210 +		   (u32)(now>>32), (u32)now); 
   5.211 +	
   5.212 +    spin_lock_irqsave(&ac_timers[0].lock, flags);
   5.213 +    dump_tqueue(&ac_timers[0].timers, "ac_time"); 
   5.214 +    spin_unlock_irqrestore(&ac_timers[0].lock, flags);
   5.215 +	printk("\n");
   5.216 +    return; 
   5.217  }
   5.218  
   5.219  /*
   5.220 @@ -303,5 +362,6 @@ void __init ac_timer_init(void)
   5.221  		INIT_LIST_HEAD(&ac_timers[i].timers);
   5.222  		spin_lock_init(&ac_timers[i].lock);
   5.223      }
   5.224 -	/* ac_timer_debug(0); */
   5.225 +
   5.226 +	add_key_handler('a', dump_timerq, "dump ac_timer queues");
   5.227  }
     6.1 --- a/xen-2.4.16/common/schedule.c	Fri Feb 14 13:18:19 2003 +0000
     6.2 +++ b/xen-2.4.16/common/schedule.c	Sat Feb 15 18:02:39 2003 +0000
     6.3 @@ -282,6 +282,9 @@ asmlinkage void schedule(void)
     6.4      return;
     6.5  }
     6.6  
     6.7 +/*
     6.8 + * The scheduling timer.
     6.9 + */
    6.10  static __cacheline_aligned int count[NR_CPUS];
    6.11  static void sched_timer(unsigned long foo)
    6.12  {
    6.13 @@ -290,14 +293,35 @@ static void sched_timer(unsigned long fo
    6.14  	s_time_t			now;
    6.15  	int 				res;
    6.16  
    6.17 +	/* reschedule after each 5 ticks */
    6.18  	if (count[cpu] >= 5) {
    6.19  		set_bit(_HYP_EVENT_NEED_RESCHED, &curr->hyp_events);
    6.20  		count[cpu] = 0;
    6.21 -		if (cpu == 0)
    6.22 -			update_time(); /* XXX RN: Should be moved on its own timer */
    6.23  	}
    6.24  	count[cpu]++;
    6.25  
    6.26 +	/*
    6.27 +     * deliver virtual timer interrups to domains if we are CPU 0
    6.28 +     * XXX RN: We don't have a per CPU list of domains yet. Otherwise 
    6.29 +     * would use that. Plus, this should be removed anyway once
    6.30 +     * Domains "know" about virtual time and timeouts. But, it's better
    6.31 +     * here then where it was before.
    6.32 +     */
    6.33 +	if (cpu == 0) {
    6.34 +		struct task_struct *p;
    6.35 +		unsigned long cpu_mask = 0;
    6.36 +
    6.37 +		/* send virtual timer interrupt */
    6.38 +		read_lock(&tasklist_lock);
    6.39 +		p = &idle0_task;
    6.40 +		do {
    6.41 +			cpu_mask |= mark_guest_event(p, _EVENT_TIMER);
    6.42 +		}
    6.43 +		while ( (p = p->next_task) != &idle0_task );
    6.44 +		read_unlock(&tasklist_lock);
    6.45 +		guest_event_notify(cpu_mask);
    6.46 +	}
    6.47 +
    6.48   again:
    6.49  	now = NOW();
    6.50  	s_timer[cpu].expires  = now + MILLISECS(10);
    6.51 @@ -310,6 +334,8 @@ static void sched_timer(unsigned long fo
    6.52  		goto again;
    6.53  
    6.54  }
    6.55 +
    6.56 +
    6.57  /*
    6.58   * Initialise the data structures
    6.59   */
     7.1 --- a/xen-2.4.16/common/timer.c	Fri Feb 14 13:18:19 2003 +0000
     7.2 +++ b/xen-2.4.16/common/timer.c	Sat Feb 15 18:02:39 2003 +0000
     7.3 @@ -586,27 +586,12 @@ void timer_bh(void)
     7.4  
     7.5  void do_timer(struct pt_regs *regs)
     7.6  {
     7.7 -    struct task_struct *p;
     7.8 -    shared_info_t *s;
     7.9 -    unsigned long cpu_mask = 0;
    7.10  
    7.11      (*(unsigned long *)&jiffies)++;
    7.12  
    7.13      if ( !using_apic_timer )
    7.14          update_process_times(user_mode(regs));
    7.15  
    7.16 -	/* XXX RN: Move this for virtual domain time timer interrupts */
    7.17 -    read_lock(&tasklist_lock);
    7.18 -    p = &idle0_task;
    7.19 -    do {
    7.20 -        s = p->shared_info;
    7.21 -        cpu_mask |= mark_guest_event(p, _EVENT_TIMER);
    7.22 -    }
    7.23 -    while ( (p = p->next_task) != &idle0_task );
    7.24 -    read_unlock(&tasklist_lock);
    7.25 -
    7.26 -    guest_event_notify(cpu_mask);
    7.27 -
    7.28      mark_bh(TIMER_BH);
    7.29      if (TQ_ACTIVE(tq_timer))
    7.30          mark_bh(TQUEUE_BH);
     8.1 --- a/xen-2.4.16/include/asm-i386/time.h	Fri Feb 14 13:18:19 2003 +0000
     8.2 +++ b/xen-2.4.16/include/asm-i386/time.h	Sat Feb 15 18:02:39 2003 +0000
     8.3 @@ -41,9 +41,6 @@ typedef s64      s_time_t;	     /* Syste
     8.4  extern  u32      stime_pcc;      /* cycle counter value at last timer irq */
     8.5  extern  s_time_t stime_now;      /* time in ns at last timer IRQ */
     8.6  
     8.7 -/* update time variables once in a while */
     8.8 -extern void update_time(void);
     8.9 -
    8.10  /*
    8.11   * Domain Virtual Time
    8.12   */