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

[Xen-changelog] This patch fix HVM/VMX time resolution issue that cause IA32E complain



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 56a775219c88491d46395e8c34d72241c9a27253
# Parent  760f9149dbaa8e07445f1e1227380a92b4205a3a
This patch fix HVM/VMX time resolution issue that cause IA32E complain
"loss tick" occationally and APIC time calibration issue.

Signed-off-by: Xiaowei Yang <xiaowei.yang@xxxxxxxxx>
Signed-off-by: Eddie Dong <eddie.dong@xxxxxxxxx>

diff -r 760f9149dbaa -r 56a775219c88 xen/arch/x86/hvm/intercept.c
--- a/xen/arch/x86/hvm/intercept.c      Sun Mar 19 16:10:20 2006
+++ b/xen/arch/x86/hvm/intercept.c      Sun Mar 19 17:52:20 2006
@@ -338,10 +338,10 @@
 
 static __inline__ void missed_ticks(struct hvm_virpit*vpit)
 {
-    int        missed_ticks;
+    int missed_ticks;
 
     missed_ticks = (NOW() - vpit->scheduled)/(s_time_t) vpit->period;
-    if ( missed_ticks > 0 ) {
+    if ( missed_ticks++ >= 0 ) {
         vpit->pending_intr_nr += missed_ticks;
         vpit->scheduled += missed_ticks * vpit->period;
     }
@@ -355,22 +355,16 @@
 
     /* pick up missed timer tick */
     missed_ticks(vpit);
-
-    vpit->pending_intr_nr++;
     if ( test_bit(_VCPUF_running, &v->vcpu_flags) ) {
-        vpit->scheduled += vpit->period;
         set_timer(&vpit->pit_timer, vpit->scheduled);
     }
 }
 
+/* pick up missed timer ticks at deactive time */
 void pickup_deactive_ticks(struct hvm_virpit *vpit)
 {
-
     if ( !active_timer(&(vpit->pit_timer)) ) {
-        /* pick up missed timer tick */
         missed_ticks(vpit);
-    
-        vpit->scheduled += vpit->period;
         set_timer(&vpit->pit_timer, vpit->scheduled);
     }
 }
diff -r 760f9149dbaa -r 56a775219c88 xen/arch/x86/hvm/vmx/io.c
--- a/xen/arch/x86/hvm/vmx/io.c Sun Mar 19 16:10:20 2006
+++ b/xen/arch/x86/hvm/vmx/io.c Sun Mar 19 17:52:20 2006
@@ -40,20 +40,33 @@
 
 #define BSP_CPU(v)    (!(v->vcpu_id))
 
-void vmx_set_tsc_shift(struct vcpu *v, struct hvm_virpit *vpit)
-{
-    u64   drift;
-
-    if ( vpit->first_injected )
-        drift = vpit->period_cycles * vpit->pending_intr_nr;
-    else 
-        drift = 0;
-    vpit->shift = v->arch.hvm_vmx.tsc_offset - drift;
-    __vmwrite(TSC_OFFSET, vpit->shift);
-
+static inline 
+void __set_tsc_offset(u64  offset)
+{
+    __vmwrite(TSC_OFFSET, offset);
 #if defined (__i386__)
-    __vmwrite(TSC_OFFSET_HIGH, ((vpit->shift)>> 32));
+    __vmwrite(TSC_OFFSET_HIGH, offset >> 32);
 #endif
+}
+
+u64 get_guest_time(struct vcpu *v)
+{
+    struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
+    u64    host_tsc;
+    
+    rdtscll(host_tsc);
+    return host_tsc + vpit->cache_tsc_offset;
+}
+
+void set_guest_time(struct vcpu *v, u64 gtime)
+{
+    struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
+    u64    host_tsc;
+   
+    rdtscll(host_tsc);
+    
+    vpit->cache_tsc_offset = gtime - host_tsc;
+    __set_tsc_offset(vpit->cache_tsc_offset);
 }
 
 static inline void
@@ -64,6 +77,7 @@
     if ( is_pit_irq(v, vector, type) ) {
         if ( !vpit->first_injected ) {
             vpit->pending_intr_nr = 0;
+            vpit->last_pit_gtime = get_guest_time(v);
             vpit->scheduled = NOW() + vpit->period;
             set_timer(&vpit->pit_timer, vpit->scheduled);
             vpit->first_injected = 1;
@@ -71,7 +85,9 @@
             vpit->pending_intr_nr--;
         }
         vpit->inject_point = NOW();
-        vmx_set_tsc_shift (v, vpit);
+
+        vpit->last_pit_gtime += vpit->period;
+        set_guest_time(v, vpit->last_pit_gtime);
     }
 
     switch(type)
@@ -189,14 +205,15 @@
 
     vmx_stts();
 
+    /* pick up the elapsed PIT ticks and re-enable pit_timer */
+    if ( vpit->first_injected) {
+        set_guest_time(v, v->domain->arch.hvm_domain.guest_time);
+        pickup_deactive_ticks(vpit);
+    }
+
     if ( test_bit(iopacket_port(v), &d->shared_info->evtchn_pending[0]) ||
          test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags) )
         hvm_wait_io();
-
-    /* pick up the elapsed PIT ticks and re-enable pit_timer */
-    if ( vpit->first_injected )
-        pickup_deactive_ticks(vpit);
-    vmx_set_tsc_shift(v, vpit);
 
     /* We can't resume the guest if we're waiting on I/O */
     ASSERT(!test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags));
diff -r 760f9149dbaa -r 56a775219c88 xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Sun Mar 19 16:10:20 2006
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Sun Mar 19 17:52:20 2006
@@ -195,7 +195,6 @@
 /* Update CR3, GDT, LDT, TR */
     unsigned int  error = 0;
     unsigned long cr0, cr4;
