# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1272973708 -3600
# Node ID 121275282095711a4dc2fa4f2e84e66209d7f1b0
# Parent 57d36cd633c3d38676cbd24af363faae118a1c8b
CPUIDLE: re-implement mwait wakeup process
It MWAITs on a completely new flag field, avoiding the IPI-avoidance
semantics of softirq_pending. It also does wakeup-waiting checks on
timer_deadline_start, that being the field that initiates wakeup via
the MONITORed memory region.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
Signed-off-by: Wei Gang <gang.wei@xxxxxxxxx>
---
xen/arch/x86/acpi/cpu_idle.c | 33 +++++++++++++++++++--------------
xen/include/asm-x86/hardirq.h | 1 +
xen/include/xen/irq_cpustat.h | 1 +
3 files changed, 21 insertions(+), 14 deletions(-)
diff -r 57d36cd633c3 -r 121275282095 xen/arch/x86/acpi/cpu_idle.c
--- a/xen/arch/x86/acpi/cpu_idle.c Tue May 04 12:46:56 2010 +0100
+++ b/xen/arch/x86/acpi/cpu_idle.c Tue May 04 12:48:28 2010 +0100
@@ -153,40 +153,45 @@ static void acpi_safe_halt(void)
/*
* 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
+ * by writing to specific memory address, instead of sending an IPI.
*/
static cpumask_t cpuidle_mwait_flags;
void cpuidle_wakeup_mwait(cpumask_t *mask)
{
cpumask_t target;
- int cpu;
+ unsigned int cpu;
cpus_and(target, *mask, cpuidle_mwait_flags);
- /* cpu is 'mwait'ing at softirq_pending,
- writing to it will wake up CPU */
+ /* CPU is MWAITing on the cpuidle_mwait_wakeup flag. */
for_each_cpu_mask(cpu, target)
- set_bit(TIMER_SOFTIRQ, &softirq_pending(cpu));
-
- cpus_andnot(*mask, *mask, cpuidle_mwait_flags);
+ mwait_wakeup(cpu) = 0;
+
+ cpus_andnot(*mask, *mask, target);
}
static void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
{
- int cpu = smp_processor_id();
-
- __monitor((void *)&softirq_pending(cpu), 0, 0);
-
+ unsigned int cpu = smp_processor_id();
+ s_time_t expires = per_cpu(timer_deadline_start, cpu);
+
+ __monitor((void *)&mwait_wakeup(cpu), 0, 0);
smp_mb();
- if (!softirq_pending(cpu))
+
+ /*
+ * Timer deadline passing is the event on which we will be woken via
+ * cpuidle_mwait_wakeup. So check it now that the location is armed.
+ */
+ if ( expires > NOW() || expires == 0 )
{
cpu_set(cpu, cpuidle_mwait_flags);
-
__mwait(eax, ecx);
-
cpu_clear(cpu, cpuidle_mwait_flags);
}
+
+ if ( expires <= NOW() && expires > 0 )
+ raise_softirq(TIMER_SOFTIRQ);
}
static void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx)
diff -r 57d36cd633c3 -r 121275282095 xen/include/asm-x86/hardirq.h
--- a/xen/include/asm-x86/hardirq.h Tue May 04 12:46:56 2010 +0100
+++ b/xen/include/asm-x86/hardirq.h Tue May 04 12:48:28 2010 +0100
@@ -8,6 +8,7 @@ typedef struct {
unsigned long __softirq_pending;
unsigned int __local_irq_count;
unsigned int __nmi_count;
+ bool_t __mwait_wakeup;
} __cacheline_aligned irq_cpustat_t;
#include <xen/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
diff -r 57d36cd633c3 -r 121275282095 xen/include/xen/irq_cpustat.h
--- a/xen/include/xen/irq_cpustat.h Tue May 04 12:46:56 2010 +0100
+++ b/xen/include/xen/irq_cpustat.h Tue May 04 12:48:28 2010 +0100
@@ -26,5 +26,6 @@ extern irq_cpustat_t irq_stat[];
#define softirq_pending(cpu) __IRQ_STAT((cpu), __softirq_pending)
#define local_irq_count(cpu) __IRQ_STAT((cpu), __local_irq_count)
#define nmi_count(cpu) __IRQ_STAT((cpu), __nmi_count)
+#define mwait_wakeup(cpu) __IRQ_STAT((cpu), __mwait_wakeup)
#endif /* __irq_cpustat_h */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|