KVM: x86: Add clock sync request to hardware enable
authorZachary Amsden <zamsden@redhat.com>
Fri, 20 Aug 2010 08:07:28 +0000 (22:07 -1000)
committerAvi Kivity <avi@redhat.com>
Sun, 24 Oct 2010 08:51:24 +0000 (10:51 +0200)
If there are active VCPUs which are marked as belonging to
a particular hardware CPU, request a clock sync for them when
enabling hardware; the TSC could be desynchronized on a newly
arriving CPU, and we need to recompute guests system time
relative to boot after a suspend event.

This covers both cases.

Note that it is acceptable to take the spinlock, as either
no other tasks will be running and no locks held (BSP after
resume), or other tasks will be guaranteed to drop the lock
relatively quickly (AP on CPU_STARTING).

Noting we now get clock synchronization requests for VCPUs
which are starting up (or restarting), it is tempting to
attempt to remove the arch/x86/kvm/x86.c CPU hot-notifiers
at this time, however it is not correct to do so; they are
required for systems with non-constant TSC as the frequency
may not be known immediately after the processor has started
until the cpufreq driver has had a chance to run and query
the chipset.

Updated: implement better locking semantics for hardware_enable

Removed the hack of dropping and retaking the lock by adding the
semantic that we always hold kvm_lock when hardware_enable is
called.  The one place that doesn't need to worry about it is
resume, as resuming a frozen CPU, the spinlock won't be taken.

Signed-off-by: Zachary Amsden <zamsden@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
arch/x86/kvm/x86.c
virt/kvm/kvm_main.c

index 4ff0c271f1259c4fb2cd8e3ad269caea7cde52c6..d0764a258047df7410ac295c1bf27dd7b28ca9df 100644 (file)
@@ -5533,7 +5533,15 @@ int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu)
 
 int kvm_arch_hardware_enable(void *garbage)
 {
+       struct kvm *kvm;
+       struct kvm_vcpu *vcpu;
+       int i;
+
        kvm_shared_msr_cpu_online();
+       list_for_each_entry(kvm, &vm_list, vm_list)
+               kvm_for_each_vcpu(i, vcpu, kvm)
+                       if (vcpu->cpu == smp_processor_id())
+                               kvm_request_guest_time_update(vcpu);
        return kvm_x86_ops->hardware_enable(garbage);
 }
 
index 5186e728c53ed7e27ba6d32df31d37f7aa140ebc..da117a6b1e2e49862443bc91741c33746695f35e 100644 (file)
@@ -1961,7 +1961,9 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
        case CPU_STARTING:
                printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n",
                       cpu);
+               spin_lock(&kvm_lock);
                hardware_enable(NULL);
+               spin_unlock(&kvm_lock);
                break;
        }
        return NOTIFY_OK;
@@ -2168,8 +2170,10 @@ static int kvm_suspend(struct sys_device *dev, pm_message_t state)
 
 static int kvm_resume(struct sys_device *dev)
 {
-       if (kvm_usage_count)
+       if (kvm_usage_count) {
+               WARN_ON(spin_is_locked(&kvm_lock));
                hardware_enable(NULL);
+       }
        return 0;
 }