ia64/xen-unstable

changeset 17781:6b77c311fd3c

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@intel.com>
Signed-off-by: Tian Kevin <kevin.tian@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jun 03 09:35:02 2008 +0100 (2008-06-03)
parents 420db89188ca
children 5603534c62f9
files xen/arch/x86/acpi/cpu_idle.c
line diff
     1.1 --- a/xen/arch/x86/acpi/cpu_idle.c	Tue Jun 03 09:33:41 2008 +0100
     1.2 +++ b/xen/arch/x86/acpi/cpu_idle.c	Tue Jun 03 09:35:02 2008 +0100
     1.3 @@ -277,6 +277,13 @@ static void acpi_processor_idle(void)
     1.4       * for C2/C3 transitions.
     1.5       */
     1.6      local_irq_disable();
     1.7 +
     1.8 +    if ( softirq_pending(smp_processor_id()) )
     1.9 +    {
    1.10 +        local_irq_enable();
    1.11 +        return;
    1.12 +    }
    1.13 +
    1.14      cx = power->state;
    1.15      if ( !cx )
    1.16      {
    1.17 @@ -422,9 +429,6 @@ static void acpi_processor_idle(void)
    1.18              ACPI_FLUSH_CPU_CACHE();
    1.19          }
    1.20  
    1.21 -        /* Get start time (ticks) */
    1.22 -        t1 = inl(pmtmr_ioport);
    1.23 -
    1.24          /*
    1.25           * Before invoking C3, be aware that TSC/APIC timer may be 
    1.26           * stopped by H/W. Without carefully handling of TSC/APIC stop issues,
    1.27 @@ -434,16 +438,19 @@ static void acpi_processor_idle(void)
    1.28          cstate_save_tsc();
    1.29          /* preparing APIC stop */
    1.30          hpet_broadcast_enter();
    1.31 +
    1.32 +        /* Get start time (ticks) */
    1.33 +        t1 = inl(pmtmr_ioport);
    1.34          /* Invoke C3 */
    1.35          acpi_idle_do_entry(cx);
    1.36 +        /* Get end time (ticks) */
    1.37 +        t2 = inl(pmtmr_ioport);
    1.38  
    1.39          /* recovering APIC */
    1.40          hpet_broadcast_exit();
    1.41          /* recovering TSC */
    1.42          cstate_restore_tsc();
    1.43  
    1.44 -        /* Get end time (ticks) */
    1.45 -        t2 = inl(pmtmr_ioport);
    1.46          if ( power->flags.bm_check && power->flags.bm_control )
    1.47          {
    1.48              /* Enable bus master arbitration */
    1.49 @@ -451,10 +458,10 @@ static void acpi_processor_idle(void)
    1.50              acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
    1.51          }
    1.52  
    1.53 +        /* Re-enable interrupts */
    1.54 +        local_irq_enable();
    1.55          /* Compute time (ticks) that we were actually asleep */
    1.56          sleep_ticks = ticks_elapsed(t1, t2);
    1.57 -        /* Re-enable interrupts */
    1.58 -        local_irq_enable();
    1.59          /* Do not account our idle-switching overhead: */
    1.60          sleep_ticks -= cx->latency_ticks + C3_OVERHEAD;
    1.61