[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] cpuidle: Enable hpet broadcast by default



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1239806845 -3600
# Node ID 573e6673e9e08328762bf58e7c02f8144c109ec2
# Parent  3e64dfebabd7340f5852ad112c858efcebc9cae5
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@xxxxxxxxx>
Signed-off-by: Tian Kevin <kevin.tian@xxxxxxxxx>
---
 xen/arch/x86/acpi/cpu_idle.c |   19 ++++++++++-
 xen/arch/x86/hpet.c          |   71 ++++++++++++++++++++++++++++++++++++++++---
 xen/arch/x86/traps.c         |    6 +++
 xen/include/asm-x86/hpet.h   |    1 
 4 files changed, 91 insertions(+), 6 deletions(-)

diff -r 3e64dfebabd7 -r 573e6673e9e0 xen/arch/x86/acpi/cpu_idle.c
--- a/xen/arch/x86/acpi/cpu_idle.c      Wed Apr 15 15:38:57 2009 +0100
+++ b/xen/arch/x86/acpi/cpu_idle.c      Wed Apr 15 15:47:25 2009 +0100
@@ -221,8 +221,8 @@ static void acpi_processor_idle(void)
         return;
     }
 
-    next_state = power ? cpuidle_current_governor->select(power) : -1;
-    if ( next_state > 0 )
+    if ( max_cstate > 0 && power && 
+         (next_state = cpuidle_current_governor->select(power)) > 0 )
     {
         cx = &power->states[next_state];
         if ( power->flags.bm_check && acpi_idle_bm_check()
@@ -853,3 +853,18 @@ int pmstat_reset_cx_stat(uint32_t cpuid)
     return 0;
 }
 
+void cpuidle_disable_deep_cstate(void)
+{
+    if ( max_cstate > 1 )
+    {
+        if ( local_apic_timer_c2_ok )
+            max_cstate = 2;
+        else
+            max_cstate = 1;
+    }
+
+    mb();
+
+    hpet_disable_legacy_broadcast();
+}
+
diff -r 3e64dfebabd7 -r 573e6673e9e0 xen/arch/x86/hpet.c
--- a/xen/arch/x86/hpet.c       Wed Apr 15 15:38:57 2009 +0100
+++ b/xen/arch/x86/hpet.c       Wed Apr 15 15:47:25 2009 +0100
@@ -22,8 +22,10 @@
 
 #define MAX_HPET_NUM 32
 
-#define HPET_EVT_USED_BIT   2
+#define HPET_EVT_USED_BIT    0
 #define HPET_EVT_USED       (1 << HPET_EVT_USED_BIT)
+#define HPET_EVT_DISABLE_BIT 1
+#define HPET_EVT_DISALBE    (1 << HPET_EVT_DISABLE_BIT)
 
 struct hpet_event_channel
 {
@@ -53,8 +55,11 @@ unsigned long hpet_address;
 
 void msi_compose_msg(struct pci_dev *pdev, int vector, struct msi_msg *msg);
 
-/* force_hpet_broadcast: if true, force using hpet_broadcast to fix lapic stop
-   issue for deep C state with pit disabled */
+/*
+ * force_hpet_broadcast: by default legacy hpet broadcast will be stopped
+ * if RTC interrupts are enabled. Enable this option if want to always enable
+ * legacy hpet broadcast for deep C state
+ */
 int force_hpet_broadcast;
 boolean_param("hpetbroadcast", force_hpet_broadcast);
 
@@ -114,6 +119,9 @@ static int reprogram_hpet_evt_channel(
     int64_t delta;
     int ret;
 
+    if ( ch->flags & HPET_EVT_DISALBE )
+        return 0;
+
     if ( unlikely(expire < 0) )
     {
         printk(KERN_DEBUG "reprogram: expire < 0\n");
@@ -482,6 +490,32 @@ static void hpet_detach_channel_share(in
 
 static void (*hpet_attach_channel)(int cpu, struct hpet_event_channel *ch);
 static void (*hpet_detach_channel)(int cpu);
+
+#include <asm/mc146818rtc.h>
+void cpuidle_disable_deep_cstate(void);
+
+void (*pv_rtc_handler)(unsigned int port, uint8_t value);
+
+static void handle_rtc_once(unsigned int port, uint8_t value)
+{
+    static int index;
+
+    if ( port == 0x70 )
+    {
+        index = value;
+        return;
+    }
+
+    if ( index != RTC_REG_B )
+        return;
+    
+    /* RTC Reg B, contain PIE/AIE/UIE */
+    if ( value & (RTC_PIE | RTC_AIE | RTC_UIE ) )
+    {
+        cpuidle_disable_deep_cstate();
+        pv_rtc_handler = NULL;
+    }
+}
 
 void hpet_broadcast_init(void)
 {
@@ -526,8 +560,11 @@ void hpet_broadcast_init(void)
         return;
     }
 
+    if ( legacy_hpet_event.flags & HPET_EVT_DISALBE )
+        return;
+
     hpet_id = hpet_read32(HPET_ID);
-    if ( !(hpet_id & HPET_ID_LEGSUP) || !force_hpet_broadcast )
+    if ( !(hpet_id & HPET_ID_LEGSUP) )
         return;
 
     /* Start HPET legacy interrupts */
@@ -555,6 +592,32 @@ void hpet_broadcast_init(void)
 
     for_each_cpu(i)
         per_cpu(cpu_bc_channel, i) = &legacy_hpet_event;
+
+    if ( !force_hpet_broadcast )
+        pv_rtc_handler = handle_rtc_once;
+}
+
+void hpet_disable_legacy_broadcast(void)
+{
+    u32 cfg;
+
+    spin_lock_irq(&legacy_hpet_event.lock);
+
+    legacy_hpet_event.flags |= HPET_EVT_DISALBE;
+
+    /* disable HPET T0 */
+    cfg = hpet_read32(HPET_T0_CFG);
+    cfg &= ~HPET_TN_ENABLE;
+    hpet_write32(cfg, HPET_T0_CFG);
+
+    /* Stop HPET legacy interrupts */
+    cfg = hpet_read32(HPET_CFG);
+    cfg &= ~HPET_CFG_LEGACY;
+    hpet_write32(cfg, HPET_CFG);
+
+    spin_unlock_irq(&legacy_hpet_event.lock);
+
+    smp_send_event_check_mask(cpu_online_map);
 }
 
 void hpet_broadcast_enter(void)
diff -r 3e64dfebabd7 -r 573e6673e9e0 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Wed Apr 15 15:38:57 2009 +0100
+++ b/xen/arch/x86/traps.c      Wed Apr 15 15:47:25 2009 +0100
@@ -1551,6 +1551,8 @@ static uint32_t guest_io_read(
     return data;
 }
 
+extern void (*pv_rtc_handler)(unsigned int port, uint8_t value);
+
 static void guest_io_write(
     unsigned int port, unsigned int bytes, uint32_t data,
     struct vcpu *v, struct cpu_user_regs *regs)
@@ -1565,6 +1567,8 @@ static void guest_io_write(
             outb((uint8_t)data, port);
             if ( pv_post_outb_hook )
                 pv_post_outb_hook(port, (uint8_t)data);
+            if ( ((port == 0x71) || (port == 0x70)) && pv_rtc_handler )
+                pv_rtc_handler(port, (uint8_t)data);
             break;
         case 2:
             outw((uint16_t)data, port);
@@ -1936,6 +1940,8 @@ static int emulate_privileged_op(struct 
             io_emul(regs);            
             if ( (op_bytes == 1) && pv_post_outb_hook )
                 pv_post_outb_hook(port, regs->eax);
+            if ( ((port == 0x71) || (port == 0x70)) && pv_rtc_handler )
+                pv_rtc_handler(port, regs->eax);
         }
         else
         {
diff -r 3e64dfebabd7 -r 573e6673e9e0 xen/include/asm-x86/hpet.h
--- a/xen/include/asm-x86/hpet.h        Wed Apr 15 15:38:57 2009 +0100
+++ b/xen/include/asm-x86/hpet.h        Wed Apr 15 15:47:25 2009 +0100
@@ -78,5 +78,6 @@ void hpet_broadcast_enter(void);
 void hpet_broadcast_enter(void);
 void hpet_broadcast_exit(void);
 int hpet_broadcast_is_available(void);
+void hpet_disable_legacy_broadcast(void);
 
 #endif /* __X86_HPET_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.