[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] First part of timer merge



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.