OSDN Git Service

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[tomoyo/tomoyo-test1.git] / arch / x86 / kvm / lapic.c
index 776391c..b5cd846 100644 (file)
@@ -1522,11 +1522,23 @@ static bool set_target_expiration(struct kvm_lapic *apic)
 
 static void advance_periodic_target_expiration(struct kvm_lapic *apic)
 {
-       apic->lapic_timer.tscdeadline +=
-               nsec_to_cycles(apic->vcpu, apic->lapic_timer.period);
+       ktime_t now = ktime_get();
+       u64 tscl = rdtsc();
+       ktime_t delta;
+
+       /*
+        * Synchronize both deadlines to the same time source or
+        * differences in the periods (caused by differences in the
+        * underlying clocks or numerical approximation errors) will
+        * cause the two to drift apart over time as the errors
+        * accumulate.
+        */
        apic->lapic_timer.target_expiration =
                ktime_add_ns(apic->lapic_timer.target_expiration,
                                apic->lapic_timer.period);
+       delta = ktime_sub(apic->lapic_timer.target_expiration, now);
+       apic->lapic_timer.tscdeadline = kvm_read_l1_tsc(apic->vcpu, tscl) +
+               nsec_to_cycles(apic->vcpu, delta);
 }
 
 static void start_sw_period(struct kvm_lapic *apic)