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] [HVM] Sync per vcpu LAPIC timer with its

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [HVM] Sync per vcpu LAPIC timer with its TSC:
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 20 Dec 2006 17:15:12 -0800
Delivery-date: Wed, 20 Dec 2006 17:15:54 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
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/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/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 kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1166611293 0
# Node ID 516e4faac066437af4b41014da831d2ad8ae0493
# Parent  2a1edeedf28d9c72492255fba638fbca61da7ee3
[HVM] Sync per vcpu LAPIC timer with its TSC:
 - benefits LAPIC calibration
 - makes scheduling policy based on LAPIC more precise
 - makes LAPIC timer code becomes simpler and cleaner after using
   periodic time layer

Signed-off-by: Xiaowei Yang <xiaowei.yang@xxxxxxxxx>
---
 xen/arch/x86/hvm/hvm.c           |    3 
 xen/arch/x86/hvm/io.c            |   15 --
 xen/arch/x86/hvm/irq.c           |    6 -
 xen/arch/x86/hvm/svm/intr.c      |    2 
 xen/arch/x86/hvm/vlapic.c        |  199 +++++++++------------------------
 xen/arch/x86/hvm/vmx/intr.c      |    4 
 xen/arch/x86/hvm/vpt.c           |  231 +++++++++++++++++++++++++++++++++++++++
 xen/include/asm-x86/hvm/vlapic.h |   24 ++--
 xen/include/asm-x86/hvm/vpt.h    |    8 -
 9 files changed, 314 insertions(+), 178 deletions(-)

diff -r 2a1edeedf28d -r 516e4faac066 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Wed Dec 20 10:37:23 2006 +0000
+++ b/xen/arch/x86/hvm/hvm.c    Wed Dec 20 10:41:33 2006 +0000
@@ -87,7 +87,8 @@ void hvm_migrate_timers(struct vcpu *v)
     pit_migrate_timers(v);
     rtc_migrate_timers(v);
     pmtimer_migrate_timers(v);
-    migrate_timer(&vcpu_vlapic(v)->vlapic_timer, v->processor);
+    if ( vcpu_vlapic(v)->pt.enabled )
+        migrate_timer(&vcpu_vlapic(v)->pt.timer, v->processor);
 }
 
 void hvm_do_resume(struct vcpu *v)
diff -r 2a1edeedf28d -r 516e4faac066 xen/arch/x86/hvm/io.c
--- a/xen/arch/x86/hvm/io.c     Wed Dec 20 10:37:23 2006 +0000
+++ b/xen/arch/x86/hvm/io.c     Wed Dec 20 10:41:33 2006 +0000
@@ -689,21 +689,6 @@ static void hvm_mmio_assist(struct cpu_u
     }
 }
 
