WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] x86: PIT broadcast to fix local APIC time

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86: PIT broadcast to fix local APIC timer stop issue for Deep C state
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 15 Jul 2008 09:30:12 -0700
Delivery-date: Tue, 15 Jul 2008 09:30:05 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1216028612 -3600
# Node ID 79517ed2a1081120ed4490f34453c6161dc4a38b
# Parent  39c2cab9e765ece9e7958ba08852f2340e7d537b
x86: PIT broadcast to fix local APIC timer stop issue for Deep C state

Local APIC timer may stop at deep C state (C3/C4...) entry. Initial
HPET broadcast working in legacy replacing mode, broke RTC intr, so
was bypassed. This patch add the logic that use platform timer (PIT)
to reenable local APIC timer at C state entry/exit.

Currently, only keep PIT enabled with 100Hz freq. The next step is
trying to dynamically enable/disable PIT while needed, and give it
lower freq.

Signed-off-by: Yu Ke <ke.yu@xxxxxxxxx>
Signed-off-by: Tian Kevin <kevin.tian@xxxxxxxxx>
Signed-off-by: Wei Gang <gang.wei@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/acpi/cpu_idle.c |   23 +++++++++++++++++----
 xen/arch/x86/setup.c         |    2 -
 xen/arch/x86/time.c          |   47 ++++++++++++++++++++++++++++++++++++++++++-
 xen/include/asm-x86/time.h   |    4 +++
 4 files changed, 70 insertions(+), 6 deletions(-)

diff -r 39c2cab9e765 -r 79517ed2a108 xen/arch/x86/acpi/cpu_idle.c
--- a/xen/arch/x86/acpi/cpu_idle.c      Mon Jul 14 10:12:07 2008 +0100
+++ b/xen/arch/x86/acpi/cpu_idle.c      Mon Jul 14 10:43:32 2008 +0100
@@ -56,6 +56,9 @@
 #define ACPI_PROCESSOR_MAX_C2_LATENCY   100
 #define ACPI_PROCESSOR_MAX_C3_LATENCY   1000
 
+static void (*lapic_timer_off)(void);
+static void (*lapic_timer_on)(void);
+
 extern u32 pmtmr_ioport;
 extern void (*pm_idle) (void);
 
@@ -437,7 +440,7 @@ static void acpi_processor_idle(void)
         /* preparing TSC stop */
         cstate_save_tsc();
         /* preparing APIC stop */
-        hpet_broadcast_enter();
+        lapic_timer_off();
 
         /* Get start time (ticks) */
         t1 = inl(pmtmr_ioport);
@@ -446,8 +449,6 @@ static void acpi_processor_idle(void)
         /* Get end time (ticks) */
         t2 = inl(pmtmr_ioport);
 
-        /* recovering APIC */
-        hpet_broadcast_exit();
         /* recovering TSC */
         cstate_restore_tsc();
 
@@ -460,6 +461,8 @@ static void acpi_processor_idle(void)
 
         /* Re-enable interrupts */
         local_irq_enable();
+        /* recovering APIC */
+        lapic_timer_on();
         /* Compute time (ticks) that we were actually asleep */
         sleep_ticks = ticks_elapsed(t1, t2);
         /* Do not account our idle-switching overhead: */
