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

[Xen-devel] [PATCH]cpuidle: mwait on softirq_pending & remove wakeup ipis



cpuidle: mwait on softirq_pending & remove wakeup ipis

For cpu which enter deep C state via monitor/mwait, wakeup can be done by 
writing to the monitored memory. So once monitor softirq_pending, we can remove 
the redundant ipis.

Signed-off-by: Yu Ke <ke.yu@xxxxxxxxx>
Signed-off-by: Wei Gang <gang.wei@xxxxxxxxx>

diff -r 132ac04cbdba xen/arch/x86/acpi/cpu_idle.c
--- a/xen/arch/x86/acpi/cpu_idle.c      Tue Mar 09 18:18:19 2010 +0000
+++ b/xen/arch/x86/acpi/cpu_idle.c      Thu Mar 11 14:07:54 2010 +0800
@@ -69,6 +69,14 @@ boolean_param("lapic_timer_c2_ok", local
 
 static struct acpi_processor_power *__read_mostly processor_powers[NR_CPUS];
 
+static char* acpi_cstate_method_name[] =
+{
+    "NONE",
+    "SYSIO",
+    "FFH",
+    "HALT"
+};
+
 static void print_acpi_power(uint32_t cpu, struct acpi_processor_power *power)
 {
     uint32_t i, idle_usage = 0;
@@ -92,6 +100,7 @@ static void print_acpi_power(uint32_t cp
         printk("type[C%d] ", power->states[i].type);
         printk("latency[%03d] ", power->states[i].latency);
         printk("usage[%08d] ", power->states[i].usage);
+        printk("method[%5s] ", 
acpi_cstate_method_name[power->states[i].entry_method]);
         printk("duration[%"PRId64"]\n", res);
     }
     printk("    C0:\tusage[%08d] duration[%"PRId64"]\n",
@@ -140,11 +149,43 @@ static void acpi_safe_halt(void)
 
 #define MWAIT_ECX_INTERRUPT_BREAK   (0x1)
 
+/*
+ * The bit is set iff cpu use monitor/mwait to enter C state
+ * with this flag set, CPU can be waken up from C state
+ * by writing to specific memory address, instead of sending IPI
+ */
+static cpumask_t cpuidle_mwait_flags;
+
+void cpuidle_wakeup_mwait(cpumask_t *mask)
+{
+    cpumask_t target;
+    int cpu;
+
+    cpus_and(target, *mask, cpuidle_mwait_flags);
+
+    /* cpu is 'mwait'ing at softirq_pending,
+       writing to it will wake up CPU */
+    for_each_cpu_mask(cpu, target)
+        set_bit(TIMER_SOFTIRQ, &softirq_pending(cpu));
+
+    cpus_andnot(*mask, *mask, cpuidle_mwait_flags);
+}
+
 static void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
 {
-    __monitor((void *)current, 0, 0);
+    int cpu = smp_processor_id();
+
+    __monitor((void *)&softirq_pending(cpu), 0, 0);
+
     smp_mb();
-    __mwait(eax, ecx);
+    if (!softirq_pending(cpu))
+    {
+        cpu_set(cpu, cpuidle_mwait_flags);
+
+        __mwait(eax, ecx);
+
+        cpu_clear(cpu, cpuidle_mwait_flags);
+    }
 }
 
 static void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
diff -r 132ac04cbdba xen/arch/x86/hpet.c
--- a/xen/arch/x86/hpet.c       Tue Mar 09 18:18:19 2010 +0000
+++ b/xen/arch/x86/hpet.c       Thu Mar 11 14:07:54 2010 +0800
@@ -165,6 +165,8 @@ static int evt_do_broadcast(cpumask_t ma
         raise_softirq(TIMER_SOFTIRQ);
         ret = 1;
     }
+
+    cpuidle_wakeup_mwait(&mask);
 
     if ( !cpus_empty(mask) )
     {
diff -r 132ac04cbdba xen/include/xen/cpuidle.h
--- a/xen/include/xen/cpuidle.h Tue Mar 09 18:18:19 2010 +0000
+++ b/xen/include/xen/cpuidle.h Thu Mar 11 14:07:54 2010 +0800
@@ -86,6 +86,8 @@ extern struct cpuidle_governor *cpuidle_
 extern struct cpuidle_governor *cpuidle_current_governor;
 void cpuidle_disable_deep_cstate(void);
 
+extern void cpuidle_wakeup_mwait(cpumask_t *mask);
+
 #define CPUIDLE_DRIVER_STATE_START  1
 
 #endif /* _XEN_CPUIDLE_H */

Attachment: cpuidle_mwait_fix_v2.patch
Description: cpuidle_mwait_fix_v2.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®.