-void hvm_interrupt_post(struct vcpu *v, int vector, int type)
-{
-    pt_intr_post(v, vector, type);
-    
-    switch(type) {
-    case APIC_DM_EXTINT:
-        break;
-            
-    default:
-        vlapic_post_injection(v, vector, type);
-        break;
-    }
-}
-
-
 void hvm_io_assist(struct vcpu *v)
 {
     vcpu_iodata_t *vio;
diff -r 2a1edeedf28d -r 516e4faac066 xen/arch/x86/hvm/irq.c
--- a/xen/arch/x86/hvm/irq.c    Wed Dec 20 10:37:23 2006 +0000
+++ b/xen/arch/x86/hvm/irq.c    Wed Dec 20 10:41:33 2006 +0000
@@ -229,10 +229,9 @@ int cpu_has_pending_irq(struct vcpu *v)
 int cpu_has_pending_irq(struct vcpu *v)
 {
     struct hvm_domain *plat = &v->domain->arch.hvm_domain;
-    int dummy;
 
     /* APIC */
-    if ( cpu_get_apic_interrupt(v, &dummy) != -1 )
+    if ( vlapic_has_interrupt(v) != -1 )
         return 1;
 
     /* PIC */
@@ -267,6 +266,9 @@ int get_intr_vector(struct vcpu* v, int 
 
 int is_irq_masked(struct vcpu *v, int irq)
 {
+    if ( is_lvtt(v, irq) )
+        return !is_lvtt_enabled(v);
+
     if ( v->domain->arch.hvm_domain.irq.vpic[irq >> 3].imr & (1 << (irq & 7))
             && domain_vioapic(v->domain)->redirtbl[irq].fields.mask )
         return 1;
diff -r 2a1edeedf28d -r 516e4faac066 xen/arch/x86/hvm/svm/intr.c
--- a/xen/arch/x86/hvm/svm/intr.c       Wed Dec 20 10:37:23 2006 +0000
+++ b/xen/arch/x86/hvm/svm/intr.c       Wed Dec 20 10:41:33 2006 +0000
@@ -141,7 +141,7 @@ asmlinkage void svm_intr_assist(void)
         break;
     }
 
-    hvm_interrupt_post(v, intr_vector, intr_type);
+    pt_intr_post(v, intr_vector, intr_type);
 }
 
 /*
diff -r 2a1edeedf28d -r 516e4faac066 xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Wed Dec 20 10:37:23 2006 +0000
+++ b/xen/arch/x86/hvm/vlapic.c Wed Dec 20 10:41:33 2006 +0000
@@ -39,9 +39,8 @@
 #define VLAPIC_VERSION                  0x00050014
 #define VLAPIC_LVT_NUM                  6
 
-extern u32 get_apic_bus_cycle(void);
-
-#define APIC_BUS_CYCLE_NS (((s_time_t)get_apic_bus_cycle()) / 1000)
+/* vlapic's frequence is 100 MHz */
+#define APIC_BUS_CYCLE_NS               10
 
 #define LVT_MASK \
     APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK
@@ -122,11 +121,6 @@ static int vlapic_test_and_set_irr(int v
     return vlapic_test_and_set_vector(vector, vlapic->regs + APIC_IRR);
 }
 
-static void vlapic_set_irr(int vector, struct vlapic *vlapic)
-{
-    vlapic_set_vector(vector, vlapic->regs + APIC_IRR);
-}
-
 static void vlapic_clear_irr(int vector, struct vlapic *vlapic)
 {
     vlapic_clear_vector(vector, vlapic->regs + APIC_IRR);
@@ -433,46 +427,19 @@ static void vlapic_ipi(struct vlapic *vl
 
 static uint32_t vlapic_get_tmcct(struct vlapic *vlapic)
 {
-    uint32_t counter_passed;
-    s_time_t passed, now = NOW();
-    uint32_t tmcct = vlapic_get_reg(vlapic, APIC_TMCCT);
-
-    if ( unlikely(now <= vlapic->timer_last_update) )
-    {
-        passed = ~0x0LL - vlapic->timer_last_update + now;
-        HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "time elapsed.");
-    }
-    else
-        passed = now - vlapic->timer_last_update;
-
-    counter_passed = passed / (APIC_BUS_CYCLE_NS * vlapic->timer_divisor);
-
-    tmcct -= counter_passed;
-
-    if ( tmcct <= 0 )
-    {
-        if ( unlikely(!vlapic_lvtt_period(vlapic)) )
-        {
-            tmcct =  0;
-            /* FIXME: should we add interrupt here? */
-        }
-        else
-        {
-            do {
-                tmcct += vlapic_get_reg(vlapic, APIC_TMICT);
-            } while ( tmcct <= 0 );
-        }
-    }
-
-    vlapic->timer_last_update = now;
-    vlapic_set_reg(vlapic, APIC_TMCCT, tmcct);
+    struct vcpu *v = current;
+    uint32_t tmcct, tmict = vlapic_get_reg(vlapic, APIC_TMICT);
+    uint64_t counter_passed;
+
+    counter_passed = (hvm_get_guest_time(v) - vlapic->pt.last_plt_gtime) // TSC
+                     * 1000000000ULL / ticks_per_sec(v) // NS
+                     / APIC_BUS_CYCLE_NS / vlapic->timer_divisor;
+    tmcct = tmict - counter_passed;
 
     HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
-      "timer initial count 0x%x, timer current count 0x%x, "
-      "update 0x%016"PRIx64", now 0x%016"PRIx64", offset 0x%x.",
-      vlapic_get_reg(vlapic, APIC_TMICT),
-      vlapic_get_reg(vlapic, APIC_TMCCT),
-      vlapic->timer_last_update, now, counter_passed);
+                "timer initial count %d, timer current count %d, "
+                "offset %"PRId64".",
+                tmict, tmcct, counter_passed);
 
     return tmcct;
 }
@@ -486,6 +453,9 @@ static void vlapic_set_tdcr(struct vlapi
     /* Update the demangled timer_divisor. */
     val = ((val & 3) | ((val & 8) >> 1)) + 1;
     vlapic->timer_divisor = 1 << (val & 7);
+
+    HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
+                "vlapic_set_tdcr timer_divisor: %d.", vlapic->timer_divisor);
 }
 
 static void vlapic_read_aligned(struct vlapic *vlapic, unsigned int offset,
@@ -577,6 +547,7 @@ static void vlapic_write(struct vcpu *v,
      * According to the IA32 Manual, all accesses should be 32 bits.
      * Some OSes do 8- or 16-byte accesses, however.
      */
+    val &= 0xffffffff;
     if ( len != 4 )
     {
         unsigned int tmp;
@@ -671,6 +642,7 @@ static void vlapic_write(struct vcpu *v,
         break;
 
     case APIC_LVTT:         /* LVT Timer Reg */
+        vlapic->pt.irq = val & APIC_VECTOR_MASK;
     case APIC_LVTTHMR:      /* LVT Thermal Monitor */
     case APIC_LVTPC:        /* LVT Performance Counter */
     case APIC_LVT0:         /* LVT LINT0 Reg */
@@ -684,25 +656,16 @@ static void vlapic_write(struct vcpu *v,
 
     case APIC_TMICT:
     {
-        s_time_t now = NOW(), offset;
-
-        stop_timer(&vlapic->vlapic_timer);
+        uint64_t period = APIC_BUS_CYCLE_NS * (uint32_t)val * 
vlapic->timer_divisor;
 
         vlapic_set_reg(vlapic, APIC_TMICT, val);
-        vlapic_set_reg(vlapic, APIC_TMCCT, val);
-        vlapic->timer_last_update = now;
-
-        offset = APIC_BUS_CYCLE_NS * vlapic->timer_divisor * val;
-
-        set_timer(&vlapic->vlapic_timer, now + offset);
+        create_periodic_time(&vlapic->pt, period, vlapic->pt.irq,
+                             vlapic_lvtt_period(vlapic), NULL, vlapic);
 
         HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
-                    "bus cycle is %"PRId64"ns, now 0x%016"PRIx64", "
-                    "timer initial count 0x%x, offset 0x%016"PRIx64", "
-                    "expire @ 0x%016"PRIx64".",
-                    APIC_BUS_CYCLE_NS, now,
-                    vlapic_get_reg(vlapic, APIC_TMICT),
-                    offset, now + offset);
+                    "bus cycle is %uns, "
+                    "initial count %lu, period %"PRIu64"ns",
+                    APIC_BUS_CYCLE_NS, val, period);
     }
     break;
 
@@ -751,48 +714,6 @@ void vlapic_msr_set(struct vlapic *vlapi
 
     HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
                 "apic base msr is 0x%016"PRIx64".", vlapic->apic_base_msr);
-}
-
-void vlapic_timer_fn(void *data)
-{
-    struct vlapic *vlapic = data;
-    uint32_t timer_vector;
-    s_time_t now;
-
-    if ( unlikely(!vlapic_enabled(vlapic) ||
-                  !vlapic_lvt_enabled(vlapic, APIC_LVTT)) )
-        return;
-
-    timer_vector = vlapic_lvt_vector(vlapic, APIC_LVTT);
-    now = NOW();
-
-    vlapic->timer_last_update = now;
-
-    if ( vlapic_test_and_set_irr(timer_vector, vlapic) )
-        vlapic->timer_pending_count++;
-
-    if ( vlapic_lvtt_period(vlapic) )
-    {
-        s_time_t offset;
-        uint32_t tmict = vlapic_get_reg(vlapic, APIC_TMICT);
-
-        vlapic_set_reg(vlapic, APIC_TMCCT, tmict);
-
-        offset = APIC_BUS_CYCLE_NS * vlapic->timer_divisor * tmict;
-
-        set_timer(&vlapic->vlapic_timer, now + offset);
-    }
-    else
-        vlapic_set_reg(vlapic, APIC_TMCCT, 0);
-
-    vcpu_kick(vlapic_vcpu(vlapic));
-
-    HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
-                "now 0x%016"PRIx64", expire @ 0x%016"PRIx64", "
-                "timer initial count 0x%x, timer current count 0x%x.",
-                now, vlapic->vlapic_timer.expires,
-                vlapic_get_reg(vlapic, APIC_TMICT),
-                vlapic_get_reg(vlapic, APIC_TMCCT));
 }
 
 int vlapic_accept_pic_intr(struct vcpu *v)
@@ -809,7 +730,7 @@ int vlapic_accept_pic_intr(struct vcpu *
              vlapic_hw_disabled(vlapic)));
 }
 
