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

[Xen-changelog] [xen-unstable] xen: New vcpu_op commands for setting periodic and single-shot timers.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1173464807 0
# Node ID 215b799fa181a807aed289e39b56c8e0c463f322
# Parent  1a01d8d9dbeca77c934156d42e955ada492b9c7b
xen: New vcpu_op commands for setting periodic and single-shot timers.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/ia64/xen/xensetup.c |    2 
 xen/arch/powerpc/setup.c     |    3 
 xen/arch/x86/apic.c          |   14 ++--
 xen/arch/x86/setup.c         |    8 --
 xen/common/compat/domain.c   |    4 +
 xen/common/domain.c          |   61 +++++++++++++++++++
 xen/common/page_alloc.c      |   15 ++++
 xen/common/sched_credit.c    |   40 ++++++++++--
 xen/common/schedule.c        |  135 ++++++++++++++++++++++++-------------------
 xen/include/public/vcpu.h    |   36 +++++++++--
 xen/include/xen/mm.h         |    5 +
 xen/include/xen/sched-if.h   |    2 
 xen/include/xen/sched.h      |    8 +-
 xen/include/xen/timer.h      |    4 -
 14 files changed, 240 insertions(+), 97 deletions(-)

diff -r 1a01d8d9dbec -r 215b799fa181 xen/arch/ia64/xen/xensetup.c
--- a/xen/arch/ia64/xen/xensetup.c      Fri Mar 09 18:26:22 2007 +0000
+++ b/xen/arch/ia64/xen/xensetup.c      Fri Mar 09 18:26:47 2007 +0000
@@ -543,8 +543,6 @@ printk("num_online_cpus=%d, max_cpus=%d\
 
     domain0_ready = 1;
 
-    schedulers_start();
-
     domain_unpause_by_systemcontroller(dom0);
 
     startup_cpu_idle_loop();
diff -r 1a01d8d9dbec -r 215b799fa181 xen/arch/powerpc/setup.c
--- a/xen/arch/powerpc/setup.c  Fri Mar 09 18:26:22 2007 +0000
+++ b/xen/arch/powerpc/setup.c  Fri Mar 09 18:26:47 2007 +0000
@@ -365,9 +365,6 @@ static void __init __start_xen(multiboot
         kick_secondary_cpus(max_cpus);
     }
 
-    /* Secondary processors must be online before we call this.  */
-    schedulers_start();
-
     /* This cannot be called before secondary cpus are marked online.  */
     percpu_free_unused_areas();
 
diff -r 1a01d8d9dbec -r 215b799fa181 xen/arch/x86/apic.c
--- a/xen/arch/x86/apic.c       Fri Mar 09 18:26:22 2007 +0000
+++ b/xen/arch/x86/apic.c       Fri Mar 09 18:26:47 2007 +0000
@@ -1023,6 +1023,13 @@ int reprogram_timer(s_time_t timeout)
     u64         apic_tmict;
 
     /*
+     * If we don't have local APIC then we just poll the timer list off the
+     * PIT interrupt.
+     */
+    if ( !cpu_has_apic )
+        return 1;
+
+    /*
      * We use this value because we don't trust zero (we think it may just
      * cause an immediate interrupt). At least this is guaranteed to hold it
      * off for ages (esp. since the clock ticks on bus clock, not cpu clock!).
@@ -1043,13 +1050,6 @@ int reprogram_timer(s_time_t timeout)
                 (u32)now, (u32)(timeout>>32),(u32)timeout);
         return 0;
     }
-
-    /*
-     * If we don't have local APIC then we just poll the timer list off the
-     * PIT interrupt. Cheesy but good enough to work on eg. VMware :-)
-     */
-    if ( !cpu_has_apic )
-        return 1;
 
     /* conversion to bus units */
     apic_tmict = (((u64)bus_scale) * expire)>>18;
diff -r 1a01d8d9dbec -r 215b799fa181 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Fri Mar 09 18:26:22 2007 +0000
+++ b/xen/arch/x86/setup.c      Fri Mar 09 18:26:47 2007 +0000
@@ -195,13 +195,13 @@ static void __init percpu_free_unused_ar
 
     /* Find first unused CPU number. */
     for ( i = 0; i < NR_CPUS; i++ )
-        if ( !cpu_online(i) )
+        if ( !cpu_possible(i) )
             break;
     first_unused = i;
 
-    /* Check that there are no holes in cpu_online_map. */
+    /* Check that there are no holes in cpu_possible_map. */
     for ( ; i < NR_CPUS; i++ )
-        BUG_ON(cpu_online(i));
+        BUG_ON(cpu_possible(i));
 
 #ifndef MEMORY_GUARD
     init_xenheap_pages(__pa(__per_cpu_start) + (first_unused << PERCPU_SHIFT),
@@ -717,8 +717,6 @@ void __init __start_xen(multiboot_info_t
 
     do_initcalls();
 
-    schedulers_start();
-
     if ( opt_watchdog ) 
         watchdog_enable();
 
diff -r 1a01d8d9dbec -r 215b799fa181 xen/common/compat/domain.c
--- a/xen/common/compat/domain.c        Fri Mar 09 18:26:22 2007 +0000
+++ b/xen/common/compat/domain.c        Fri Mar 09 18:26:47 2007 +0000
@@ -55,6 +55,10 @@ int compat_vcpu_op(int cmd, int vcpuid, 
     case VCPUOP_up:
     case VCPUOP_down:
     case VCPUOP_is_up:
+    case VCPUOP_set_periodic_timer:
+    case VCPUOP_stop_periodic_timer:
+    case VCPUOP_set_singleshot_timer:
+    case VCPUOP_stop_singleshot_timer:
         rc = do_vcpu_op(cmd, vcpuid, arg);
         break;
 
diff -r 1a01d8d9dbec -r 215b799fa181 xen/common/domain.c
--- a/xen/common/domain.c       Fri Mar 09 18:26:22 2007 +0000
+++ b/xen/common/domain.c       Fri Mar 09 18:26:47 2007 +0000
@@ -102,6 +102,9 @@ struct vcpu *alloc_vcpu(
     v->runstate.state = is_idle_vcpu(v) ? RUNSTATE_running : RUNSTATE_offline;
     v->runstate.state_entry_time = NOW();
 
+    /* VCPUs by default have a 100Hz ticker. */
+    v->periodic_period = MILLISECS(10);
+
     if ( (vcpu_id != 0) && !is_idle_domain(d) )
         set_bit(_VCPUF_down, &v->vcpu_flags);
 
@@ -267,6 +270,9 @@ void domain_kill(struct domain *d)
     domain_relinquish_resources(d);
     put_domain(d);
 
+    /* Kick page scrubbing after domain_relinquish_resources(). */
+    page_scrub_kick();
+
     send_guest_global_virq(dom0, VIRQ_DOM_EXC);
 }
 
@@ -589,6 +595,61 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
         break;
     }
 
+    case VCPUOP_set_periodic_timer:
+    {
+        struct vcpu_set_periodic_timer set;
+
+        rc = -EFAULT;
+        if ( copy_from_guest(&set, arg, 1) )
+            break;
+
+        rc = -EINVAL;
+        if ( set.period_ns < MILLISECS(1) )
+            break;
+
+        v->periodic_period = set.period_ns;
+        vcpu_force_reschedule(v);
+
+        break;
+    }
+
+    case VCPUOP_stop_periodic_timer:
+    {
+        v->periodic_period = 0;
+        vcpu_force_reschedule(v);
+        break;
+    }
+
+    case VCPUOP_set_singleshot_timer:
+    {
+        struct vcpu_set_singleshot_timer set;
+
+        if ( v != current )
+            return -EINVAL;
+
+        if ( copy_from_guest(&set, arg, 1) )
+            return -EFAULT;
+
+        if ( v->singleshot_timer.cpu != smp_processor_id() )
+        {
+            stop_timer(&v->singleshot_timer);
+            v->singleshot_timer.cpu = smp_processor_id();
+        }
+
+        set_timer(&v->singleshot_timer, set.timeout_abs_ns);
+
+        break;
+    }
+
+    case VCPUOP_stop_singleshot_timer:
+    {
+        if ( v != current )
+            return -EINVAL;
+
+        stop_timer(&v->singleshot_timer);
+        break;
+    }
+
     default:
         rc = arch_do_vcpu_op(cmd, v, arg);
         break;
diff -r 1a01d8d9dbec -r 215b799fa181 xen/common/page_alloc.c
--- a/xen/common/page_alloc.c   Fri Mar 09 18:26:22 2007 +0000
+++ b/xen/common/page_alloc.c   Fri Mar 09 18:26:47 2007 +0000
@@ -970,6 +970,8 @@ __initcall(pagealloc_keyhandler_init);
  * PAGE SCRUBBING
  */
 
+static DEFINE_PER_CPU(struct timer, page_scrub_timer);
+
 static void page_scrub_softirq(void)
 {
     struct list_head *ent;
@@ -978,7 +980,7 @@ static void page_scrub_softirq(void)
     int               i;
     s_time_t          start = NOW();
 
-    /* Aim to do 1ms of work (ten percent of a 10ms jiffy). */
+    /* Aim to do 1ms of work every 10ms. */
     do {
         spin_lock(&page_scrub_lock);
 
@@ -1014,6 +1016,13 @@ static void page_scrub_softirq(void)
             free_heap_pages(pfn_dom_zone_type(page_to_mfn(pg)), pg, 0);
         }
     } while ( (NOW() - start) < MILLISECS(1) );
+
+    set_timer(&this_cpu(page_scrub_timer), NOW() + MILLISECS(10));
+}
+
+static void page_scrub_timer_fn(void *unused)
+{
+    page_scrub_schedule_work();
 }
 
 unsigned long avail_scrub_pages(void)
@@ -1049,6 +1058,10 @@ __initcall(register_heap_trigger);
 
 static __init int page_scrub_init(void)
 {
+    int cpu;
+    for_each_cpu ( cpu )
+        init_timer(&per_cpu(page_scrub_timer, cpu),
+                   page_scrub_timer_fn, NULL, cpu);
     open_softirq(PAGE_SCRUB_SOFTIRQ, page_scrub_softirq);
     return 0;
 }
diff -r 1a01d8d9dbec -r 215b799fa181 xen/common/sched_credit.c
--- a/xen/common/sched_credit.c Fri Mar 09 18:26:22 2007 +0000
+++ b/xen/common/sched_credit.c Fri Mar 09 18:26:47 2007 +0000
@@ -186,6 +186,8 @@ struct csched_pcpu {
 struct csched_pcpu {
     struct list_head runq;
     uint32_t runq_sort_last;
+    struct timer ticker;
+    unsigned int tick;
 };
 
 /*
@@ -245,7 +247,7 @@ struct csched_private {
  */
 static struct csched_private csched_priv;
 
-
+static void csched_tick(void *_cpu);
 
 static inline int
 __cycle_cpu(int cpu, const cpumask_t *mask)
@@ -362,12 +364,13 @@ csched_pcpu_init(int cpu)
     if ( csched_priv.master >= csched_priv.ncpus )
         csched_priv.master = cpu;
 
+    init_timer(&spc->ticker, csched_tick, (void *)(unsigned long)cpu, cpu);
     INIT_LIST_HEAD(&spc->runq);
     spc->runq_sort_last = csched_priv.runq_sort;
     per_cpu(schedule_data, cpu).sched_priv = spc;
 
     /* Start off idling... */
-    BUG_ON( !is_idle_vcpu(per_cpu(schedule_data, cpu).curr) );
+    BUG_ON(!is_idle_vcpu(per_cpu(schedule_data, cpu).curr));
     cpu_set(cpu, csched_priv.idlers);
 
     spin_unlock_irqrestore(&csched_priv.lock, flags);
@@ -1013,8 +1016,13 @@ csched_acct(void)
 }
 
 static void
-csched_tick(unsigned int cpu)
-{
+csched_tick(void *_cpu)
+{
+    unsigned int cpu = (unsigned long)_cpu;
+    struct csched_pcpu *spc = CSCHED_PCPU(cpu);
+
+    spc->tick++;
+
     /*
      * Accounting for running VCPU
      */
@@ -1028,7 +1036,7 @@ csched_tick(unsigned int cpu)
      * we could distribute or at the very least cycle the duty.
      */
     if ( (csched_priv.master == cpu) &&
-         (per_cpu(schedule_data, cpu).tick % CSCHED_TICKS_PER_ACCT) == 0 )
+         (spc->tick % CSCHED_TICKS_PER_ACCT) == 0 )
     {
         csched_acct();
     }
@@ -1041,6 +1049,8 @@ csched_tick(unsigned int cpu)
      * once per accounting period (currently 30 milliseconds).
      */
     csched_runq_sort(cpu);
+
+    set_timer(&spc->ticker, NOW() + MILLISECS(CSCHED_MSECS_PER_TICK));
 }
 
 static struct csched_vcpu *
@@ -1248,8 +1258,7 @@ csched_dump_pcpu(int cpu)
     spc = CSCHED_PCPU(cpu);
     runq = &spc->runq;
 
-    printk(" tick=%lu, sort=%d, sibling=0x%lx, core=0x%lx\n",
-            per_cpu(schedule_data, cpu).tick,
+    printk(" sort=%d, sibling=0x%lx, core=0x%lx\n",
             spc->runq_sort_last,
             cpu_sibling_map[cpu].bits[0],
             cpu_core_map[cpu].bits[0]);
@@ -1341,6 +1350,22 @@ csched_init(void)
     CSCHED_STATS_RESET();
 }
 
+/* Tickers cannot be kicked until SMP subsystem is alive. */
+static __init int csched_start_tickers(void)
+{
+    struct csched_pcpu *spc;
+    unsigned int cpu;
+
+    for_each_online_cpu ( cpu )
+    {
+        spc = CSCHED_PCPU(cpu);
+        set_timer(&spc->ticker, NOW() + MILLISECS(CSCHED_MSECS_PER_TICK));
+    }
+
+    return 0;
+}
+__initcall(csched_start_tickers);
+
 
 struct scheduler sched_credit_def = {
     .name           = "SMP Credit Scheduler",
@@ -1359,7 +1384,6 @@ struct scheduler sched_credit_def = {
     .adjust         = csched_dom_cntl,
 
     .pick_cpu       = csched_cpu_pick,
-    .tick           = csched_tick,
     .do_schedule    = csched_schedule,
 
     .dump_cpu_state = csched_dump_pcpu,
diff -r 1a01d8d9dbec -r 215b799fa181 xen/common/schedule.c
--- a/xen/common/schedule.c     Fri Mar 09 18:26:22 2007 +0000
+++ b/xen/common/schedule.c     Fri Mar 09 18:26:47 2007 +0000
@@ -45,8 +45,8 @@ boolean_param("dom0_vcpus_pin", opt_dom0
 
 /* Various timer handlers. */
 static void s_timer_fn(void *unused);
-static void t_timer_fn(void *unused);
-static void vcpu_timer_fn(void *data);
+static void vcpu_periodic_timer_fn(void *data);
+static void vcpu_singleshot_timer_fn(void *data);
 static void poll_timer_fn(void *data);
 
 /* This is global for now so that private implementations can reach it */
@@ -65,9 +65,6 @@ static struct scheduler ops;
 #define SCHED_OP(fn, ...)                                 \
          (( ops.fn != NULL ) ? ops.fn( __VA_ARGS__ )      \
           : (typeof(ops.fn(__VA_ARGS__)))0 )
-
-/* Per-CPU periodic timer sends an event to the currently-executing domain. */
-static DEFINE_PER_CPU(struct timer, t_timer);
 
 static inline void vcpu_runstate_change(
     struct vcpu *v, int new_state, s_time_t new_entry_time)
@@ -114,8 +111,12 @@ int sched_init_vcpu(struct vcpu *v, unsi
         cpus_setall(v->cpu_affinity);
 
     /* Initialise the per-domain timers. */
-    init_timer(&v->timer, vcpu_timer_fn, v, v->processor);
-    init_timer(&v->poll_timer, poll_timer_fn, v, v->processor);
+    init_timer(&v->periodic_timer, vcpu_periodic_timer_fn,
+               v, v->processor);
+    init_timer(&v->singleshot_timer, vcpu_singleshot_timer_fn,
+               v, v->processor);
+    init_timer(&v->poll_timer, poll_timer_fn,
+               v, v->processor);
 
     /* Idle VCPUs are scheduled immediately. */
     if ( is_idle_domain(d) )
@@ -132,7 +133,8 @@ int sched_init_vcpu(struct vcpu *v, unsi
 
 void sched_destroy_vcpu(struct vcpu *v)
 {
-    kill_timer(&v->timer);
+    kill_timer(&v->periodic_timer);
+    kill_timer(&v->singleshot_timer);
     kill_timer(&v->poll_timer);
     SCHED_OP(destroy_vcpu, v);
 }
@@ -223,10 +225,29 @@ static void vcpu_migrate(struct vcpu *v)
     vcpu_wake(v);
 }
 
+/*
+ * Force a VCPU through a deschedule/reschedule path.
+ * For example, using this when setting the periodic timer period means that
+ * most periodic-timer state need only be touched from within the scheduler
+ * which can thus be done without need for synchronisation.
+ */
+void vcpu_force_reschedule(struct vcpu *v)
+{
+    vcpu_schedule_lock_irq(v);
+    if ( test_bit(_VCPUF_running, &v->vcpu_flags) )
+        set_bit(_VCPUF_migrating, &v->vcpu_flags);
+    vcpu_schedule_unlock_irq(v);
+
+    if ( test_bit(_VCPUF_migrating, &v->vcpu_flags) )
+    {
+        vcpu_sleep_nosync(v);
+        vcpu_migrate(v);
+    }
+}
+
 int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity)
 {
     cpumask_t online_affinity;
-    unsigned long flags;
 
     if ( (v->domain->domain_id == 0) && opt_dom0_vcpus_pin )
         return -EINVAL;
@@ -235,13 +256,13 @@ int vcpu_set_affinity(struct vcpu *v, cp
     if ( cpus_empty(online_affinity) )
         return -EINVAL;
 
-    vcpu_schedule_lock_irqsave(v, flags);
+    vcpu_schedule_lock_irq(v);
 
     v->cpu_affinity = *affinity;
     if ( !cpu_isset(v->processor, v->cpu_affinity) )
         set_bit(_VCPUF_migrating, &v->vcpu_flags);
 
-    vcpu_schedule_unlock_irqrestore(v, flags);
+    vcpu_schedule_unlock_irq(v);
 
     if ( test_bit(_VCPUF_migrating, &v->vcpu_flags) )
     {
@@ -458,7 +479,7 @@ long do_set_timer_op(s_time_t timeout)
 
     if ( timeout == 0 )
     {
-        stop_timer(&v->timer);
+        stop_timer(&v->singleshot_timer);
     }
     else if ( unlikely(timeout < 0) || /* overflow into 64th bit? */
               unlikely((offset > 0) && ((uint32_t)(offset >> 50) != 0)) )
@@ -474,14 +495,20 @@ long do_set_timer_op(s_time_t timeout)
          * timeout in this case can burn a lot of CPU. We therefore go for a
          * reasonable middleground of triggering a timer event in 100ms.
          */
-        gdprintk(XENLOG_INFO, "Warning: huge timeout set by domain %d (vcpu 
%d):"
-                " %"PRIx64"\n",
+        gdprintk(XENLOG_INFO, "Warning: huge timeout set by domain %d "
+                "(vcpu %d): %"PRIx64"\n",
                 v->domain->domain_id, v->vcpu_id, (uint64_t)timeout);
-        set_timer(&v->timer, NOW() + MILLISECS(100));
+        set_timer(&v->singleshot_timer, NOW() + MILLISECS(100));
     }
     else
     {
-        set_timer(&v->timer, timeout);
+        if ( v->singleshot_timer.cpu != smp_processor_id() )
+        {
+            stop_timer(&v->singleshot_timer);
+            v->singleshot_timer.cpu = smp_processor_id();
+        }
+
+        set_timer(&v->singleshot_timer, timeout);
     }
 
     return 0;
@@ -540,6 +567,28 @@ long sched_adjust(struct domain *d, stru
     return 0;
 }
 
+static void vcpu_periodic_timer_work(struct vcpu *v)
+{
+    s_time_t now = NOW();
+    uint64_t periodic_next_event;
+
+    ASSERT(!active_timer(&v->periodic_timer));
+
+    if ( v->periodic_period == 0 )
+        return;
+
+    periodic_next_event = v->periodic_last_event + v->periodic_period;
+    if ( now > periodic_next_event )
+    {
+        send_timer_event(v);
+        v->periodic_last_event = now;
+        periodic_next_event = now + v->periodic_period;
+    }
+
+    v->periodic_timer.cpu = smp_processor_id();
+    set_timer(&v->periodic_timer, periodic_next_event);
+}
+
 /* 
  * The main function
  * - deschedule the current domain (scheduler independent).
@@ -606,14 +655,13 @@ static void schedule(void)
 
     perfc_incrc(sched_ctx);
 
-    prev->sleep_tick = sd->tick;
+    stop_timer(&prev->periodic_timer);
 
     /* Ensure that the domain has an up-to-date time base. */
     if ( !is_idle_vcpu(next) )
     {
         update_vcpu_system_time(next);
-        if ( next->sleep_tick != sd->tick )
-            send_timer_event(next);
+        vcpu_periodic_timer_work(next);
     }
 
     TRACE_4D(TRC_SCHED_SWITCH,
@@ -631,13 +679,6 @@ void context_saved(struct vcpu *prev)
         vcpu_migrate(prev);
 }
 
-/****************************************************************************
- * Timers: the scheduler utilises a number of timers
- * - s_timer: per CPU timer for preemption and scheduling decisions
- * - t_timer: per CPU periodic timer to send timer interrupt to current dom
- * - dom_timer: per domain timer to specifiy timeout values
- ****************************************************************************/
-
 /* The scheduler timer: force a run through the scheduler */
 static void s_timer_fn(void *unused)
 {
@@ -645,28 +686,15 @@ static void s_timer_fn(void *unused)
     perfc_incrc(sched_irq);
 }
 
-/* Periodic tick timer: send timer event to current domain */
-static void t_timer_fn(void *unused)
-{
-    struct vcpu *v   = current;
-
-    this_cpu(schedule_data).tick++;
-
-    if ( !is_idle_vcpu(v) )
-    {
-        update_vcpu_system_time(v);
-        send_timer_event(v);
-    }
-
-    page_scrub_schedule_work();
-
-    SCHED_OP(tick, smp_processor_id());
-
-    set_timer(&this_cpu(t_timer), NOW() + MILLISECS(10));
-}
-
-/* Per-VCPU timer function: sends a virtual timer interrupt. */
-static void vcpu_timer_fn(void *data)
+/* Per-VCPU periodic timer function: sends a virtual timer interrupt. */
+static void vcpu_periodic_timer_fn(void *data)
+{
+    struct vcpu *v = data;
+    vcpu_periodic_timer_work(v);
+}
+
+/* Per-VCPU single-shot timer function: sends a virtual timer interrupt. */
+static void vcpu_singleshot_timer_fn(void *data)
 {
     struct vcpu *v = data;
     send_timer_event(v);
@@ -691,7 +719,6 @@ void __init scheduler_init(void)
     {
         spin_lock_init(&per_cpu(schedule_data, i).schedule_lock);
         init_timer(&per_cpu(schedule_data, i).s_timer, s_timer_fn, NULL, i);
-        init_timer(&per_cpu(t_timer, i), t_timer_fn, NULL, i);
     }
 
     for ( i = 0; schedulers[i] != NULL; i++ )
@@ -706,16 +733,6 @@ void __init scheduler_init(void)
 
     printk("Using scheduler: %s (%s)\n", ops.name, ops.opt_name);
     SCHED_OP(init);
-}
-
-/*
- * Start a scheduler for each CPU
- * This has to be done *after* the timers, e.g., APICs, have been initialised
- */
-void schedulers_start(void) 
-{   
-    t_timer_fn(0);
-    smp_call_function((void *)t_timer_fn, NULL, 1, 1);
 }
 
 void dump_runq(unsigned char key)
diff -r 1a01d8d9dbec -r 215b799fa181 xen/include/public/vcpu.h
--- a/xen/include/public/vcpu.h Fri Mar 09 18:26:22 2007 +0000
+++ b/xen/include/public/vcpu.h Fri Mar 09 18:26:47 2007 +0000
@@ -42,13 +42,13 @@
  * @extra_arg == pointer to vcpu_guest_context structure containing initial
  *               state for the VCPU.
  */
-#define VCPUOP_initialise           0
+#define VCPUOP_initialise            0
 
 /*
  * Bring up a VCPU. This makes the VCPU runnable. This operation will fail
  * if the VCPU has not been initialised (VCPUOP_initialise).
  */
-#define VCPUOP_up                   1
+#define VCPUOP_up                    1
 
 /*
  * Bring down a VCPU (i.e., make it non-runnable).
@@ -64,16 +64,16 @@
  *     practise to move a VCPU onto an 'idle' or default page table, LDT and
  *     GDT before bringing it down.
  */
-#define VCPUOP_down                 2
+#define VCPUOP_down                  2
 
 /* Returns 1 if the given VCPU is up. */
-#define VCPUOP_is_up                3
+#define VCPUOP_is_up                 3
 
 /*
  * Return information about the state and running time of a VCPU.
  * @extra_arg == pointer to vcpu_runstate_info structure.
  */
-#define VCPUOP_get_runstate_info    4
+#define VCPUOP_get_runstate_info     4
 struct vcpu_runstate_info {
     /* VCPU's current state (RUNSTATE_*). */
     int      state;
@@ -128,6 +128,32 @@ struct vcpu_register_runstate_memory_are
     } addr;
 };
 typedef struct vcpu_register_runstate_memory_area 
vcpu_register_runstate_memory_area_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_register_runstate_memory_area_t);
+
+/*
+ * Set or stop a VCPU's periodic timer. Every VCPU has one periodic timer
+ * which can be set via these commands. Periods smaller than one millisecond
+ * may not be supported.
+ */
+#define VCPUOP_set_periodic_timer    6 /* arg == vcpu_set_periodic_timer_t */
+#define VCPUOP_stop_periodic_timer   7 /* arg == NULL */
+struct vcpu_set_periodic_timer {
+    uint64_t period_ns;
+};
+typedef struct vcpu_set_periodic_timer vcpu_set_periodic_timer_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_set_periodic_timer_t);
+
+/*
+ * Set or stop a VCPU's single-shot timer. Every VCPU has one single-shot
+ * timer which can be set via these commands.
+ */
+#define VCPUOP_set_singleshot_timer  8 /* arg == vcpu_set_singleshot_timer_t */
+#define VCPUOP_stop_singleshot_timer 9 /* arg == NULL */
+struct vcpu_set_singleshot_timer {
+    uint64_t timeout_abs_ns;
+};
+typedef struct vcpu_set_singleshot_timer vcpu_set_singleshot_timer_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_set_singleshot_timer_t);
 
 #endif /* __XEN_PUBLIC_VCPU_H__ */
 
diff -r 1a01d8d9dbec -r 215b799fa181 xen/include/xen/mm.h
--- a/xen/include/xen/mm.h      Fri Mar 09 18:26:22 2007 +0000
+++ b/xen/include/xen/mm.h      Fri Mar 09 18:26:47 2007 +0000
@@ -92,6 +92,11 @@ extern struct list_head page_scrub_list;
         if ( !list_empty(&page_scrub_list) )    \
             raise_softirq(PAGE_SCRUB_SOFTIRQ);  \
     } while ( 0 )
+#define page_scrub_kick()                                               \
+    do {                                                                \
+        if ( !list_empty(&page_scrub_list) )                            \
+            cpumask_raise_softirq(cpu_online_map, PAGE_SCRUB_SOFTIRQ);  \
+    } while ( 0 )
 unsigned long avail_scrub_pages(void);
 
 #include <asm/mm.h>
diff -r 1a01d8d9dbec -r 215b799fa181 xen/include/xen/sched-if.h
--- a/xen/include/xen/sched-if.h        Fri Mar 09 18:26:22 2007 +0000
+++ b/xen/include/xen/sched-if.h        Fri Mar 09 18:26:47 2007 +0000
@@ -16,7 +16,6 @@ struct schedule_data {
     struct vcpu        *idle;           /* idle task for this cpu          */
     void               *sched_priv;
     struct timer        s_timer;        /* scheduling timer                */
-    unsigned long       tick;           /* current periodic 'tick'         */
 } __cacheline_aligned;
 
 DECLARE_PER_CPU(struct schedule_data, schedule_data);
@@ -61,7 +60,6 @@ struct scheduler {
     unsigned int sched_id;  /* ID for this scheduler             */
 
     void         (*init)           (void);
-    void         (*tick)           (unsigned int cpu);
 
     int          (*init_domain)    (struct domain *);
     void         (*destroy_domain) (struct domain *);
diff -r 1a01d8d9dbec -r 215b799fa181 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Fri Mar 09 18:26:22 2007 +0000
+++ b/xen/include/xen/sched.h   Fri Mar 09 18:26:47 2007 +0000
@@ -79,8 +79,10 @@ struct vcpu
 
     struct vcpu     *next_in_list;
 
-    struct timer     timer;         /* one-shot timer for timeout values */
-    unsigned long    sleep_tick;    /* tick at which this vcpu started sleep */
+    uint64_t         periodic_period;
+    uint64_t         periodic_last_event;
+    struct timer     periodic_timer;
+    struct timer     singleshot_timer;
 
     struct timer     poll_timer;    /* timeout for SCHEDOP_poll */
 
@@ -332,7 +334,6 @@ void __domain_crash_synchronous(void) __
 
 #define set_current_state(_s) do { current->state = (_s); } while (0)
 void scheduler_init(void);
-void schedulers_start(void);
 int  sched_init_vcpu(struct vcpu *v, unsigned int processor);
 void sched_destroy_vcpu(struct vcpu *v);
 int  sched_init_domain(struct domain *d);
@@ -497,6 +498,7 @@ void domain_unpause_by_systemcontroller(
 void domain_unpause_by_systemcontroller(struct domain *d);
 void cpu_init(void);
 
+void vcpu_force_reschedule(struct vcpu *v);
 int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity);
 
 void vcpu_runstate_get(struct vcpu *v, struct vcpu_runstate_info *runstate);
diff -r 1a01d8d9dbec -r 215b799fa181 xen/include/xen/timer.h
--- a/xen/include/xen/timer.h   Fri Mar 09 18:26:22 2007 +0000
+++ b/xen/include/xen/timer.h   Fri Mar 09 18:26:47 2007 +0000
@@ -35,7 +35,7 @@ struct timer {
  * The timer must *previously* have been initialised by init_timer(), or its
  * structure initialised to all-zeroes.
  */
-static __inline__ int active_timer(struct timer *timer)
+static inline int active_timer(struct timer *timer)
 {
     return (timer->heap_offset != 0);
 }
@@ -46,7 +46,7 @@ static __inline__ int active_timer(struc
  * time (and multiple times) on an inactive timer. It must *never* execute
  * concurrently with any other operation on the same timer.
  */
-static __inline__ void init_timer(
+static inline void init_timer(
     struct timer *timer,
     void           (*function)(void *),
     void            *data,

_______________________________________________
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®.