|
@@ -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)
|