-int cpu_get_apic_interrupt(struct vcpu *v, int *mode)
+int vlapic_has_interrupt(struct vcpu *v)
 {
     struct vlapic *vlapic = vcpu_vlapic(v);
     int highest_irr;
@@ -822,42 +743,22 @@ int cpu_get_apic_interrupt(struct vcpu *
          ((highest_irr & 0xF0) <= vlapic_get_ppr(vlapic)) )
         return -1;
 
+    return highest_irr;
+}
+
+int cpu_get_apic_interrupt(struct vcpu *v, int *mode)
+{
+    int vector = vlapic_has_interrupt(v);
+    struct vlapic *vlapic = vcpu_vlapic(v);
+
+    if ( vector == -1 )
+        return -1;
+ 
+    vlapic_set_vector(vector, vlapic->regs + APIC_ISR);
+    vlapic_clear_irr(vector, vlapic);
+
     *mode = APIC_DM_FIXED;
-    return highest_irr;
-}
-
-void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode)
-{
-    struct vlapic *vlapic = vcpu_vlapic(v);
-
-    switch ( deliver_mode )
-    {
-    case APIC_DM_FIXED:
-    case APIC_DM_LOWEST:
-        vlapic_set_vector(vector, vlapic->regs + APIC_ISR);
-        vlapic_clear_irr(vector, vlapic);
-        if ( (vector == vlapic_lvt_vector(vlapic, APIC_LVTT)) &&
-             (vlapic->timer_pending_count != 0) )
-        {
-            vlapic->timer_pending_count--;
-            vlapic_set_irr(vector, vlapic);
-        }
-        break;
-
-    case APIC_DM_REMRD:
-        gdprintk(XENLOG_WARNING, "Ignoring delivery mode 3.\n");
-        break;
-
-    case APIC_DM_SMI:
-    case APIC_DM_NMI:
-    case APIC_DM_INIT:
-    case APIC_DM_STARTUP:
-        break;
-
-    default:
-        gdprintk(XENLOG_WARNING, "Invalid delivery mode\n");
-        break;
-    }
+    return vector;
 }
 
 /* Reset the VLPAIC back to its power-on/reset state. */
