Source-Changes-HG archive

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

[src/cherry-xenmp]: src/sys/arch/xen/xen Various clock fixes:



details:   https://anonhg.NetBSD.org/src/rev/0933a5c8b07d
branches:  cherry-xenmp
changeset: 765647:0933a5c8b07d
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Sat Oct 22 19:26:16 2011 +0000

description:
Various clock fixes:
- xen_get_timecount() is CPU specific, so get the time from this
  virtual CPU and not VCPU0. Also keep xen_clock_bias per-cpu.
- The periodic timer looks buggy, we stop receiving events after a (short)
  while. Linux is using the one-shoot timer so use it too (and disable
  the periodic timer), but rearm it from the event handler, not idle_block()
  as the later may not be called if the CPU is busy, resulting it clock
  event loss.
- use  HYPERVISOR_block() in idle_block() again, now that interrupts are
  working properly.

diffstat:

 sys/arch/xen/xen/clock.c |  57 +++++++++++++++++++++++++++++++++++------------
 1 files changed, 42 insertions(+), 15 deletions(-)

diffs (135 lines):

diff -r 8ed7f8bc237a -r 0933a5c8b07d sys/arch/xen/xen/clock.c
--- a/sys/arch/xen/xen/clock.c  Sat Oct 22 19:21:57 2011 +0000
+++ b/sys/arch/xen/xen/clock.c  Sat Oct 22 19:26:16 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: clock.c,v 1.54.6.4 2011/09/18 18:54:32 cherry Exp $    */
+/*     $NetBSD: clock.c,v 1.54.6.5 2011/10/22 19:26:16 bouyer Exp $    */
 
 /*
  *
@@ -29,7 +29,7 @@
 #include "opt_xen.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.54.6.4 2011/09/18 18:54:32 cherry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.54.6.5 2011/10/22 19:26:16 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/cpu.h>
@@ -94,7 +94,7 @@
  * back to maintain the illusion that hardclock(9) was called when it
  * was supposed to be, not when Xen got around to scheduling us.
  */
-static volatile uint64_t xen_clock_bias;
+static volatile uint64_t xen_clock_bias[MAXCPUS];
 
 #ifdef DOM0OPS
 /* If we're dom0, send our time to Xen every minute or so. */
@@ -416,9 +416,10 @@
 xen_get_timecount(struct timecounter *tc)
 {
        uint64_t ns;
+       struct cpu_info *ci = curcpu();
 
        mutex_enter(&tmutex);
-       ns = get_system_time() - xen_clock_bias;
+       ns = get_vcpu_time(ci) - xen_clock_bias[ci->ci_cpuid];
        mutex_exit(&tmutex);
 
        return (u_int)ns;
@@ -439,12 +440,10 @@
        int err, evtch;
        static bool tcdone = false;
 
-       struct vcpu_set_periodic_timer hardclock_period = { NS_PER_TICK };
-
        struct cpu_info *ci = curcpu();
        volatile struct shadow *shadow = &ci_shadow[ci->ci_cpuid];
 
-       xen_clock_bias = 0;
+       xen_clock_bias[ci->ci_cpuid] = 0;
 
        evcnt_attach_dynamic(&hardclock_called[ci->ci_cpuid],
                             EVCNT_TYPE_INTR,
@@ -468,12 +467,19 @@
        }
        /* The splhigh requirements start here. */
 
-       /* Set hardclock() frequency */
-       err = HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer,
+       /*
+        * The periodic timer looks buggy, we stop receiving events
+        * after a while. Use the one-shot timer every NS_PER_TICK
+        * and rearm it from the event handler.
+        */
+       err = HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer,
                                 ci->ci_cpuid,
-                                &hardclock_period);
+                                NULL);
 
        KASSERT(err == 0);
+       err = HYPERVISOR_set_timer_op(
+           vcpu_system_time[ci->ci_cpuid] + NS_PER_TICK);
+       KASSERT(err == 0);
 
        event_set_handler(evtch, (int (*)(void *))xen_timer_handler,
            ci, IPL_CLOCK, "clock");
@@ -504,25 +510,34 @@
        int64_t delta;
        struct cpu_info *ci = curcpu();
        KASSERT(arg == ci);
+       int err;
+again:
        mutex_enter(&tmutex);
-
        delta = (int64_t)(get_vcpu_time(ci) - vcpu_system_time[ci->ci_cpuid]);
-
        mutex_exit(&tmutex);
 
        /* Several ticks may have passed without our being run; catch up. */
        while (delta >= (int64_t)NS_PER_TICK) {
                mutex_enter(&tmutex);
                vcpu_system_time[ci->ci_cpuid] += NS_PER_TICK;
-               xen_clock_bias = (delta -= NS_PER_TICK);
+               xen_clock_bias[ci->ci_cpuid] = (delta -= NS_PER_TICK);
                mutex_exit(&tmutex);
                hardclock((struct clockframe *)regs);
                hardclock_called[ci->ci_cpuid].ev_count++;
        }
+
+       /*
+        * rearm the timer. If it fails it's probably because the date
+        * is in the past, update our local time and try again.
+        */
+       err = HYPERVISOR_set_timer_op(
+           vcpu_system_time[ci->ci_cpuid] + NS_PER_TICK);
+       if (err)
+               goto again;
        
-       if (xen_clock_bias) {
+       if (xen_clock_bias[ci->ci_cpuid]) {
                mutex_enter(&tmutex);
-               xen_clock_bias = 0;
+               xen_clock_bias[ci->ci_cpuid] = 0;
                mutex_exit(&tmutex);
        }
 
@@ -537,6 +552,18 @@
 void
 idle_block(void)
 {
+#ifdef MULTIPROCESSOR
        HYPERVISOR_yield();
        __sti();
+#else
+       struct cpu_info *ci = curcpu();
+       int r;
+
+       r = HYPERVISOR_set_timer_op(
+           vcpu_system_time[ci->ci_cpuid] + NS_PER_TICK);
+       if (r == 0)
+               HYPERVISOR_block();
+       else
+               __sti();
+#endif
 }



Home | Main Index | Thread Index | Old Index