# HG changeset patch
# User djm@xxxxxxxxxxxxxxx
# Node ID 89fc07f85b01f15ae00ea4d312352b2d1dd0a075
# Parent 9361694781fcf78e8cb03634d1fdd5dbd4930cf7
First part of timer merge
Signed-off-by Kevin Tian <Kevin.tian@xxxxxxxxx>
Signed-off-by Eddie Dong <Eddie.dong@xxxxxxxxx>
diff -r 9361694781fc -r 89fc07f85b01 xen/arch/ia64/xen/vcpu.c
--- a/xen/arch/ia64/xen/vcpu.c Tue Sep 6 22:21:40 2005
+++ b/xen/arch/ia64/xen/vcpu.c Tue Sep 6 22:49:01 2005
@@ -1032,6 +1032,8 @@
if (is_idle_task(vcpu->domain)) {
printf("****** vcpu_set_next_timer called during idle!!\n");
+ vcpu_safe_set_itm(s);
+ return;
}
//s = PSCBX(vcpu,xen_itm);
if (d && (d > now) && (d < s)) {
diff -r 9361694781fc -r 89fc07f85b01 xen/arch/ia64/xen/xenmisc.c
--- a/xen/arch/ia64/xen/xenmisc.c Tue Sep 6 22:21:40 2005
+++ b/xen/arch/ia64/xen/xenmisc.c Tue Sep 6 22:49:01 2005
@@ -113,29 +113,6 @@
printf("__hypercall_create_continuation: not implemented!!!\n");
}
#endif
-
-///////////////////////////////
-
-///////////////////////////////
-// from arch/x86/apic.c
-///////////////////////////////
-
-extern unsigned long domain0_ready;
-
-int reprogram_ac_timer(s_time_t timeout)
-{
- struct vcpu *v = current;
-
-#ifdef CONFIG_VTI
-// if(VMX_DOMAIN(v))
- return 1;
-#endif // CONFIG_VTI
- if (!domain0_ready) return 1;
- local_cpu_data->itm_next = timeout;
- if (is_idle_task(v->domain)) vcpu_safe_set_itm(timeout);
- else vcpu_set_next_timer(current);
- return 1;
-}
///////////////////////////////
// from arch/ia64/page_alloc.c
diff -r 9361694781fc -r 89fc07f85b01 xen/arch/ia64/xen/xensetup.c
--- a/xen/arch/ia64/xen/xensetup.c Tue Sep 6 22:21:40 2005
+++ b/xen/arch/ia64/xen/xensetup.c Tue Sep 6 22:49:01 2005
@@ -252,11 +252,8 @@
printk("About to call scheduler_init()\n");
scheduler_init();
local_irq_disable();
-printk("About to call xen_time_init()\n");
- xen_time_init();
-#ifdef CONFIG_VTI
+printk("About to call init_xen_time()\n");
init_xen_time(); /* initialise the time */
-#endif // CONFIG_VTI
printk("About to call ac_timer_init()\n");
ac_timer_init();
// init_xen_time(); ???
diff -r 9361694781fc -r 89fc07f85b01 xen/arch/ia64/xen/xentime.c
--- a/xen/arch/ia64/xen/xentime.c Tue Sep 6 22:21:40 2005
+++ b/xen/arch/ia64/xen/xentime.c Tue Sep 6 22:49:01 2005
@@ -26,118 +26,78 @@
#include <asm/sal.h>
#include <asm/sections.h>
#include <asm/system.h>
-#ifdef XEN
#include <asm/vcpu.h>
#include <linux/jiffies.h> // not included by xen/sched.h
-#endif
#include <xen/softirq.h>
-#ifdef XEN
seqlock_t xtime_lock __cacheline_aligned_in_smp = SEQLOCK_UNLOCKED;
-#endif
#define TIME_KEEPER_ID 0
-extern unsigned long wall_jiffies;
-
-static s_time_t stime_irq; /* System time at last 'time update' */
-
unsigned long domain0_ready = 0;
-
-#ifndef CONFIG_VTI
+static s_time_t stime_irq = 0x0; /* System time at last 'time
update' */
+unsigned long itc_scale, ns_scale;
+unsigned long itc_at_irq;
+
static inline u64 get_time_delta(void)
{
- return ia64_get_itc();
-}
-#else // CONFIG_VTI
-static s_time_t stime_irq = 0x0; /* System time at last 'time
update' */
-unsigned long itc_scale;
-unsigned long itc_at_irq;
-static unsigned long wc_sec, wc_nsec; /* UTC time at last 'time update'. */
-//static rwlock_t time_lock = RW_LOCK_UNLOCKED;
-static irqreturn_t vmx_timer_interrupt (int irq, void *dev_id, struct pt_regs
*regs);
-
-static inline u64 get_time_delta(void)
-{
s64 delta_itc;
- u64 delta, cur_itc;
+ u64 cur_itc;
cur_itc = ia64_get_itc();
delta_itc = (s64)(cur_itc - itc_at_irq);
+
+ /* Ensure that the returned system time is monotonically increasing. */
if ( unlikely(delta_itc < 0) ) delta_itc = 0;
- delta = ((u64)delta_itc) * itc_scale;
- delta = delta >> 32;
-
- return delta;
-}
-
-u64 tick_to_ns(u64 tick)
-{
- return (tick * itc_scale) >> 32;
-}
-#endif // CONFIG_VTI
+ return cycle_to_ns(delta_itc);
+}
+
+/* We don't expect an absolute cycle value here, since then no way
+ * to prevent overflow for large norminator. Normally this conversion
+ * is used for relative offset.
+ */
+u64 cycle_to_ns(u64 cycle)
+{
+ return (cycle * itc_scale) >> 32;
+}
+
+u64 ns_to_cycle(u64 ns)
+{
+ return (ns * ns_scale) >> 32;
+}
s_time_t get_s_time(void)
{
s_time_t now;
- unsigned long flags;
-
- read_lock_irqsave(&xtime_lock, flags);
-
- now = stime_irq + get_time_delta();
-
- /* Ensure that the returned system time is monotonically increasing. */
- {
- static s_time_t prev_now = 0;
- if ( unlikely(now < prev_now) )
- now = prev_now;
- prev_now = now;
- }
-
- read_unlock_irqrestore(&xtime_lock, flags);
+ unsigned long flags, seq;
+
+ do {
+ seq = read_seqbegin(&xtime_lock);
+ now = stime_irq + get_time_delta();
+ } while (unlikely(read_seqretry(&xtime_lock, seq)));
return now;
}
void update_dom_time(struct vcpu *v)
{
-// FIXME: implement this?
-// printf("update_dom_time: called, not implemented, skipping\n");
- return;
+ /* N-op here, and let dom0 to manage system time directly */
+ return;
}
/* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
{
-#ifdef CONFIG_VTI
- u64 _nsecs;
-
- write_lock_irq(&xtime_lock);
-
- _nsecs = (u64)nsecs + (s64)(stime_irq - system_time_base);
- while ( _nsecs >= 1000000000 )
- {
- _nsecs -= 1000000000;
- secs++;
- }
-
- wc_sec = secs;
- wc_nsec = (unsigned long)_nsecs;
-
- write_unlock_irq(&xtime_lock);
-
- update_dom_time(current->domain);
-#else
-// FIXME: Should this be do_settimeofday (from linux)???
- printf("do_settime: called, not implemented, stopping\n");
- dummy();
-#endif
+ /* If absolute system time is managed by dom0, there's no need for such
+ * action since only virtual itc/itm service is provided.
+ */
+ return;
}
irqreturn_t
xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{
- unsigned long new_itm;
+ unsigned long new_itm, old_itc;
#define HEARTBEAT_FREQ 16 // period in seconds
#ifdef HEARTBEAT_FREQ
@@ -150,12 +110,6 @@
count = 0;
}
#endif
-#ifndef XEN
- if (unlikely(cpu_is_offline(smp_processor_id()))) {
- return IRQ_HANDLED;
- }
-#endif
-#ifdef XEN
if (current->domain == dom0) {
// FIXME: there's gotta be a better way of doing this...
// We have to ensure that domain0 is launched before we
@@ -176,35 +130,12 @@
vcpu_wake(current);
}
}
- raise_actimer_softirq();
-#endif
-
-#ifndef XEN
- platform_timer_interrupt(irq, dev_id, regs);
-#endif
-
new_itm = local_cpu_data->itm_next;
if (!time_after(ia64_get_itc(), new_itm))
-#ifdef XEN
return;
-#else
- printk(KERN_ERR "Oops: timer tick before it's due
(itc=%lx,itm=%lx)\n",
- ia64_get_itc(), new_itm);
-#endif
-
-#ifdef XEN
-// printf("GOT TO HERE!!!!!!!!!!!\n");
- //while(1);
-#else
- profile_tick(CPU_PROFILING, regs);
-#endif
while (1) {
-#ifndef XEN
- update_process_times(user_mode(regs));
-#endif
-
new_itm += local_cpu_data->itm_delta;
if (smp_processor_id() == TIME_KEEPER_ID) {
@@ -221,6 +152,12 @@
do_timer(regs);
#endif
local_cpu_data->itm_next = new_itm;
+
+ /* Updates system time (nanoseconds since boot). */
+ old_itc = itc_at_irq;
+ itc_at_irq = ia64_get_itc();
+ stime_irq += cycle_to_ns(itc_at_irq - old_itc);
+
#ifdef TURN_ME_OFF_FOR_NOW_IA64_XEN
write_sequnlock(&xtime_lock);
#endif
@@ -251,132 +188,65 @@
//#endif
/* double check, in case we got hit by a (slow) PMI: */
} while (time_after_eq(ia64_get_itc(), new_itm));
+ raise_softirq(AC_TIMER_SOFTIRQ);
+
return IRQ_HANDLED;
}
static struct irqaction xen_timer_irqaction = {
-#ifdef CONFIG_VTI
- .handler = vmx_timer_interrupt,
-#else // CONFIG_VTI
.handler = xen_timer_interrupt,
-#endif // CONFIG_VTI
-#ifndef XEN
- .flags = SA_INTERRUPT,
-#endif
.name = "timer"
};
void __init
-xen_time_init (void)
+ia64_time_init (void)
{
register_percpu_irq(IA64_TIMER_VECTOR, &xen_timer_irqaction);
ia64_init_itm();
}
-#ifdef CONFIG_VTI
-
/* Late init function (after all CPUs are booted). */
int __init init_xen_time()
{
struct timespec tm;
+ ia64_time_init();
itc_scale = 1000000000UL << 32 ;
itc_scale /= local_cpu_data->itc_freq;
+ ns_scale = (local_cpu_data->itc_freq << 32) / 1000000000UL;
/* System time ticks from zero. */
stime_irq = (s_time_t)0;
itc_at_irq = ia64_get_itc();
- /* Wallclock time starts as the initial RTC time. */
- efi_gettimeofday(&tm);
- wc_sec = tm.tv_sec;
- wc_nsec = tm.tv_nsec;
-
-
printk("Time init:\n");
printk(".... System Time: %ldns\n", NOW());
printk(".... scale: %16lX\n", itc_scale);
- printk(".... Wall Clock: %lds %ldus\n", wc_sec, wc_nsec/1000);
return 0;
}
-static irqreturn_t
-vmx_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned long new_itm;
- struct vcpu *v = current;
-
-
- new_itm = local_cpu_data->itm_next;
-
- if (!time_after(ia64_get_itc(), new_itm))
- return;
-
- while (1) {
-#ifdef CONFIG_SMP
- /*
- * For UP, this is done in do_timer(). Weird, but
- * fixing that would require updates to all
- * platforms.
- */
- update_process_times(user_mode(v, regs));
-#endif
- new_itm += local_cpu_data->itm_delta;
-
- if (smp_processor_id() == TIME_KEEPER_ID) {
- /*
- * Here we are in the timer irq handler. We have irqs locally
- * disabled, but we don't know if the timer_bh is running on
- * another CPU. We need to avoid to SMP race by acquiring the
- * xtime_lock.
- */
- local_cpu_data->itm_next = new_itm;
-
- write_lock_irq(&xtime_lock);
- /* Update jiffies counter. */
- (*(unsigned long *)&jiffies_64)++;
-
- /* Update wall time. */
- wc_nsec += 1000000000/HZ;
- if ( wc_nsec >= 1000000000 )
- {
- wc_nsec -= 1000000000;
- wc_sec++;
- }
-
- /* Updates system time (nanoseconds since boot). */
- stime_irq += MILLISECS(1000/HZ);
- itc_at_irq = ia64_get_itc();
-
- write_unlock_irq(&xtime_lock);
-
- } else
- local_cpu_data->itm_next = new_itm;
-
- if (time_after(new_itm, ia64_get_itc()))
- break;
- }
-
- do {
- /*
- * If we're too close to the next clock tick for
- * comfort, we increase the safety margin by
- * intentionally dropping the next tick(s). We do NOT
- * update itm.next because that would force us to call
- * do_timer() which in turn would let our clock run
- * too fast (with the potentially devastating effect
- * of losing monotony of time).
- */
- while (!time_after(new_itm, ia64_get_itc() +
local_cpu_data->itm_delta/2))
- new_itm += local_cpu_data->itm_delta;
- ia64_set_itm(new_itm);
- /* double check, in case we got hit by a (slow) PMI: */
- } while (time_after_eq(ia64_get_itc(), new_itm));
- raise_softirq(AC_TIMER_SOFTIRQ);
-
- return IRQ_HANDLED;
-}
-#endif // CONFIG_VTI
-
+int reprogram_ac_timer(s_time_t timeout)
+{
+ struct vcpu *v = current;
+ s_time_t expire;
+ unsigned long seq, cur_itc, itm_next;
+
+ if (!domain0_ready) return 1;
+
+ do {
+ seq = read_seqbegin(&xtime_lock);
+ if ((expire = timeout - NOW()) < 0)
+ return 0;
+
+ cur_itc = ia64_get_itc();
+ itm_next = cur_itc + ns_to_cycle(expire);
+ } while (unlikely(read_seqretry(&xtime_lock, seq)));
+
+ local_cpu_data->itm_next = itm_next;
+ vcpu_set_next_timer(current);
+ return 1;
+}
+
+
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|