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

[Xen-devel] [PATCH 2/4] SMP support to Xen PM


  • To: "Keir Fraser" <keir@xxxxxxxxxxxxx>
  • From: "Tian, Kevin" <kevin.tian@xxxxxxxxx>
  • Date: Thu, 19 Jul 2007 18:03:18 +0800
  • Cc: xen-devel@xxxxxxxxxxxxxxxxxxx
  • Delivery-date: Thu, 19 Jul 2007 03:01:17 -0700
  • List-id: Xen developer discussion <xen-devel.lists.xensource.com>
  • Thread-index: AcfJ7AeIgUMH5dJnSkyoXbSfCHcyvw==
  • Thread-topic: [PATCH 2/4] SMP support to Xen PM

Add SMP sleep support to Xen. One new utility is created
to allow vcpu continue previous running after migration
to new processor.

Signed-off-by Kevin Tian <kevin.tian@xxxxxxxxx>
diff -r 3de9eb0bc3c1 xen/arch/x86/acpi/power.c
--- a/xen/arch/x86/acpi/power.c Thu Jul 19 14:35:47 2007 +0800
+++ b/xen/arch/x86/acpi/power.c Thu Jul 19 17:26:05 2007 +0800
@@ -119,19 +119,25 @@ int enter_state(u32 state)
     if (state <= ACPI_STATE_S0 || state > ACPI_S_STATES_MAX)
         return -EINVAL;
 
-    /* Sync lazy state on ths cpu */
     __sync_lazy_execstate();
     pmprintk(XENLOG_INFO, "Flush lazy state\n");
 
     if (!spin_trylock(&pm_lock))
         return -EBUSY;
     
-    freeze_domains();
-
-    hvm_cpu_down();
-
     pmprintk(XENLOG_INFO, "PM: Preparing system for %s sleep\n",
         acpi_states[state]);
+
+    freeze_domains();
+
+    disable_nonboot_cpus();
+    if (num_online_cpus() != 1)
+    {
+        error = -EBUSY;
+        goto Enable_cpu;
+    }
+
+    hvm_cpu_down();
 
     acpi_sleep_prepare(state);
 
@@ -169,9 +175,28 @@ int enter_state(u32 state)
     if ( !hvm_cpu_up() )
         BUG();
 
+ Enable_cpu:
+    enable_nonboot_cpus();
+
     thaw_domains();
     spin_unlock(&pm_lock);
     return error;
+}
+
+static void acpi_power_off(void)
+{
+    pmprintk(XENLOG_INFO, "%s called\n", __FUNCTION__);
+    local_irq_disable();
+    /* Some SMP machines only can poweroff in boot CPU */
+    acpi_enter_sleep_state(ACPI_STATE_S5);
+}
+
+static void enter_state_helper(void *data)
+{
+    struct cpu_user_regs *regs = guest_cpu_user_regs();
+    struct acpi_sleep_info *sinfo = (struct acpi_sleep_info *)data;
+
+    regs->eax = enter_state(sinfo->sleep_state);
 }
 
 /*
@@ -187,6 +212,8 @@ int enter_state(u32 state)
  */
 int acpi_enter_sleep(struct xenpf_enter_acpi_sleep *sleep)
 {
+    int ret;
+
     if (!IS_PRIV(current->domain) || !acpi_sinfo.pm1a_cnt)
         return -EPERM;
 
@@ -215,7 +242,26 @@ int acpi_enter_sleep(struct xenpf_enter_
     acpi_video_flags = sleep->video_flags;
     saved_videomode = sleep->video_mode;
 
-    return enter_state(acpi_sinfo.sleep_state);
+    /* acpi power off method */
+    if (acpi_sinfo.sleep_state == ACPI_STATE_S5)
+    {
+        acpi_power_off();
+        /* Shouldn't return */
+        while(1);
+    }
+
+    if (current->processor == 0)
+    {
+        pmprintk(XENLOG_INFO, "vcpu0 on cpu0, sleep direclty\n");
+        ret = enter_state(acpi_sinfo.sleep_state);
+    }
+    else
+    {
+        pmprintk(XENLOG_INFO, "vcpu0 on cpu%d, migrate to cpu0\n",
+            current->processor);
+        ret = self_migrate_and_continue(0, enter_state_helper,
&acpi_sinfo);
+    }
+    return ret;
 }
 
 static int acpi_get_wake_status(void)
diff -r 3de9eb0bc3c1 xen/arch/x86/cpu/intel_cacheinfo.c
--- a/xen/arch/x86/cpu/intel_cacheinfo.c        Thu Jul 19 14:35:47 2007
+0800
+++ b/xen/arch/x86/cpu/intel_cacheinfo.c        Thu Jul 19 17:26:14 2007
+0800
@@ -17,7 +17,7 @@ struct _cache_table
 };
 
 /* all the cache descriptor types we care about (no TLB or trace cache
entries) */
-static struct _cache_table cache_table[] __initdata =
+static struct _cache_table cache_table[] __devinitdata =
 {
        { 0x06, LVL_1_INST, 8 },        /* 4-way set assoc, 32 byte line
size */
        { 0x08, LVL_1_INST, 16 },       /* 4-way set assoc, 32 byte line
size */
@@ -60,7 +60,7 @@ static struct _cache_table cache_table[]
        { 0x00, 0, 0}
 };
 
-unsigned int __init init_intel_cacheinfo(struct cpuinfo_x86 *c)
+unsigned int __devinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
 {
        unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /*
Cache sizes */
 
diff -r 3de9eb0bc3c1 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Thu Jul 19 14:35:47 2007 +0800
+++ b/xen/arch/x86/domain.c     Thu Jul 19 14:35:48 2007 +0800
@@ -82,6 +82,7 @@ static void play_dead(void)
     __cpu_disable();
     /* This must be done before dead CPU ack */
     cpu_exit_clear();
+    hvm_cpu_down();
     wbinvd();
     mb();
     /* Ack it */
@@ -1361,6 +1362,56 @@ void sync_vcpu_execstate(struct vcpu *v)
 
     /* Other cpus call __sync_lazy_execstate from flush ipi handler. */
     flush_tlb_mask(v->vcpu_dirty_cpumask);
+}
+
+struct migrate_info {
+    void (*saved_schedule_tail) (struct vcpu *);
+    void (*func) (void *data);
+    void *data;
+    cpumask_t saved_affinity;
+};
+
+/* helper to continue previous flow on new cpu, and recover
+ * necessary context at exit
+ */
+static void self_migrate_helper(struct vcpu *v)
+{
+    struct migrate_info *info = v->arch.continue_info;
+
+    if (info->func)
+        info->func(info->data);
+
+    v->arch.schedule_tail = info->saved_schedule_tail;
+    v->cpu_affinity = info->saved_affinity;
+    xfree(info);
+
+    vcpu_set_affinity(v, &v->cpu_affinity);
+
+    /* In case no migration again */
+    schedule_tail(v);
+}
+
+int self_migrate_and_continue(int  cpu,
+                              void (*func)(void *data),
+                              void *data)
+{
+    struct vcpu *v = current;
+    struct migrate_info *info;
+    cpumask_t mask = cpumask_of_cpu(cpu);
+
+    info = xmalloc(struct migrate_info);
+    if (!info)
+        return -ENOMEM;
+
+    info->func = func;
+    info->data = data;
+    info->saved_schedule_tail = v->arch.schedule_tail;
+    v->arch.schedule_tail = self_migrate_helper;
+
+    info->saved_affinity = v->cpu_affinity;
+    v->arch.continue_info = info;
+    vcpu_set_affinity(v, &mask);
+    return 0;
 }
 
 #define next_arg(fmt, args) ({
\
diff -r 3de9eb0bc3c1 xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h      Thu Jul 19 14:35:47 2007 +0800
+++ b/xen/include/asm-x86/domain.h      Thu Jul 19 14:35:48 2007 +0800
@@ -268,6 +268,9 @@ struct arch_vcpu
     void (*ctxt_switch_from) (struct vcpu *);
     void (*ctxt_switch_to) (struct vcpu *);
 
+    /* Record information required to continue execution after
migration */
+    void *continue_info;
+
     /* Bounce information for propagating an exception to guest OS. */
     struct trap_bounce trap_bounce;
 
diff -r 3de9eb0bc3c1 xen/include/asm-x86/smp.h
--- a/xen/include/asm-x86/smp.h Thu Jul 19 14:35:47 2007 +0800
+++ b/xen/include/asm-x86/smp.h Thu Jul 19 14:35:48 2007 +0800
@@ -66,6 +66,8 @@ extern void enable_nonboot_cpus(void);
 extern void enable_nonboot_cpus(void);
 #else
 static inline int cpu_is_offline(int cpu) {return 0;}
+static inline void disable_nonboot_cpus(void) {}
+static inline void enable_nonboot_cpus(void) {}
 #endif
 
 /*
diff -r 3de9eb0bc3c1 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Thu Jul 19 14:35:47 2007 +0800
+++ b/xen/include/xen/sched.h   Thu Jul 19 14:35:48 2007 +0800
@@ -479,6 +479,10 @@ int vcpu_set_affinity(struct vcpu *v, cp
 
 void vcpu_runstate_get(struct vcpu *v, struct vcpu_runstate_info
*runstate);
 
+int self_migrate_and_continue(int  cpu,
+                              void (*func)(void *data),
+                              void *data);
+
 static inline void vcpu_unblock(struct vcpu *v)
 {
     if ( test_and_clear_bit(_VPF_blocked, &v->pause_flags) )

Attachment: xen_smp_pm_support.patch
Description: xen_smp_pm_support.patch

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

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