-    u64     host_tsc;
 
     if (v->vcpu_id == 0)
         hvm_setup_platform(v->domain);
@@ -250,9 +249,7 @@
     v->arch.hvm_vmx.launch_cpu = smp_processor_id();
 
     /* init guest tsc to start from 0 */
-    rdtscll(host_tsc);
-    v->arch.hvm_vmx.tsc_offset = 0 - host_tsc;
-    vmx_set_tsc_shift(v, &v->domain->arch.hvm_domain.vpit);
+    set_guest_time(v, 0);
 }
 
 /*
diff -r 760f9149dbaa -r 56a775219c88 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Sun Mar 19 16:10:20 2006
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Sun Mar 19 17:52:20 2006
@@ -354,8 +354,18 @@
 
 #endif /* __i386__ */
 
+static void vmx_freeze_time(struct vcpu *v)
+{
+    struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
+    
+    v->domain->arch.hvm_domain.guest_time = get_guest_time(v);
+    if ( vpit->first_injected )
+        stop_timer(&(vpit->pit_timer));
+}
+
 static void vmx_ctxt_switch_from(struct vcpu *v)
 {
+    vmx_freeze_time(v);
     vmx_save_segments(v);
     vmx_load_msrs();
 }
@@ -1707,7 +1717,7 @@
 
         rdtscll(msr_content);
         vpit = &(v->domain->arch.hvm_domain.vpit);
-        msr_content += vpit->shift;
+        msr_content += vpit->cache_tsc_offset;
         break;
     }
     case MSR_IA32_SYSENTER_CS:
@@ -1751,22 +1761,8 @@
 
     switch (regs->ecx) {
     case MSR_IA32_TIME_STAMP_COUNTER:
-    {
-        struct hvm_virpit *vpit;
-        u64 host_tsc, drift;
-
-        rdtscll(host_tsc);
-        vpit = &(v->domain->arch.hvm_domain.vpit);
-        drift = v->arch.hvm_vmx.tsc_offset - vpit->shift;
-        vpit->shift = msr_content - host_tsc;
-       v->arch.hvm_vmx.tsc_offset = vpit->shift + drift;
-        __vmwrite(TSC_OFFSET, vpit->shift);
-
-#if defined (__i386__)
-        __vmwrite(TSC_OFFSET_HIGH, ((vpit->shift)>>32));
-#endif
-        break;
-    }
+        set_guest_time(v, msr_content);
+        break;
     case MSR_IA32_SYSENTER_CS:
         __vmwrite(GUEST_SYSENTER_CS, msr_content);
         break;
diff -r 760f9149dbaa -r 56a775219c88 xen/include/asm-x86/hvm/domain.h
--- a/xen/include/asm-x86/hvm/domain.h  Sun Mar 19 16:10:20 2006
+++ b/xen/include/asm-x86/hvm/domain.h  Sun Mar 19 17:52:20 2006
@@ -37,6 +37,7 @@
     unsigned int           pae_enabled;
 
     struct hvm_virpit      vpit;
+    u64                    guest_time;
     struct hvm_virpic      vpic;
     struct hvm_vioapic     vioapic;
     struct hvm_io_handler  io_handler;
diff -r 760f9149dbaa -r 56a775219c88 xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h        Sun Mar 19 16:10:20 2006
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h        Sun Mar 19 17:52:20 2006
@@ -77,7 +77,6 @@
     unsigned long           cpu_based_exec_control;
     struct vmx_msr_state    msr_content;
     void                    *io_bitmap_a, *io_bitmap_b;
-    u64                     tsc_offset;
     struct timer            hlt_timer;  /* hlt ins emulation wakeup timer */
 };
 
diff -r 760f9149dbaa -r 56a775219c88 xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Sun Mar 19 16:10:20 2006
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Sun Mar 19 17:52:20 2006
@@ -30,10 +30,11 @@
 extern void vmx_asm_do_resume(void);
 extern void vmx_asm_do_launch(void);
 extern void vmx_intr_assist(void);
-extern void vmx_set_tsc_shift(struct vcpu *, struct hvm_virpit *);
 extern void vmx_migrate_timers(struct vcpu *v);
 extern void arch_vmx_do_launch(struct vcpu *);
 extern void arch_vmx_do_resume(struct vcpu *);
+extern void set_guest_time(struct vcpu *v, u64 gtime);
+extern u64  get_guest_time(struct vcpu *v);
 
 extern unsigned int cpu_rev;
 
diff -r 760f9149dbaa -r 56a775219c88 xen/include/asm-x86/hvm/vpit.h
--- a/xen/include/asm-x86/hvm/vpit.h    Sun Mar 19 16:10:20 2006
+++ b/xen/include/asm-x86/hvm/vpit.h    Sun Mar 19 17:52:20 2006
@@ -38,7 +38,6 @@
 struct hvm_virpit {
     /* for simulation of counter 0 in mode 2 */
     u64 period_cycles;          /* pit frequency in cpu cycles */
-    u64 shift;                  /* save the value of offset - drift */
     s_time_t inject_point;      /* the time inject virt intr */
     s_time_t scheduled;         /* scheduled timer interrupt */
     struct timer pit_timer;     /* periodic timer for mode 2*/
@@ -46,6 +45,8 @@
     unsigned int pending_intr_nr; /* the couner for pending timer interrupts */
     u32 period;                 /* pit frequency in ns */
     int first_injected;         /* flag to prevent shadow window */
+    s64 cache_tsc_offset;       /* cache of VMCS TSC_OFFSET offset */
+    u64 last_pit_gtime;         /* guest time when last pit is injected */
 
     /* virtual PIT state for handle related I/O */
     int read_state;

_______________________________________________
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®.