# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1212482102 -3600
# Node ID 6b77c311fd3c90db5a0cbbcfc44bf8d99b709b2b
# Parent 420db89188caafa5ee453407dce010a901abc2b8
x86: Enhance Cx stability by adding softirq check before entry cstate
Without checking softirq_pending before entry Cx state, softirq such
as SCHEDULE_SOFTIRQ and TIMER_SOFTIRQ can't be handled timely. It may
cause severe failures such as disk I/O failure.
This patch addresses the issue above, meanwhile move timing points
closer to cstate entry/exit point to make C3 residency more accurate,
and enable irq a little earlier.
Signed-off-by: Wei Gang <gang.wei@xxxxxxxxx>
Signed-off-by: Tian Kevin <kevin.tian@xxxxxxxxx>
---
xen/arch/x86/acpi/cpu_idle.c | 21 ++++++++++++++-------
1 files changed, 14 insertions(+), 7 deletions(-)
diff -r 420db89188ca -r 6b77c311fd3c xen/arch/x86/acpi/cpu_idle.c
--- a/xen/arch/x86/acpi/cpu_idle.c Tue Jun 03 09:33:41 2008 +0100
+++ b/xen/arch/x86/acpi/cpu_idle.c Tue Jun 03 09:35:02 2008 +0100
@@ -277,6 +277,13 @@ static void acpi_processor_idle(void)
* for C2/C3 transitions.
*/
local_irq_disable();
+
+ if ( softirq_pending(smp_processor_id()) )
+ {
+ local_irq_enable();
+ return;
+ }
+
cx = power->state;
if ( !cx )
{
@@ -422,9 +429,6 @@ static void acpi_processor_idle(void)
ACPI_FLUSH_CPU_CACHE();
}
- /* Get start time (ticks) */
- t1 = inl(pmtmr_ioport);
-
/*
* Before invoking C3, be aware that TSC/APIC timer may be
* stopped by H/W. Without carefully handling of TSC/APIC stop issues,
@@ -434,16 +438,19 @@ static void acpi_processor_idle(void)
cstate_save_tsc();
/* preparing APIC stop */
hpet_broadcast_enter();
+
+ /* Get start time (ticks) */
+ t1 = inl(pmtmr_ioport);
/* Invoke C3 */
acpi_idle_do_entry(cx);
+ /* Get end time (ticks) */
+ t2 = inl(pmtmr_ioport);
/* recovering APIC */
hpet_broadcast_exit();
/* recovering TSC */
cstate_restore_tsc();
- /* Get end time (ticks) */
- t2 = inl(pmtmr_ioport);
if ( power->flags.bm_check && power->flags.bm_control )
{
/* Enable bus master arbitration */
@@ -451,10 +458,10 @@ static void acpi_processor_idle(void)
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
}
+ /* Re-enable interrupts */
+ local_irq_enable();
/* Compute time (ticks) that we were actually asleep */
sleep_ticks = ticks_elapsed(t1, t2);
- /* Re-enable interrupts */
- local_irq_enable();
/* Do not account our idle-switching overhead: */
sleep_ticks -= cx->latency_ticks + C3_OVERHEAD;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|