@@ -918,8 +819,7 @@ int vlapic_init(struct vcpu *v)
     if ( v->vcpu_id == 0 )
         vlapic->apic_base_msr |= MSR_IA32_APICBASE_BSP;
 
-    init_timer(&vlapic->vlapic_timer,
-                  vlapic_timer_fn, vlapic, v->processor);
+    init_timer(&vlapic->pt.timer, pt_timer_fn, &vlapic->pt, v->processor);
 
     return 0;
 }
@@ -928,7 +828,22 @@ void vlapic_destroy(struct vcpu *v)
 {
     struct vlapic *vlapic = vcpu_vlapic(v);
 
-    kill_timer(&vlapic->vlapic_timer);
+    kill_timer(&vlapic->pt.timer);
     unmap_domain_page_global(vlapic->regs);
     free_domheap_page(vlapic->regs_page);
 }
+
+int is_lvtt(struct vcpu *v, int vector)
+{
+    return vcpu_vlapic(v)->pt.enabled &&
+           vector == vlapic_lvt_vector(vcpu_vlapic(v), APIC_LVTT);
+}
+
+int is_lvtt_enabled(struct vcpu *v)
+{
+    if ( unlikely(!vlapic_enabled(vcpu_vlapic(v))) ||
+            !vlapic_lvt_enabled(vcpu_vlapic(v), APIC_LVTT)) 
+        return 0;
+
+    return 1;
+}
diff -r 2a1edeedf28d -r 516e4faac066 xen/arch/x86/hvm/vmx/intr.c
--- a/xen/arch/x86/hvm/vmx/intr.c       Wed Dec 20 10:37:23 2006 +0000
+++ b/xen/arch/x86/hvm/vmx/intr.c       Wed Dec 20 10:41:33 2006 +0000
@@ -175,8 +175,8 @@ asmlinkage void vmx_intr_assist(void)
         BUG();
         break;
     }
-    
-    hvm_interrupt_post(v, highest_vector, intr_type);
+
+    pt_intr_post(v, highest_vector, intr_type);
 }
 
 /*
diff -r 2a1edeedf28d -r 516e4faac066 xen/arch/x86/hvm/vpt.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/hvm/vpt.c    Wed Dec 20 10:41:33 2006 +0000
@@ -0,0 +1,231 @@
+/*
+ * vpt.c: Virtual Platform Timer
+ *
+ * Copyright (c) 2006, Xiaowei Yang, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+#include <xen/time.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/vpt.h>
+#include <asm/event.h>
+
+static __inline__ void missed_ticks(struct periodic_time *pt)
+{
+    s_time_t missed_ticks;
+
+    missed_ticks = NOW() - pt->scheduled;
+    if ( missed_ticks > 0 ) 
+    {
+        missed_ticks = missed_ticks / (s_time_t) pt->period + 1;
+        if ( missed_ticks > 1000 )
+        {
+            /* TODO: Adjust guest time together */
+            pt->pending_intr_nr++;
+        }
+        else
+        {
+            pt->pending_intr_nr += missed_ticks;
+        }
+        pt->scheduled += missed_ticks * pt->period;
+    }
+}
+
+void pt_freeze_time(struct vcpu *v)
+{
+    struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+    struct list_head *list;
+    struct periodic_time *pt;
+
+    if ( test_bit(_VCPUF_blocked, &v->vcpu_flags) )
+        return;
+
+    v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
+
+    list_for_each( list, head )
+    {
+        pt = list_entry(list, struct periodic_time, list);
+        stop_timer(&pt->timer);
+    }
+}
+
+void pt_thaw_time(struct vcpu *v)
+{
+    struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+    struct list_head *list;
+    struct periodic_time *pt;
+
+    if ( v->arch.hvm_vcpu.guest_time )
+    {
+        hvm_set_guest_time(v, v->arch.hvm_vcpu.guest_time);
+        v->arch.hvm_vcpu.guest_time = 0;
+
+        list_for_each( list, head )
+        {
+            pt = list_entry(list, struct periodic_time, list);
+            missed_ticks(pt);
+            set_timer(&pt->timer, pt->scheduled);
+        }
+    }
+}
+
+/* Hook function for the platform periodic time */
+void pt_timer_fn(void *data)
+{
+    struct periodic_time *pt = data;
+
+    pt->pending_intr_nr++;
+    pt->scheduled += pt->period;
+
+    missed_ticks(pt);
+
+    if ( !pt->one_shot )
+        set_timer(&pt->timer, pt->scheduled);
+
+    vcpu_kick(pt->vcpu);
+}
+
+void pt_update_irq(struct vcpu *v)
+{
+    struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+    struct list_head *list;
+    struct periodic_time *pt;
+    uint64_t max_lag = -1ULL;
+    int irq = -1;
+
+    list_for_each( list, head )
+    {
+        pt = list_entry(list, struct periodic_time, list);
+        if ( !is_irq_masked(v, pt->irq) && pt->pending_intr_nr 
+                && pt->last_plt_gtime + pt->period < max_lag )
+        {
+            max_lag = pt->last_plt_gtime + pt->period;
+            irq = pt->irq;
+        }
+    }
+
+    if ( is_lvtt(v, irq) )
+        vlapic_set_irq(vcpu_vlapic(v), irq, 0);
+    else if ( irq >= 0 )
+    {
+        hvm_isa_irq_deassert(v->domain, irq);
+        hvm_isa_irq_assert(v->domain, irq);
+    }
+}
+
+struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type)
+{
+    struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+    struct list_head *list;
+    struct periodic_time *pt;
+    struct RTCState *rtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
+    int vec;
+
+    list_for_each( list, head )
+    {
+        pt = list_entry(list, struct periodic_time, list);
+        if ( !pt->pending_intr_nr )
+            continue;
+
+        if ( is_lvtt(v, pt->irq) )
+        {
+            if (pt->irq == vector)
+                return pt;
+            else
+                continue;
+        }
+
+        vec = get_intr_vector(v, pt->irq, type);
+
+        /* RTC irq need special care */
+        if ( vector != vec || (pt->irq == 8 && !is_rtc_periodic_irq(rtc)) )
+            continue;
+
+        return pt;
+    }
+
+    return NULL;
+}
+
+void pt_intr_post(struct vcpu *v, int vector, int type)
+{
+    struct periodic_time *pt = is_pt_irq(v, vector, type);
+
+    if (pt == NULL)
+        return;
+
+    pt->pending_intr_nr--;
+    pt->last_plt_gtime += pt->period_cycles;
+    hvm_set_guest_time(pt->vcpu, pt->last_plt_gtime);
+
+    if (pt->cb)
+        pt->cb(pt->vcpu, pt->priv);
+}
+
+/* If pt is enabled, discard pending intr */
+void pt_reset(struct vcpu *v)
+{
+    struct list_head *head = &v->arch.hvm_vcpu.tm_list;
+    struct list_head *list;
+    struct periodic_time *pt;
+
+    list_for_each( list, head )
+    {
+       pt = list_entry(list, struct periodic_time, list);
+       if ( pt->enabled )
+        {
+            pt->pending_intr_nr = 0;
+            pt->last_plt_gtime = hvm_get_guest_time(pt->vcpu);
+            pt->scheduled = NOW() + pt->period;
+            set_timer(&pt->timer, pt->scheduled);
+        }
+    }
+}
+
+void create_periodic_time(struct periodic_time *pt, uint64_t period,
+                          uint8_t irq, char one_shot, time_cb *cb, void *data)
+{
+    destroy_periodic_time(pt);
+
+    pt->enabled = 1;
+    if (period < 900000) /* < 0.9 ms */
+    {
+        printk("HVM_PlatformTime: program too small period %"PRIu64"\n", 
period);
+        period = 900000; /* force to 0.9ms */
+    }
+    pt->period = period;
+    pt->vcpu = current;
+    pt->last_plt_gtime = hvm_get_guest_time(pt->vcpu);
+    pt->irq = irq;
+    pt->period_cycles = (u64)period * cpu_khz / 1000000L;
+    pt->one_shot = one_shot;
+    pt->scheduled = NOW() + period;
+    pt->cb = cb;
+    pt->priv = data;
+
+    list_add(&pt->list, &current->arch.hvm_vcpu.tm_list);
+    set_timer(&pt->timer, pt->scheduled);
+}
+
+void destroy_periodic_time(struct periodic_time *pt)
+{
+    if ( pt->enabled )
+    {
+        pt->enabled = 0;
+        pt->pending_intr_nr = 0;
+        list_del(&pt->list);
+        stop_timer(&pt->timer);
+    }
+}
diff -r 2a1edeedf28d -r 516e4faac066 xen/include/asm-x86/hvm/vlapic.h
--- a/xen/include/asm-x86/hvm/vlapic.h  Wed Dec 20 10:37:23 2006 +0000
+++ b/xen/include/asm-x86/hvm/vlapic.h  Wed Dec 20 10:41:33 2006 +0000
@@ -23,6 +23,7 @@
 
 #include <asm/msr.h>
 #include <public/hvm/ioreq.h>
