@@ -345,6 +345,7 @@ struct kvm_vcpu_arch {
u64 last_tsc_write;
bool tsc_rebase;
bool tsc_trapping;
+ bool tsc_overrun;
bool nmi_pending;
bool nmi_injected;
@@ -1015,13 +1015,19 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
u64 tsc = compute_guest_tsc(v, kernel_ns);
if (tsc > tsc_timestamp)
kvm_x86_ops->adjust_tsc_offset(v, tsc-tsc_timestamp);
- }
- local_irq_restore(flags);
- if (catchup) {
- if (this_tsc_khz < v->kvm->arch.virtual_tsc_khz)
+ local_irq_restore(flags);
+
+ /* Now, see if we need to switch into trap mode */
+ if (vcpu->tsc_overrun && !vcpu->tsc_trapping)
+ kvm_x86_ops->set_tsc_trap(v, 1);
+
+ /* If we're falling behind and not trapping, re-trigger */
+ if (!vcpu->tsc_trapping &&
+ this_tsc_khz < v->kvm->arch.virtual_tsc_khz)
vcpu->tsc_rebase = 1;
return 0;
}
+ local_irq_restore(flags);
/*
* Time as measured by the TSC may go backwards when resetting the base
@@ -1098,6 +1104,17 @@ static void kvm_update_tsc_trapping(struct kvm *kvm)
int trap, i;
struct kvm_vcpu *vcpu;
+ /*
+ * Subtle point; we don't consider TSC rate here as part of
+ * the decision to trap or not. The reason for it is that
+ * TSC rate changes happen asynchronously, and are thus racy.
+ * The only safe place to check for this is above, in
+ * kvm_guest_time_update, where we've read the HZ value and
+ * the indication from the asynchronous notifier that TSC
+ * is in an overrun condition. Even that is racy, however that
+ * code is guaranteed to be called again if the CPU frequency
+ * changes yet another time before entering hardware virt.
+ */
trap = check_tsc_unstable() && atomic_read(&kvm->online_vcpus) > 1;
kvm_for_each_vcpu(i, vcpu, kvm)
kvm_x86_ops->set_tsc_trap(vcpu, trap && !vcpu->arch.time_page);
@@ -1977,8 +1994,11 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
kvm_put_guest_fpu(vcpu);
vcpu->arch.last_host_tsc = native_read_tsc();
- /* For unstable TSC, force compensation and catchup on next CPU */
- if (check_tsc_unstable()) {
+ /*
+ * For unstable TSC, force compensation and catchup on next CPU
+ * Don't need to do this if there is an overrun, as we'll trap.
+ */
+ if (check_tsc_unstable() && !vcpu->arch.tsc_overrun) {
vcpu->arch.tsc_rebase = 1;
kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
}
@@ -4342,6 +4362,8 @@ static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long va
kvm_for_each_vcpu(i, vcpu, kvm) {
if (vcpu->cpu != freq->cpu)
continue;
+ if (freq->new > kvm->arch.virtual_tsc_khz)
+ vcpu->arch.tsc_overrun = 1;
kvm_request_clock_update(vcpu);
if (vcpu->cpu != smp_processor_id())
send_ipi = 1;