KVM: x86: fix maintaining of kvm_clock stability on guest CPU hotplug
VCPU TSC synchronization is perfromed in kvm_write_tsc() when the TSC value being set is within 1 second from the expected, as obtained by extrapolating of the TSC in already synchronized VCPUs. This is naturally achieved on all VCPUs at VM start and resume; however on VCPU hotplug it is not: the newly added VCPU is created with TSC == 0 while others are well ahead. To compensate for that, consider host-initiated kvm_write_tsc() with TSC == 0 a special case requiring synchronization regardless of the current TSC on other VCPUs. Signed-off-by: Denis Plotnikov <dplotnikov@virtuozzo.com> Reviewed-by: Roman Kagan <rkagan@virtuozzo.com> Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
This commit is contained in:
parent
c5e8ec8e9b
commit
bd8fab39cd
|
@ -1454,16 +1454,25 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr)
|
||||||
elapsed = ns - kvm->arch.last_tsc_nsec;
|
elapsed = ns - kvm->arch.last_tsc_nsec;
|
||||||
|
|
||||||
if (vcpu->arch.virtual_tsc_khz) {
|
if (vcpu->arch.virtual_tsc_khz) {
|
||||||
u64 tsc_exp = kvm->arch.last_tsc_write +
|
if (data == 0 && msr->host_initiated) {
|
||||||
nsec_to_cycles(vcpu, elapsed);
|
/*
|
||||||
u64 tsc_hz = vcpu->arch.virtual_tsc_khz * 1000LL;
|
* detection of vcpu initialization -- need to sync
|
||||||
/*
|
* with other vCPUs. This particularly helps to keep
|
||||||
* Special case: TSC write with a small delta (1 second)
|
* kvm_clock stable after CPU hotplug
|
||||||
* of virtual cycle time against real time is
|
*/
|
||||||
* interpreted as an attempt to synchronize the CPU.
|
synchronizing = true;
|
||||||
*/
|
} else {
|
||||||
synchronizing = data < tsc_exp + tsc_hz &&
|
u64 tsc_exp = kvm->arch.last_tsc_write +
|
||||||
data + tsc_hz > tsc_exp;
|
nsec_to_cycles(vcpu, elapsed);
|
||||||
|
u64 tsc_hz = vcpu->arch.virtual_tsc_khz * 1000LL;
|
||||||
|
/*
|
||||||
|
* Special case: TSC write with a small delta (1 second)
|
||||||
|
* of virtual cycle time against real time is
|
||||||
|
* interpreted as an attempt to synchronize the CPU.
|
||||||
|
*/
|
||||||
|
synchronizing = data < tsc_exp + tsc_hz &&
|
||||||
|
data + tsc_hz > tsc_exp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue