WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 12/12] SMP support to Xen PM

To: "Keir Fraser" <Keir.Fraser@xxxxxxxxxxxx>, "Ian Pratt" <m+Ian.Pratt@xxxxxxxxxxxx>, <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH 12/12] SMP support to Xen PM
From: "Tian, Kevin" <kevin.tian@xxxxxxxxx>
Date: Wed, 14 Feb 2007 17:20:13 +0800
Cc: "Yu, Ke" <ke.yu@xxxxxxxxx>
Delivery-date: Wed, 14 Feb 2007 01:21:01 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Thread-index: AcdQGVUPjJqPs5WmTzqK3sNAnGbFYw==
Thread-topic: [PATCH 12/12] SMP support to Xen PM
Utilize cpu hotplug infrastructure to pull down all other
cpus except cpu0, before starting suspend sequence. One
trick point is, cpu0 is a bit special and we'd better do
suspend on it. However vcpu0/dom0 is the one to trigger
power event which however may not bind to cpu0. So a new
softirq is introduced to switch flow to idle vcpu on cpu0
if such case happens.

Signed-off-by Kevin Tian <kevin.tian@xxxxxxxxx>

diff -r 308c4ef593e9 xen/arch/x86/acpi/power.c
--- a/xen/arch/x86/acpi/power.c Wed Feb 14 11:13:42 2007 +0800
+++ b/xen/arch/x86/acpi/power.c Wed Feb 14 14:59:23 2007 +0800
@@ -23,6 +23,7 @@
 #include <xen/sched.h>
 #include <xen/domain.h>
 #include <xen/console.h>
+#include <xen/softirq.h>
 
 u8 sleep_states[ACPI_S_STATE_COUNT];
 DEFINE_SPINLOCK(pm_lock);
@@ -75,26 +76,48 @@ static void device_power_up(void)
     console_resume();
 }
 
-/* Main interface to do xen specific suspend/resume */
-int enter_state(u32 state)
+static void freeze_domains(void)
 {
     struct domain *d;
-    unsigned long flags;
-    int error;
-
-    if (state <= ACPI_STATE_S0 || state > ACPI_S_STATES_MAX)
-        return -EINVAL;
-
-    if (!spin_trylock(&pm_lock))
-        return -EBUSY;
-    
+
     for_each_domain(d)
        if (d->domain_id != 0) {
            domain_pause(d);
            arch_domain_suspend(d);
     }
-
+}
+
+static void thaw_domains(void)
+{
+    struct domain *d;
+
+    for_each_domain(d)
+       if (d->domain_id != 0)
+           domain_unpause(d);
+}
+
+/* Main interface to do xen specific suspend/resume */
+int enter_state(u32 state)
+{
+    unsigned long flags;
+    int error;
+
+    if (smp_processor_id() != 0)
+        return -EPERM;
+
+    if (state <= ACPI_STATE_S0 || state > ACPI_S_STATES_MAX)
+        return -EINVAL;
+
+    if (!spin_trylock(&pm_lock))
+        return -EBUSY;
+    
     printk("PM: Preparing system for %s sleep\n", acpi_states[state]);
+
+    disable_nonboot_cpus();
+    if (num_online_cpus() != 1) {
+        error = -EBUSY;
+        goto Enable_cpu;
+    }
 
     local_irq_save(flags);
 
@@ -128,12 +151,10 @@ int enter_state(u32 state)
     device_power_up();
 
     printk("PM: Finishing wakeup.\n");
-    for_each_domain(d)
-       if (d->domain_id!=0)
-           domain_unpause(d);
-
  Done:
     local_irq_restore(flags);
+ Enable_cpu:
+    enable_nonboot_cpus();
     spin_unlock(&pm_lock);
     return error;
 
@@ -202,7 +223,22 @@ 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);
+    freeze_domains();
+    if (current->processor == 0) {
+        int ret;
+
+        printk(XENLOG_INFO "vcpu0 on cpu0, sleep direclty\n");
+        ret = enter_state(acpi_sinfo.sleep_state);
+        thaw_domains();
+        return ret;
+    }
+
+    printk(XENLOG_INFO "vcpu0 on cpu%d, pause self and notify cpu0\n",
+        current->processor);
+    cpu_raise_softirq(0, PM_SOFTIRQ);
+    vcpu_pause_self();
+    /* return value doens't matter here. */
+    return 0;
 }
 
 static int acpi_get_wake_status(void)
@@ -228,6 +264,49 @@ acpi_status asmlinkage acpi_enter_sleep_
     /* Wait until we enter sleep state, and spin until we wake */
     while (!acpi_get_wake_status());
     return_ACPI_STATUS(AE_OK);
+}
+
+/*
+ * Power management related softirq, and cpu0 only.
+ *
+ * The reason for introducing this softirq is that cpu0 is a bit
+ * special as the last one to be pull down. However the sleep request
+ * is issued from vcpu0 of dom0 and this vcpu may not bind to cpu0.
+ *
+ * So if above case happens, the CPU receiving sleep request will
+ * raise a softirq to cpu0 and idle vcpu on cpu0 then execute this
+ * handler immediately.
+ *
+ * If vcpu0 is already running on cpu0, this softirq is not triggered
+ */
+static void pm_softirq(void)
+{
+    int cpu = smp_processor_id();
+    struct vcpu *v = dom0->vcpu[0];
+    struct cpu_user_regs *regs;
+
+    printk(XENLOG_DEBUG "In pm_softirq\n");
+    /* only cpu0 handles this irq for now */
+    if (cpu != 0)
+        return;
+
+    printk(XENLOG_DEBUG "handled by cpu0\n");
+    /* wait vcpu0/dom0 to pause itself */
+    while ( test_bit(_VCPUF_migrating, &v->vcpu_flags) )
+        cpu_relax();
+
+    while ( test_bit(_VCPUF_need_sync, &v->vcpu_flags) )
+        cpu_relax();
+
+    printk(XENLOG_INFO "vcpu0/dom0 has been paused\n");
+    /* now safe to suspend whole system from cpu 0 */
+    regs = &v->arch.guest_context.user_regs;
+    regs->eax = enter_state(acpi_sinfo.sleep_state);
+
+    /* Now unpause vcpu0/dom0 */
+    vcpu_unpause(v);
+
+    thaw_domains();
 }
 
 static int __init acpi_sleep_init(void)
@@ -247,6 +326,8 @@ static int __init acpi_sleep_init(void)
     printk(")\n");
 
     acpi_reserve_bootmem();
+
+    open_softirq(PM_SOFTIRQ, pm_softirq);
     return 0;
 }
 __initcall(acpi_sleep_init);
diff -r 308c4ef593e9 xen/include/asm-x86/smp.h
--- a/xen/include/asm-x86/smp.h Wed Feb 14 11:13:42 2007 +0800
+++ b/xen/include/asm-x86/smp.h Wed Feb 14 11:13:42 2007 +0800
@@ -70,6 +70,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 308c4ef593e9 xen/include/xen/softirq.h
--- a/xen/include/xen/softirq.h Wed Feb 14 11:13:42 2007 +0800
+++ b/xen/include/xen/softirq.h Wed Feb 14 11:13:42 2007 +0800
@@ -10,8 +10,9 @@
 #define PAGE_SCRUB_SOFTIRQ                5
 #define TRACE_SOFTIRQ                     6
 #define RCU_SOFTIRQ                       7
+#define PM_SOFTIRQ                        8
 
-#define NR_COMMON_SOFTIRQS                8
+#define NR_COMMON_SOFTIRQS                9
 
 #include <asm/softirq.h>

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
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH 12/12] SMP support to Xen PM, Tian, Kevin <=