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

[Xen-changelog] [xen-unstable] [HVM] Sync per vcpu LAPIC timer with its TSC:



# 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


 


Rackspace

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