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: Clean up APIC local timer handling.

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86: Clean up APIC local timer handling.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 03 Nov 2009 01:45:42 -0800
Delivery-date: Tue, 03 Nov 2009 01:46:15 -0800
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 1257240802 0
# Node ID 450f2ddd2dc6688bb3c5be3636944b33b3b1bb9c
# Parent  7d7631b57d1966ba2fe7ccf4333f87d8a77d2fb4
x86: Clean up APIC local timer handling.

1. Writing TMICT=0 disables the timer. Use this fact to simplify and
improve reprogram_timer(). In particular, we always write TMICT, and
write zero when we do not need a timer interrupt.

2. In HPET broadcast timer handler, set TMICT=0 when we mask the APIC
local timer. May as well do this early, before entering deep sleep.

3. In HVM-guest APIC emulation, disable the emulated local timer when
the guest sets TMICT=0. Previously we would issue an immediate
one-shot interrupt.

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/apic.c       |   62 ++++++++--------------------------------------
 xen/arch/x86/hpet.c       |    7 ++---
 xen/arch/x86/hvm/vlapic.c |   11 ++++++--
 3 files changed, 23 insertions(+), 57 deletions(-)

diff -r 7d7631b57d19 -r 450f2ddd2dc6 xen/arch/x86/apic.c
--- a/xen/arch/x86/apic.c       Tue Nov 03 08:40:40 2009 +0000
+++ b/xen/arch/x86/apic.c       Tue Nov 03 09:33:22 2009 +0000
@@ -1178,65 +1178,25 @@ void enable_APIC_timer(void)
 #undef APIC_DIVISOR
 
 /*
- * reprogram the APIC timer. Timeoutvalue is in ns from start of boot
- * returns 1 on success
- * returns 0 if the timeout value is too small or in the past.
+ * reprogram_timer: Reprogram the APIC timer.
+ * Timeout is a Xen system time (nanoseconds since boot); 0 disables the timer.
+ * Returns 1 on success; 0 if the timeout is too soon or is in the past.
  */
 int reprogram_timer(s_time_t timeout)
 {
-    s_time_t    now;
-    s_time_t    expire;
-    u64         apic_tmict;
-
-    /*
-     * If we don't have local APIC then we just poll the timer list off the
-     * PIT interrupt.
-     */
+    s_time_t expire;
+    u32 apic_tmict = 0;
+
+    /* No local APIC: timer list is polled via the PIT interrupt. */
     if ( !cpu_has_apic )
         return 1;
 
-    /*
-     * We use this value because we don't trust zero (we think it may just
-     * cause an immediate interrupt). At least this is guaranteed to hold it
-     * off for ages (esp. since the clock ticks on bus clock, not cpu clock!).
-     */
-    if ( timeout == 0 )
-    {
-        apic_tmict = 0xffffffff;
-        goto reprogram;
-    }
-
-    now = NOW();
-    expire = timeout - now; /* value from now */
-
-    if ( expire <= 0 )
-    {
-        Dprintk("APICT[%02d] Timeout in the past 0x%08X%08X > 0x%08X%08X\n", 
-                smp_processor_id(), (u32)(now>>32), 
-                (u32)now, (u32)(timeout>>32),(u32)timeout);
-        return 0;
-    }
-
-    /* conversion to bus units */
-    apic_tmict = (((u64)bus_scale) * expire)>>18;
-
-    if ( apic_tmict >= 0xffffffff )
-    {
-        Dprintk("APICT[%02d] Timeout value too large\n", smp_processor_id());
-        apic_tmict = 0xffffffff;
-    }
-
-    if ( apic_tmict == 0 )
-    {
-        Dprintk("APICT[%02d] timeout value too small\n", smp_processor_id());
-        return 0;
-    }
-
- reprogram:
-    /* Program the timer. */
+    if ( timeout && ((expire = timeout - NOW()) > 0) )
+        apic_tmict = min_t(u64, (bus_scale * expire) >> 18, UINT_MAX);
+
     apic_write(APIC_TMICT, (unsigned long)apic_tmict);
 
-    return 1;
+    return apic_tmict || !timeout;
 }
 
 fastcall void smp_apic_timer_interrupt(struct cpu_user_regs * regs)
diff -r 7d7631b57d19 -r 450f2ddd2dc6 xen/arch/x86/hpet.c
--- a/xen/arch/x86/hpet.c       Tue Nov 03 08:40:40 2009 +0000
+++ b/xen/arch/x86/hpet.c       Tue Nov 03 09:33:22 2009 +0000
@@ -642,6 +642,8 @@ void hpet_broadcast_enter(void)
     if ( hpet_attach_channel )
         hpet_attach_channel(cpu, ch);
 
+    /* Cancel any outstanding LAPIC timer event and disable interrupts. */
+    reprogram_timer(0);
     disable_APIC_timer();
 
     cpu_set(cpu, ch->cpumask);
@@ -664,11 +666,8 @@ void hpet_broadcast_exit(void)
 
     if ( cpu_test_and_clear(cpu, ch->cpumask) )
     {
-        /* Cancel any outstanding LAPIC event and re-enable interrupts. */
-        reprogram_timer(0);
+        /* Reprogram the deadline; trigger timer work now if it has passed. */
         enable_APIC_timer();
-        
-        /* Reprogram the deadline; trigger timer work now if it has passed. */
         if ( !reprogram_timer(per_cpu(timer_deadline, cpu)) )
             raise_softirq(TIMER_SOFTIRQ);
 
diff -r 7d7631b57d19 -r 450f2ddd2dc6 xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Tue Nov 03 08:40:40 2009 +0000
+++ b/xen/arch/x86/hvm/vlapic.c Tue Nov 03 09:33:22 2009 +0000
@@ -667,10 +667,17 @@ static int vlapic_write(struct vcpu *v, 
 
     case APIC_TMICT:
     {
-        uint64_t period = (uint64_t)APIC_BUS_CYCLE_NS *
-                            (uint32_t)val * vlapic->hw.timer_divisor;
+        uint64_t period;
 
         vlapic_set_reg(vlapic, APIC_TMICT, val);
+        if ( val == 0 )
+        {
+            destroy_periodic_time(&vlapic->pt);
+            break;
+        }
+
+        period = ((uint64_t)APIC_BUS_CYCLE_NS *
+                  (uint32_t)val * vlapic->hw.timer_divisor);
         create_periodic_time(current, &vlapic->pt, period, 
                              vlapic_lvtt_period(vlapic) ? period : 0,
                              vlapic->pt.irq, vlapic_pt_cb,

_______________________________________________
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: Clean up APIC local timer handling., Xen patchbot-unstable <=