ia64/xen-unstable

changeset 19549:573e6673e9e0

cpuidle: Enable hpet broadcast by default

And stop legacy hpet broadcast and limit max C-state to shallower
state if RTC interrupts are enabled.

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 Wed Apr 15 15:47:25 2009 +0100 (2009-04-15)
parents 3e64dfebabd7
children b14dc215dd19
files xen/arch/x86/acpi/cpu_idle.c xen/arch/x86/hpet.c xen/arch/x86/traps.c xen/include/asm-x86/hpet.h
line diff
     1.1 --- a/xen/arch/x86/acpi/cpu_idle.c	Wed Apr 15 15:38:57 2009 +0100
     1.2 +++ b/xen/arch/x86/acpi/cpu_idle.c	Wed Apr 15 15:47:25 2009 +0100
     1.3 @@ -221,8 +221,8 @@ static void acpi_processor_idle(void)
     1.4          return;
     1.5      }
     1.6  
     1.7 -    next_state = power ? cpuidle_current_governor->select(power) : -1;
     1.8 -    if ( next_state > 0 )
     1.9 +    if ( max_cstate > 0 && power && 
    1.10 +         (next_state = cpuidle_current_governor->select(power)) > 0 )
    1.11      {
    1.12          cx = &power->states[next_state];
    1.13          if ( power->flags.bm_check && acpi_idle_bm_check()
    1.14 @@ -853,3 +853,18 @@ int pmstat_reset_cx_stat(uint32_t cpuid)
    1.15      return 0;
    1.16  }
    1.17  
    1.18 +void cpuidle_disable_deep_cstate(void)
    1.19 +{
    1.20 +    if ( max_cstate > 1 )
    1.21 +    {
    1.22 +        if ( local_apic_timer_c2_ok )
    1.23 +            max_cstate = 2;
    1.24 +        else
    1.25 +            max_cstate = 1;
    1.26 +    }
    1.27 +
    1.28 +    mb();
    1.29 +
    1.30 +    hpet_disable_legacy_broadcast();
    1.31 +}
    1.32 +
     2.1 --- a/xen/arch/x86/hpet.c	Wed Apr 15 15:38:57 2009 +0100
     2.2 +++ b/xen/arch/x86/hpet.c	Wed Apr 15 15:47:25 2009 +0100
     2.3 @@ -22,8 +22,10 @@
     2.4  
     2.5  #define MAX_HPET_NUM 32
     2.6  
     2.7 -#define HPET_EVT_USED_BIT   2
     2.8 +#define HPET_EVT_USED_BIT    0
     2.9  #define HPET_EVT_USED       (1 << HPET_EVT_USED_BIT)
    2.10 +#define HPET_EVT_DISABLE_BIT 1
    2.11 +#define HPET_EVT_DISALBE    (1 << HPET_EVT_DISABLE_BIT)
    2.12  
    2.13  struct hpet_event_channel
    2.14  {
    2.15 @@ -53,8 +55,11 @@ unsigned long hpet_address;
    2.16  
    2.17  void msi_compose_msg(struct pci_dev *pdev, int vector, struct msi_msg *msg);
    2.18  
    2.19 -/* force_hpet_broadcast: if true, force using hpet_broadcast to fix lapic stop
    2.20 -   issue for deep C state with pit disabled */
    2.21 +/*
    2.22 + * force_hpet_broadcast: by default legacy hpet broadcast will be stopped
    2.23 + * if RTC interrupts are enabled. Enable this option if want to always enable
    2.24 + * legacy hpet broadcast for deep C state
    2.25 + */
    2.26  int force_hpet_broadcast;
    2.27  boolean_param("hpetbroadcast", force_hpet_broadcast);
    2.28  
    2.29 @@ -114,6 +119,9 @@ static int reprogram_hpet_evt_channel(
    2.30      int64_t delta;
    2.31      int ret;
    2.32  
    2.33 +    if ( ch->flags & HPET_EVT_DISALBE )
    2.34 +        return 0;
    2.35 +
    2.36      if ( unlikely(expire < 0) )
    2.37      {
    2.38          printk(KERN_DEBUG "reprogram: expire < 0\n");
    2.39 @@ -483,6 +491,32 @@ static void hpet_detach_channel_share(in
    2.40  static void (*hpet_attach_channel)(int cpu, struct hpet_event_channel *ch);
    2.41  static void (*hpet_detach_channel)(int cpu);
    2.42  
    2.43 +#include <asm/mc146818rtc.h>
    2.44 +void cpuidle_disable_deep_cstate(void);
    2.45 +
    2.46 +void (*pv_rtc_handler)(unsigned int port, uint8_t value);
    2.47 +
    2.48 +static void handle_rtc_once(unsigned int port, uint8_t value)
    2.49 +{
    2.50 +    static int index;
    2.51 +
    2.52 +    if ( port == 0x70 )
    2.53 +    {
    2.54 +        index = value;
    2.55 +        return;
    2.56 +    }
    2.57 +
    2.58 +    if ( index != RTC_REG_B )
    2.59 +        return;
    2.60 +    
    2.61 +    /* RTC Reg B, contain PIE/AIE/UIE */
    2.62 +    if ( value & (RTC_PIE | RTC_AIE | RTC_UIE ) )
    2.63 +    {
    2.64 +        cpuidle_disable_deep_cstate();
    2.65 +        pv_rtc_handler = NULL;
    2.66 +    }
    2.67 +}
    2.68 +
    2.69  void hpet_broadcast_init(void)
    2.70  {
    2.71      u64 hpet_rate;
    2.72 @@ -526,8 +560,11 @@ void hpet_broadcast_init(void)
    2.73          return;
    2.74      }
    2.75  
    2.76 +    if ( legacy_hpet_event.flags & HPET_EVT_DISALBE )
    2.77 +        return;
    2.78 +
    2.79      hpet_id = hpet_read32(HPET_ID);
    2.80 -    if ( !(hpet_id & HPET_ID_LEGSUP) || !force_hpet_broadcast )
    2.81 +    if ( !(hpet_id & HPET_ID_LEGSUP) )
    2.82          return;
    2.83  
    2.84      /* Start HPET legacy interrupts */
    2.85 @@ -555,6 +592,32 @@ void hpet_broadcast_init(void)
    2.86  
    2.87      for_each_cpu(i)
    2.88          per_cpu(cpu_bc_channel, i) = &legacy_hpet_event;
    2.89 +
    2.90 +    if ( !force_hpet_broadcast )
    2.91 +        pv_rtc_handler = handle_rtc_once;
    2.92 +}
    2.93 +
    2.94 +void hpet_disable_legacy_broadcast(void)
    2.95 +{
    2.96 +    u32 cfg;
    2.97 +
    2.98 +    spin_lock_irq(&legacy_hpet_event.lock);
    2.99 +
   2.100 +    legacy_hpet_event.flags |= HPET_EVT_DISALBE;
   2.101 +
   2.102 +    /* disable HPET T0 */
   2.103 +    cfg = hpet_read32(HPET_T0_CFG);
   2.104 +    cfg &= ~HPET_TN_ENABLE;
   2.105 +    hpet_write32(cfg, HPET_T0_CFG);
   2.106 +
   2.107 +    /* Stop HPET legacy interrupts */
   2.108 +    cfg = hpet_read32(HPET_CFG);
   2.109 +    cfg &= ~HPET_CFG_LEGACY;
   2.110 +    hpet_write32(cfg, HPET_CFG);
   2.111 +
   2.112 +    spin_unlock_irq(&legacy_hpet_event.lock);
   2.113 +
   2.114 +    smp_send_event_check_mask(cpu_online_map);
   2.115  }
   2.116  
   2.117  void hpet_broadcast_enter(void)
     3.1 --- a/xen/arch/x86/traps.c	Wed Apr 15 15:38:57 2009 +0100
     3.2 +++ b/xen/arch/x86/traps.c	Wed Apr 15 15:47:25 2009 +0100
     3.3 @@ -1551,6 +1551,8 @@ static uint32_t guest_io_read(
     3.4      return data;
     3.5  }
     3.6  
     3.7 +extern void (*pv_rtc_handler)(unsigned int port, uint8_t value);
     3.8 +
     3.9  static void guest_io_write(
    3.10      unsigned int port, unsigned int bytes, uint32_t data,
    3.11      struct vcpu *v, struct cpu_user_regs *regs)
    3.12 @@ -1565,6 +1567,8 @@ static void guest_io_write(
    3.13              outb((uint8_t)data, port);
    3.14              if ( pv_post_outb_hook )
    3.15                  pv_post_outb_hook(port, (uint8_t)data);
    3.16 +            if ( ((port == 0x71) || (port == 0x70)) && pv_rtc_handler )
    3.17 +                pv_rtc_handler(port, (uint8_t)data);
    3.18              break;
    3.19          case 2:
    3.20              outw((uint16_t)data, port);
    3.21 @@ -1936,6 +1940,8 @@ static int emulate_privileged_op(struct 
    3.22              io_emul(regs);            
    3.23              if ( (op_bytes == 1) && pv_post_outb_hook )
    3.24                  pv_post_outb_hook(port, regs->eax);
    3.25 +            if ( ((port == 0x71) || (port == 0x70)) && pv_rtc_handler )
    3.26 +                pv_rtc_handler(port, regs->eax);
    3.27          }
    3.28          else
    3.29          {
     4.1 --- a/xen/include/asm-x86/hpet.h	Wed Apr 15 15:38:57 2009 +0100
     4.2 +++ b/xen/include/asm-x86/hpet.h	Wed Apr 15 15:47:25 2009 +0100
     4.3 @@ -78,5 +78,6 @@ void hpet_broadcast_init(void);
     4.4  void hpet_broadcast_enter(void);
     4.5  void hpet_broadcast_exit(void);
     4.6  int hpet_broadcast_is_available(void);
     4.7 +void hpet_disable_legacy_broadcast(void);
     4.8  
     4.9  #endif /* __X86_HPET_H__ */