+#include <asm/hvm/vpt.h>
 
 #define MAX_VECTOR      256
 
@@ -49,14 +50,14 @@
 #define vlapic_enabled(vlapic)      (!vlapic_disabled(vlapic))
 
 struct vlapic {
-    uint64_t           apic_base_msr;
-    uint32_t           disabled; /* VLAPIC_xx_DISABLED */
-    uint32_t           timer_divisor;
-    struct timer       vlapic_timer;
-    int                timer_pending_count;
-    s_time_t           timer_last_update;
-    struct page_info   *regs_page;
-    void               *regs;
+    uint64_t             apic_base_msr;
+    uint32_t             disabled; /* VLAPIC_xx_DISABLED */
+    uint32_t             timer_divisor;
+    struct periodic_time pt;
+    int                  timer_pending_count;
+    s_time_t             timer_last_update;
+    struct page_info     *regs_page;
+    void                 *regs;
 };
 
 static inline uint32_t vlapic_get_reg(struct vlapic *vlapic, uint32_t reg)
@@ -70,13 +71,11 @@ static inline void vlapic_set_reg(
     *((uint32_t *)(vlapic->regs + reg)) = val;
 }
 
-
 int vlapic_set_irq(struct vlapic *vlapic, uint8_t vec, uint8_t trig);