@@ -752,8 +755,20 @@ static int check_cx(struct acpi_processo
     if ( cx->type == ACPI_STATE_C3 )
     {
         /* We must be able to use HPET in place of LAPIC timers. */
-        if ( !hpet_broadcast_is_available() )
+        if ( hpet_broadcast_is_available() )
+        {
+            lapic_timer_off = hpet_broadcast_enter;
+            lapic_timer_on = hpet_broadcast_exit;
+        }
+        else if ( pit_broadcast_is_available() )
+        {
+            lapic_timer_off = pit_broadcast_enter;
+            lapic_timer_on = pit_broadcast_exit;
+        }
+        else
+        {
             return -EINVAL;
+        }
 
         /* All the logic here assumes flags.bm_check is same across all CPUs */
         if ( !bm_check_flag )
diff -r 39c2cab9e765 -r 79517ed2a108 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Mon Jul 14 10:12:07 2008 +0100
+++ b/xen/arch/x86/setup.c      Mon Jul 14 10:43:32 2008 +0100
@@ -96,7 +96,7 @@ boolean_param("noapic", skip_ioapic_setu
 
 /* **** Linux config option: propagated to domain0. */
 /* xen_cpuidle: xen control cstate. */
-static int xen_cpuidle;
+/*static*/ int xen_cpuidle;
 boolean_param("cpuidle", xen_cpuidle);
 
 int early_boot = 1;
diff -r 39c2cab9e765 -r 79517ed2a108 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Mon Jul 14 10:12:07 2008 +0100
+++ b/xen/arch/x86/time.c       Mon Jul 14 10:43:32 2008 +0100
@@ -147,6 +147,32 @@ static inline u64 scale_delta(u64 delta,
     return product;
 }
 
+/*
+ * cpu_mask that denotes the CPUs that needs timer interrupt coming in as
+ * IPIs in place of local APIC timers
+ */
+extern int xen_cpuidle;
+static cpumask_t pit_broadcast_mask;
+
+static void smp_send_timer_broadcast_ipi(void)
+{
+    int cpu = smp_processor_id();
+    cpumask_t mask;
+
+    cpus_and(mask, cpu_online_map, pit_broadcast_mask);
+
+    if ( cpu_isset(cpu, mask) )
+    {
+        cpu_clear(cpu, mask);
+        raise_softirq(TIMER_SOFTIRQ);
+    }
+
+    if ( !cpus_empty(mask) )
+    {
+        cpumask_raise_softirq(mask, TIMER_SOFTIRQ);
+    }
+}
+
 static void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
 {
     ASSERT(local_irq_is_enabled());
@@ -160,6 +186,9 @@ static void timer_interrupt(int irq, voi
     /* Rough hack to allow accurate timers to sort-of-work with no APIC. */
     if ( !cpu_has_apic )
         raise_softirq(TIMER_SOFTIRQ);
+
+    if ( xen_cpuidle )
+        smp_send_timer_broadcast_ipi();
 
     /* Emulate a 32-bit PIT counter. */
     if ( using_pit )
@@ -1006,9 +1035,10 @@ void __init early_time_init(void)
     setup_irq(0, &irq0);
 }
 
+/* keep pit enabled for pit_broadcast working while cpuidle enabled */
 static int disable_pit_irq(void)
 {
-    if ( !using_pit && cpu_has_apic )
+    if ( !using_pit && cpu_has_apic && !xen_cpuidle )
     {
         /* Disable PIT CH0 timer interrupt. */
         outb_p(0x30, PIT_MODE);
@@ -1025,6 +1055,21 @@ static int disable_pit_irq(void)
     return 0;
 }
 __initcall(disable_pit_irq);
+
+void pit_broadcast_enter(void)
+{
+    cpu_set(smp_processor_id(), pit_broadcast_mask);
+}
+
+void pit_broadcast_exit(void)
+{
+    cpu_clear(smp_processor_id(), pit_broadcast_mask);
+}
+
+int pit_broadcast_is_available(void)
+{
+    return xen_cpuidle;
+}
 
 void send_timer_event(struct vcpu *v)
 {
diff -r 39c2cab9e765 -r 79517ed2a108 xen/include/asm-x86/time.h
--- a/xen/include/asm-x86/time.h        Mon Jul 14 10:12:07 2008 +0100
+++ b/xen/include/asm-x86/time.h        Mon Jul 14 10:43:32 2008 +0100
@@ -34,4 +34,8 @@ struct tm;
 struct tm;
 struct tm wallclock_time(void);
 
+void pit_broadcast_enter(void);
+void pit_broadcast_exit(void);
+int pit_broadcast_is_available(void);
+
 #endif /* __X86_TIME_H__ */

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] x86: PIT broadcast to fix local APIC timer stop issue for Deep C state, Xen patchbot-unstable <=