# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1270533131 -3600
# Node ID cd6c6c68501591b99a06d3e149465fb2b55ea794
# Parent 4a3e131f749897f79ff619235d6310cbd69b3ba3
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>
---
xen/arch/x86/acpi/cpu_idle.c | 45 +++++++++++++++++++++++++++++++++++++++++--
xen/arch/x86/hpet.c | 2 +
xen/include/xen/cpuidle.h | 2 +
3 files changed, 47 insertions(+), 2 deletions(-)
diff -r 4a3e131f7498 -r cd6c6c685015 xen/arch/x86/acpi/cpu_idle.c
--- a/xen/arch/x86/acpi/cpu_idle.c Tue Apr 06 06:51:04 2010 +0100
+++ b/xen/arch/x86/acpi/cpu_idle.c Tue Apr 06 06:52:11 2010 +0100
@@ -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 4a3e131f7498 -r cd6c6c685015 xen/arch/x86/hpet.c
--- a/xen/arch/x86/hpet.c Tue Apr 06 06:51:04 2010 +0100
+++ b/xen/arch/x86/hpet.c Tue Apr 06 06:52:11 2010 +0100
@@ -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 4a3e131f7498 -r cd6c6c685015 xen/include/xen/cpuidle.h
--- a/xen/include/xen/cpuidle.h Tue Apr 06 06:51:04 2010 +0100
+++ b/xen/include/xen/cpuidle.h Tue Apr 06 06:52:11 2010 +0100
@@ -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 */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|