        In order to calculate instant APIC counter register value,
        KVM refers host time stamp of previous APIC timer firing point
        (last_update) to get the time passed and thus calculate
        current APIC time counter register. Using NOW of
        the host hrtime firing time will have accumulated difference
        since the timer callback is executed with uncertainity delay,
        and it may introduce many drift as the time goes on.
    
        This patch fix this by adjust last_update by expected period.
    
        Signed-off-by: Yaozu (Eddie) Dong <Eddie.Dong@intel.com>
diff --git a/drivers/kvm/irq.c b/drivers/kvm/irq.c
diff --git a/drivers/kvm/irq.h b/drivers/kvm/irq.h
index 44e1fa4..ed6d20a 100644
--- a/drivers/kvm/irq.h
+++ b/drivers/kvm/irq.h
@@ -111,6 +111,7 @@ struct kvm_lapic {
 	struct kvm_io_device dev;
 	struct {
 		unsigned long pending;
+		s64 period;	/* unit: ns */
 		u32 divide_count;
 		ktime_t last_update;
 		struct hrtimer dev;
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
diff --git a/drivers/kvm/lapic.c b/drivers/kvm/lapic.c
index 1430667..09aadcb 100644
--- a/drivers/kvm/lapic.c
+++ b/drivers/kvm/lapic.c
@@ -350,18 +350,6 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
 	return result;
 }
 
-static inline int apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
-				  int vector, int level, int trig_mode)
-{
-	int result = 0;
-
-	spin_lock_bh(&apic->lock);
-	result = __apic_accept_irq(apic, delivery_mode,
-				   vector, level, trig_mode);
-	spin_unlock_bh(&apic->lock);
-	return result;
-}
-
 struct kvm_lapic *kvm_apic_round_robin(struct kvm *kvm, u8 vector,
 				       unsigned long bitmap)
 {
@@ -625,27 +613,28 @@ static void apic_mmio_write(struct kvm_io_device *this,
 	case APIC_TMICT:
 		{
 			ktime_t now = apic->timer.dev.base->get_time();
-			u32 offset;
 
 			apic_set_reg(apic, APIC_TMICT, val);
 			apic->timer.last_update = now;
-			offset =
+			apic->timer.period =
 			    APIC_BUS_CYCLE_NS * apic->timer.divide_count * val;
 
 			/* Make sure the lock ordering is coherent */
 			spin_unlock_bh(&apic->lock);
 			hrtimer_cancel(&apic->timer.dev);
 			hrtimer_start(&apic->timer.dev,
-				      ktime_add_ns(now, offset),
+				      ktime_add_ns(now, apic->timer.period),
 				      HRTIMER_MODE_ABS);
 
 			apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
 				   PRIx64 ", "
-				   "timer initial count 0x%x, offset 0x%x, "
+				   "timer initial count 0x%x, period %lldns, "
 				   "expire @ 0x%016" PRIx64 ".\n", __FUNCTION__,
 				   APIC_BUS_CYCLE_NS, ktime_to_ns(now),
-				   apic_get_reg(apic, APIC_TMICT), offset,
-				   ktime_to_ns(ktime_add_ns(now, offset)));
+				   apic_get_reg(apic, APIC_TMICT),
+				   apic->timer.period,
+				   ktime_to_ns(ktime_add_ns(now,
+						apic->timer.period)));
 		}
 		return;
 
@@ -760,7 +749,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
 
 	/* with FSB delivery interrupt, we can restart APIC functionality */
 	apic_debug("apic base msr is 0x%016" PRIx64 ", and base address is "
-		   "0x%lx.\n", apic->apic_base, apic->base_address);
+		   "0x%lx.\n", apic->vcpu->apic_base, apic->base_address);
 
 	spin_unlock_bh(&apic->lock);
 }
@@ -859,7 +848,6 @@ EXPORT_SYMBOL_GPL(kvm_lapic_get_regs);
 static int __apic_timer_fn(struct kvm_lapic *apic)
 {
 	u32 vector;
-	ktime_t now;
 	int result = 0;
 
 	if (unlikely(!apic_enabled(apic) ||
@@ -870,8 +858,7 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
 	}
 
 	vector = apic_lvt_vector(apic, APIC_LVTT);
-	now = apic->timer.dev.base->get_time();
-	apic->timer.last_update = now;
+	apic->timer.last_update = apic->timer.dev.expires;
 	apic->timer.pending++;
 	__apic_accept_irq(apic, APIC_DM_FIXED, vector, 1, 0);
 
@@ -882,7 +869,9 @@ static int __apic_timer_fn(struct kvm_lapic *apic)
 		offset = APIC_BUS_CYCLE_NS * apic->timer.divide_count * tmict;
 
 		result = 1;
-		apic->timer.dev.expires = ktime_add_ns(now, offset);
+		apic->timer.dev.expires = ktime_add_ns(
+					apic->timer.dev.expires,
+					apic->timer.period);
 	}
 
 	return result;
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