-
-void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode);
 
 int vlapic_find_highest_irr(struct vlapic *vlapic);
 
+int vlapic_has_interrupt(struct vcpu *v);
 int cpu_get_apic_interrupt(struct vcpu *v, int *mode);
 
 int  vlapic_init(struct vcpu *v);
@@ -91,4 +90,7 @@ struct vlapic *apic_round_robin(
 
 int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda);
 
+int is_lvtt(struct vcpu *v, int vector);
+int is_lvtt_enabled(struct vcpu *v);
+
 #endif /* __ASM_X86_HVM_VLAPIC_H__ */
diff -r 2a1edeedf28d -r 516e4faac066 xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h     Wed Dec 20 10:37:23 2006 +0000
+++ b/xen/include/asm-x86/hvm/vpt.h     Wed Dec 20 10:41:33 2006 +0000
@@ -42,10 +42,10 @@ struct periodic_time {
     struct list_head list;
     char enabled;
     char one_shot;              /* one shot time */
-    int irq;
+    u8 irq;
     struct vcpu *vcpu;          /* vcpu timer interrupt delivers to */
     u32 pending_intr_nr;        /* the couner for pending timer interrupts */
-    u32 period;                 /* frequency in ns */
+    u64 period;                 /* frequency in ns */
     u64 period_cycles;          /* frequency in cpu cycles */
     s_time_t scheduled;         /* scheduled timer interrupt */
     u64 last_plt_gtime;         /* platform time when last IRQ is injected */
@@ -115,8 +115,8 @@ struct periodic_time *is_pt_irq(struct v
 struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type);
 void pt_intr_post(struct vcpu *v, int vector, int type);
 void pt_reset(struct vcpu *v);
-void create_periodic_time(struct periodic_time *pt, u32 period, char irq, 
-                          char one_shot, time_cb *cb, void *data);
+void create_periodic_time(struct periodic_time *pt, uint64_t period,
+                          uint8_t irq, char one_shot, time_cb *cb, void *data);
 void destroy_periodic_time(struct periodic_time *pt);
 
 int pv_pit_handler(int port, int data, int write);

_______________________________________________
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] [HVM] Sync per vcpu LAPIC timer with its TSC:, Xen patchbot-unstable <=