aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen-2.4.16/arch/i386/apic.c153
-rw-r--r--xen-2.4.16/common/ac_timer.c344
2 files changed, 229 insertions, 268 deletions
diff --git a/xen-2.4.16/arch/i386/apic.c b/xen-2.4.16/arch/i386/apic.c
index b967934e3c..9b999df951 100644
--- a/xen-2.4.16/arch/i386/apic.c
+++ b/xen-2.4.16/arch/i386/apic.c
@@ -218,9 +218,7 @@ int __init verify_local_APIC(void)
void __init sync_Arb_IDs(void)
{
- /*
- * Wait for idle.
- */
+ /* Wait for idle. */
apic_wait_icr_idle();
Dprintk("Synchronizing Arb IDs.\n");
@@ -508,11 +506,11 @@ void __init wait_8254_wraparound(void)
prev_count = curr_count;
curr_count = get_8254_timer_count();
delta = curr_count-prev_count;
- /*
- * This limit for delta seems arbitrary, but it isn't, it's
- * slightly above the level of error a buggy Mercury/Neptune
- * chipset timer can cause.
- */
+ /*
+ * This limit for delta seems arbitrary, but it isn't, it's slightly
+ * above the level of error a buggy Mercury/Neptune chipset timer can
+ * cause.
+ */
} while (delta < 300);
}
@@ -581,7 +579,7 @@ int __init calibrate_APIC_clock(void)
* counter running for calibration. */
__setup_APIC_LVTT(1000000000);
- /* The timer chip counts down to zero. Let's wait
+ /* The timer chip counts down to zero. Let's wait
* for a wraparound to start exact measurement:
* (the current tick might have been already half done) */
wait_8254_wraparound();
@@ -611,18 +609,18 @@ int __init calibrate_APIC_clock(void)
result/(1000000/HZ),
result%(1000000/HZ));
- cpu_freq = (u64)(((t2-t1)/LOOPS)*HZ);
+ cpu_freq = (u64)(((t2-t1)/LOOPS)*HZ);
- /* set up multipliers for accurate timer code */
- bus_freq = result*HZ;
- bus_cycle = (u32) (1000000000000LL/bus_freq); /* in pico seconds */
- bus_scale = (1000*262144)/bus_cycle;
+ /* set up multipliers for accurate timer code */
+ bus_freq = result*HZ;
+ bus_cycle = (u32) (1000000000000LL/bus_freq); /* in pico seconds */
+ bus_scale = (1000*262144)/bus_cycle;
- /* print results */
- printk("..... bus_freq = %u Hz\n", bus_freq);
- printk("..... bus_cycle = %u ps\n", bus_cycle);
- printk("..... bus_scale = %u \n", bus_scale);
- /* reset APIC to zero timeout value */
+ /* print results */
+ printk("..... bus_freq = %u Hz\n", bus_freq);
+ printk("..... bus_cycle = %u ps\n", bus_cycle);
+ printk("..... bus_scale = %u \n", bus_scale);
+ /* reset APIC to zero timeout value */
__setup_APIC_LVTT(0);
return result;
}
@@ -636,7 +634,7 @@ void __init setup_APIC_clocks (void)
printk("Using local APIC timer interrupts.\n");
using_apic_timer = 1;
__cli();
- /* calibrate CPU0 for CPU speed and BUS speed */
+ /* calibrate CPU0 for CPU speed and BUS speed */
bus_freq = calibrate_APIC_clock();
/* Now set up the timer for real. */
setup_APIC_timer((void *)bus_freq);
@@ -654,41 +652,38 @@ void __init setup_APIC_clocks (void)
*/
int reprogram_ac_timer(s_time_t timeout)
{
- int cpu = smp_processor_id();
- s_time_t now;
- s_time_t expire;
- u64 apic_tmict;
-
- now = NOW();
- expire = timeout - now; /* value from now */
-
-
- if (expire <= 0) {
- TRC(printk("APICT[%02d] Timeout in the past 0x%08X%08X > 0x%08X%08X\n",
- cpu, (u32)(now>>32), (u32)now,
- (u32)(timeout>>32),(u32)timeout));
- return 0; /* timeout value in the past */
- }
-
- /* conversion to bus units */
- apic_tmict = (((u64)bus_scale) * expire)>>18;
-
- if (apic_tmict >= 0xffffffff) {
- /* This is bad! */
- printk("APICT[%02d] Timeout value too large\n", cpu);
- apic_tmict = 0xffffffff;
- }
- if (apic_tmict == 0) {
- TRC(printk("APICT[%02d] timeout value too small\n", cpu));
- return 0;
- }
-
- /* programm timer */
- apic_write(APIC_TMICT, (unsigned long)apic_tmict);
-
- TRC(printk("APICT[%02d] reprog(): expire=%lld %u\n",
- cpu, expire, apic_tmict));
- return 1;
+ int cpu = smp_processor_id();
+ s_time_t now;
+ s_time_t expire;
+ u64 apic_tmict;
+
+ now = NOW();
+ expire = timeout - now; /* value from now */
+
+ if (expire <= 0) {
+ printk("APICT[%02d] Timeout in the past 0x%08X%08X > 0x%08X%08X\n",
+ cpu, (u32)(now>>32), (u32)now, (u32)(timeout>>32),(u32)timeout);
+ return 0; /* timeout value in the past */
+ }
+
+ /* conversion to bus units */
+ apic_tmict = (((u64)bus_scale) * expire)>>18;
+
+ if (apic_tmict >= 0xffffffff) {
+ printk("APICT[%02d] Timeout value too large\n", cpu);
+ apic_tmict = 0xffffffff;
+ }
+ if (apic_tmict == 0) {
+ printk("APICT[%02d] timeout value too small\n", cpu);
+ return 0;
+ }
+
+ /* programm timer */
+ apic_write(APIC_TMICT, (unsigned long)apic_tmict);
+
+ TRC(printk("APICT[%02d] reprog(): expire=%lld %u\n",
+ cpu, expire, apic_tmict));
+ return 1;
}
/*
@@ -702,29 +697,28 @@ int reprogram_ac_timer(s_time_t timeout)
static s_time_t last_cpu0_tirq = 0;
inline void smp_local_timer_interrupt(struct pt_regs * regs)
{
- int cpu = smp_processor_id();
- s_time_t diff, now;
-
+ int cpu = smp_processor_id();
+ s_time_t diff, now;
/* if CPU 0 do old timer stuff */
- if (cpu == 0) {
-
- now = NOW();
- diff = now - last_cpu0_tirq;
-
- if (diff <= 0) {
- printk ("System Time went backwards: %lld\n", diff);
- return;
- }
-
- while (diff >= MILLISECS(10)) {
- do_timer(regs);
- diff -= MILLISECS(10);
- last_cpu0_tirq += MILLISECS(10);
- }
- }
- /* call accurate timer function */
- do_ac_timer();
+ if (cpu == 0)
+ {
+ now = NOW();
+ diff = now - last_cpu0_tirq;
+
+ if (diff <= 0) {
+ printk ("System Time went backwards: %lld\n", diff);
+ return;
+ }
+
+ while (diff >= MILLISECS(10)) {
+ do_timer(regs);
+ diff -= MILLISECS(10);
+ last_cpu0_tirq += MILLISECS(10);
+ }
+ }
+ /* call accurate timer function */
+ do_ac_timer();
}
/*
@@ -747,9 +741,8 @@ void smp_apic_timer_interrupt(struct pt_regs * regs)
apic_timer_irqs[cpu]++;
/*
- * NOTE! We'd better ACK the irq immediately,
- * because timer handling can be slow.
- * XXX is this save?
+ * NOTE! We'd better ACK the irq immediately, because timer handling can
+ * be slow. XXX is this save?
*/
ack_APIC_irq();
@@ -825,7 +818,7 @@ int __init APIC_init_uniprocessor (void)
* Complain if the BIOS pretends there is one.
*/
if (!cpu_has_apic&&APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]))
- {
+ {
printk("BIOS bug, local APIC #%d not detected!...\n",
boot_cpu_physical_apicid);
return -1;
diff --git a/xen-2.4.16/common/ac_timer.c b/xen-2.4.16/common/ac_timer.c
index a46ec53d44..8f65ff7093 100644
--- a/xen-2.4.16/common/ac_timer.c
+++ b/xen-2.4.16/common/ac_timer.c
@@ -44,6 +44,12 @@
#define TRC(_x)
#endif
+/*
+ * We pull handlers off the timer list this far in future,
+ * rather than reprogramming the time hardware.
+ */
+#define TIMER_SLOP (50*1000) /* ns */
+
/* A timer list per CPU */
typedef struct ac_timers_st
{
@@ -58,8 +64,8 @@ static ac_timers_t ac_timers[NR_CPUS];
#define MAX_STATS
typedef struct act_stats_st
{
- u32 count;
- u32 times[2*(BUCKETS)];
+ u32 count;
+ u32 times[2*(BUCKETS)];
} __cacheline_aligned act_stats_t;
static act_stats_t act_stats[NR_CPUS];
@@ -79,71 +85,68 @@ static int detach_ac_timer(struct ac_timer *timer);
*/
int add_ac_timer(struct ac_timer *timer)
{
- int cpu = smp_processor_id();
- unsigned long flags;
- s_time_t now;
-
- /* sanity checks */
-
- /* make sure timeout value is in the future */
- now = NOW();
- TRC(printk("ACT [%02d] add(): now=%lld timo=%lld\n",
- cpu, now, timer->expires));
- if (timer->expires <= now) {
- printk("ACT[%02d] add_ac_timer: now=0x%08X%08X > expire=0x%08X%08X\n",
- cpu, (u32)(now>>32), (u32)now,
- (u32)(timer->expires>>32), (u32)timer->expires);
- return 1;
- }
- spin_lock_irqsave(&ac_timers[cpu].lock, flags);
- /*
+ int cpu = smp_processor_id();
+ unsigned long flags;
+ s_time_t now;
+
+ /* make sure timeout value is in the future */
+ now = NOW();
+ TRC(printk("ACT [%02d] add(): now=%lld timo=%lld\n",
+ cpu, now, timer->expires));
+ if (timer->expires <= now) {
+ printk("ACT[%02d] add_ac_timer: now=0x%08X%08X > expire=0x%08X%08X\n",
+ cpu, (u32)(now>>32), (u32)now,
+ (u32)(timer->expires>>32), (u32)timer->expires);
+ return 1;
+ }
+ spin_lock_irqsave(&ac_timers[cpu].lock, flags);
+ /*
* Add timer to the list. If it gets added to the front we have to
* reprogramm the timer
*/
- if (list_empty(&ac_timers[cpu].timers)) {
- /* Reprogramm and add to head of list */
- if (!reprogram_ac_timer(timer->expires)) {
- /* failed */
- printk("ACT [%02d] add(): add at head failed\n", cpu);
- spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
- return 1;
- }
- list_add(&timer->timer_list, &ac_timers[cpu].timers);
- TRC(printk("ACT [%02d] add(0x%08X%08X): added at head\n", cpu,
- (u32)(timer->expires>>32), (u32)timer->expires));
- } else {
- struct list_head *pos;
- struct ac_timer *t;
- for (pos = ac_timers[cpu].timers.next;
- pos != &ac_timers[cpu].timers;
- pos = pos->next) {
- t = list_entry(pos, struct ac_timer, timer_list);
- if (t->expires > timer->expires)
- break;
- }
-
- if (pos->prev == &ac_timers[cpu].timers) {
- /* added to head, reprogramm timer */
- if (!reprogram_ac_timer(timer->expires)) {
- /* failed */
- TRC(printk("ACT [%02d] add(): add at head failed\n", cpu));
- spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
- return 1;
- }
- list_add (&(timer->timer_list), pos->prev);
- TRC(printk("ACT [%02d] add(0x%08X%08X): added at head\n", cpu,
- (u32)(timer->expires>>32), (u32)timer->expires));
- } else {
- list_add (&(timer->timer_list), pos->prev);
- TRC(printk("ACT [%02d] add(0x%08X%08X): add < exp=0x%08X%08X\n",
- cpu,
- (u32)(timer->expires>>32), (u32)timer->expires,
- (u32)(t->expires>>32), (u32)t->expires));
- }
-
- }
- spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
- return 0;
+ if (list_empty(&ac_timers[cpu].timers)) {
+ /* Reprogramm and add to head of list */
+ if (!reprogram_ac_timer(timer->expires)) {
+ /* failed */
+ printk("ACT [%02d] add(): add at head failed\n", cpu);
+ spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
+ return 1;
+ }
+ list_add(&timer->timer_list, &ac_timers[cpu].timers);
+ TRC(printk("ACT [%02d] add(0x%08X%08X): added at head\n", cpu,
+ (u32)(timer->expires>>32), (u32)timer->expires));
+ } else {
+ struct list_head *pos;
+ struct ac_timer *t;
+ for (pos = ac_timers[cpu].timers.next;
+ pos != &ac_timers[cpu].timers;
+ pos = pos->next) {
+ t = list_entry(pos, struct ac_timer, timer_list);
+ if (t->expires > timer->expires)
+ break;
+ }
+
+ if (pos->prev == &ac_timers[cpu].timers) {
+ /* added to head, reprogramm timer */
+ if (!reprogram_ac_timer(timer->expires)) {
+ /* failed */
+ TRC(printk("ACT [%02d] add(): add at head failed\n", cpu));
+ spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
+ return 1;
+ }
+ list_add (&(timer->timer_list), pos->prev);
+ TRC(printk("ACT [%02d] add(0x%08X%08X): added at head\n", cpu,
+ (u32)(timer->expires>>32), (u32)timer->expires));
+ } else {
+ list_add (&(timer->timer_list), pos->prev);
+ TRC(printk("ACT [%02d] add(0x%08X%08X): add < exp=0x%08X%08X\n",
+ cpu,
+ (u32)(timer->expires>>32), (u32)timer->expires,
+ (u32)(t->expires>>32), (u32)t->expires));
+ }
+ }
+ spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
+ return 0;
}
/*
@@ -154,11 +157,11 @@ int add_ac_timer(struct ac_timer *timer)
*/
static int detach_ac_timer(struct ac_timer *timer)
{
- TRC(int cpu = smp_processor_id());
- TRC(printk("ACT [%02d] detach(): \n", cpu));
- list_del(&timer->timer_list);
- timer->timer_list.next = NULL;
- return 0;
+ TRC(int cpu = smp_processor_id());
+ TRC(printk("ACT [%02d] detach(): \n", cpu));
+ list_del(&timer->timer_list);
+ timer->timer_list.next = NULL;
+ return 0;
}
/*
@@ -169,18 +172,17 @@ static int detach_ac_timer(struct ac_timer *timer)
*/
int rem_ac_timer(struct ac_timer *timer)
{
- int cpu = smp_processor_id();
- int res;
- unsigned long flags;
+ int cpu = smp_processor_id();
+ int res;
+ unsigned long flags;
- TRC(printk("ACT [%02d] remove(): timo=%lld \n", cpu, timer->expires));
- /* sanity checks */
+ TRC(printk("ACT [%02d] remove(): timo=%lld \n", cpu, timer->expires));
- spin_lock_irqsave(&ac_timers[cpu].lock, flags);
- res = detach_ac_timer(timer);
- spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
+ spin_lock_irqsave(&ac_timers[cpu].lock, flags);
+ res = detach_ac_timer(timer);
+ spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
- return res;
+ return res;
}
/*
@@ -191,12 +193,12 @@ int rem_ac_timer(struct ac_timer *timer)
*/
int mod_ac_timer(struct ac_timer *timer, s_time_t new_time)
{
- if (rem_ac_timer(timer) != 0)
- return -1;
- timer->expires = new_time;
- if (add_ac_timer(timer) != 0)
- return -1;
- return 0;
+ if (rem_ac_timer(timer) != 0)
+ return -1;
+ timer->expires = new_time;
+ if (add_ac_timer(timer) != 0)
+ return -1;
+ return 0;
}
/*
@@ -205,108 +207,76 @@ int mod_ac_timer(struct ac_timer *timer, s_time_t new_time)
*/
void do_ac_timer(void)
{
- int cpu = smp_processor_id();
- unsigned long flags;
- s_time_t now;
- struct ac_timer *t;
- struct list_head *tmp;
+ int cpu = smp_processor_id();
+ unsigned long flags;
+ struct ac_timer *t;
- spin_lock_irqsave(&ac_timers[cpu].lock, flags);
+ spin_lock_irqsave(&ac_timers[cpu].lock, flags);
do_timer_again:
- now = NOW();
- TRC(printk("ACT [%02d] do(): now=%lld\n", cpu, now));
+ TRC(printk("ACT [%02d] do(): now=%lld\n", cpu, NOW()));
- /* Sanity checks */
- /* empty time list */
- if (list_empty(&ac_timers[cpu].timers)) {
- printk("ACT[%02d] do_ac_timer(): timer irq without timer\n", cpu);
- spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
- return;
- }
-
-
- /* execute the head of timer queue */
- t = list_entry(ac_timers[cpu].timers.next, struct ac_timer, timer_list);
- detach_ac_timer(t);
-
- spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
-
+ /* Sanity: is the timer list empty? */
+ if ( list_empty(&ac_timers[cpu].timers) )
+ printk("ACT[%02d] do_ac_timer(): timer irq without timer\n", cpu);
#ifdef AC_TIMER_STATS
- {
- s32 diff;
- u32 i;
- diff = ((s32)(now - t->expires)) / 1000; /* delta in us */
- if (diff < -BUCKETS)
- diff = -BUCKETS;
- else if (diff > BUCKETS)
- diff = BUCKETS;
- act_stats[cpu].times[diff+BUCKETS]++;
- act_stats[cpu].count++;
-
- if (act_stats[cpu].count >= 5000) {
- printk("ACT Stats\n");
+ {
+ s32 diff;
+ u32 i;
+ diff = ((s32)(NOW() - t->expires)) / 1000; /* delta in us */
+ if (diff < -BUCKETS)
+ diff = -BUCKETS;
+ else if (diff > BUCKETS)
+ diff = BUCKETS;
+ act_stats[cpu].times[diff+BUCKETS]++;
+ act_stats[cpu].count++;
+
+ if (act_stats[cpu].count >= 5000) {
+ printk("ACT Stats\n");
for (i=0; i < 2*BUCKETS; i++) {
if (act_stats[cpu].times[i] != 0)
- printk("ACT [%02d]: %3dus: %5d\n",
- cpu,i-BUCKETS, act_stats[cpu].times[i]);
- act_stats[cpu].times[i]=0;
- }
- act_stats[cpu].count = 0;
- printk("\n");
- }
- }
+ printk("ACT [%02d]: %3dus: %5d\n",
+ cpu,i-BUCKETS, act_stats[cpu].times[i]);
+ act_stats[cpu].times[i]=0;
+ }
+ act_stats[cpu].count = 0;
+ printk("\n");
+ }
+ }
#endif
-
-
- if (t->expires > now) {
- //printk("ACT [%02d] do(): irq too early (%lld ns)\n",
- // cpu, now - t->expires );
- }
- if (t->function != NULL)
- t->function(t->data);
-
-
- /* check if there are other timer functions on the list */
- now = NOW();
-
- spin_lock_irqsave(&ac_timers[cpu].lock, flags);
-
- if (!list_empty(&ac_timers[cpu].timers)) {
- list_for_each(tmp, &ac_timers[cpu].timers) {
- t = list_entry(tmp, struct ac_timer, timer_list);
- TRC(printk("ACT [%02d] do(): now=%lld timo=%lld\n",
- cpu, now, t->expires));
- if (t->expires <= now) {
- detach_ac_timer(t);
- spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
- if (t->function != NULL)
- t->function(t->data);
- spin_lock_irqsave(&ac_timers[cpu].lock, flags);
- now = NOW();
- } else {
- TRC(printk("ACT [%02d] do(): break1\n", cpu));
- break;
- }
- }
- }
+ /* Handle all timeouts in the near future. */
+ while ( !list_empty(&ac_timers[cpu].timers) )
+ {
+ t = list_entry(ac_timers[cpu].timers.next,
+ struct ac_timer, timer_list);
+ if ( t->expires > (NOW() + TIMER_SLOP) ) break;
+ detach_ac_timer(t);
+ spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
+ if ( t->function != NULL ) t->function(t->data);
+ spin_lock_irqsave(&ac_timers[cpu].lock, flags);
+ }
- /* If list not empty reprogramm timer to new head of list */
- if (!list_empty(&ac_timers[cpu].timers)) {
- t = list_entry(ac_timers[cpu].timers.next,struct ac_timer,timer_list);
- if (t->expires > 0) {
- TRC(printk("ACT [%02d] do(): reprog timo=%lld\n",cpu,t->expires));
- if (!reprogram_ac_timer(t->expires)) {
- TRC(printk("ACT [%02d] do(): again\n", cpu));
- goto do_timer_again;
- }
- }
- }
- spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
- TRC(printk("ACT [%02d] do(): end\n", cpu));
+ /* If list not empty then reprogram timer to new head of list */
+ if ( !list_empty(&ac_timers[cpu].timers) )
+ {
+ t = list_entry(ac_timers[cpu].timers.next,
+ struct ac_timer, timer_list);
+ if ( t->expires > 0 )
+ {
+ TRC(printk("ACT [%02d] do(): reprog timo=%lld\n",cpu,t->expires));
+ if ( !reprogram_ac_timer(t->expires) )
+ {
+ TRC(printk("ACT [%02d] do(): again\n", cpu));
+ goto do_timer_again;
+ }
+ }
+ }
+
+ spin_unlock_irqrestore(&ac_timers[cpu].lock, flags);
+ TRC(printk("ACT [%02d] do(): end\n", cpu));
}
/*
@@ -317,16 +287,16 @@ static void dump_tqueue(struct list_head *queue, char *name)
{
struct list_head *list;
int loop = 0;
- struct ac_timer *t;
+ struct ac_timer *t;
printk ("QUEUE %s %lx n: %lx, p: %lx\n", name, (unsigned long)queue,
(unsigned long) queue->next, (unsigned long) queue->prev);
list_for_each (list, queue) {
- t = list_entry(list, struct ac_timer, timer_list);
+ t = list_entry(list, struct ac_timer, timer_list);
printk (" %s %d : %lx ex=0x%08X%08X %lu n: %lx, p: %lx\n",
- name, loop++,
+ name, loop++,
(unsigned long)list,
- (u32)(t->expires>>32), (u32)t->expires, t->data,
+ (u32)(t->expires>>32), (u32)t->expires, t->data,
(unsigned long)list->next, (unsigned long)list->prev);
}
return;
@@ -336,32 +306,30 @@ static void dump_tqueue(struct list_head *queue, char *name)
static void dump_timerq(u_char key, void *dev_id, struct pt_regs *regs)
{
u_long flags;
- s_time_t now = NOW();
+ s_time_t now = NOW();
printk("Dumping ac_timer queues for cpu 0: NOW=0x%08X%08X\n",
- (u32)(now>>32), (u32)now);
+ (u32)(now>>32), (u32)now);
spin_lock_irqsave(&ac_timers[0].lock, flags);
dump_tqueue(&ac_timers[0].timers, "ac_time");
spin_unlock_irqrestore(&ac_timers[0].lock, flags);
- printk("\n");
+ printk("\n");
return;
}
-/*
- * init
- */
+
void __init ac_timer_init(void)
{
int i;
- printk ("ACT: Initialising Accurate timers\n");
+ printk ("ACT: Initialising Accurate timers\n");
for (i = 0; i < NR_CPUS; i++)
{
- INIT_LIST_HEAD(&ac_timers[i].timers);
- spin_lock_init(&ac_timers[i].lock);
+ INIT_LIST_HEAD(&ac_timers[i].timers);
+ spin_lock_init(&ac_timers[i].lock);
}
- add_key_handler('a', dump_timerq, "dump ac_timer queues");
+ add_key_handler('a', dump_timerq, "dump ac_timer queues");
}