Skip to content

Commit

Permalink
KVM: SVM: Ensure timestamp counter monotonicity
Browse files Browse the repository at this point in the history
When a vcpu is migrated from one cpu to another, its timestamp counter
may lose its monotonic property if the host has unsynced timestamp counters.
This can confuse the guest, sometimes to the point of refusing to boot.

As the rdtsc instruction is rather fast on AMD processors (7-10 cycles),
we can simply record the last host tsc when we drop the cpu, and adjust
the vcpu tsc offset when we detect that we've migrated to a different cpu.

Signed-off-by: Avi Kivity <avi@qumranet.com>
  • Loading branch information
Avi Kivity committed May 3, 2007
1 parent d28c6cf commit 0cc5064
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 4 deletions.
1 change: 1 addition & 0 deletions drivers/kvm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ struct kvm_vcpu {
struct mutex mutex;
int cpu;
int launched;
u64 host_tsc;
struct kvm_run *run;
int interrupt_window_open;
unsigned long irq_summary; /* bit vector: 1 per word in irq_pending */
Expand Down
21 changes: 17 additions & 4 deletions drivers/kvm/svm.c
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,6 @@ static void init_vmcb(struct vmcb *vmcb)
{
struct vmcb_control_area *control = &vmcb->control;
struct vmcb_save_area *save = &vmcb->save;
u64 tsc;

control->intercept_cr_read = INTERCEPT_CR0_MASK |
INTERCEPT_CR3_MASK |
Expand Down Expand Up @@ -517,8 +516,7 @@ static void init_vmcb(struct vmcb *vmcb)

control->iopm_base_pa = iopm_base;
control->msrpm_base_pa = msrpm_base;
rdtscll(tsc);
control->tsc_offset = -tsc;
control->tsc_offset = 0;
control->int_ctl = V_INTR_MASKING_MASK;

init_seg(&save->es);
Expand Down Expand Up @@ -606,11 +604,26 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu)

static void svm_vcpu_load(struct kvm_vcpu *vcpu)
{
get_cpu();
int cpu;

cpu = get_cpu();
if (unlikely(cpu != vcpu->cpu)) {
u64 tsc_this, delta;

/*
* Make sure that the guest sees a monotonically
* increasing TSC.
*/
rdtscll(tsc_this);
delta = vcpu->host_tsc - tsc_this;
vcpu->svm->vmcb->control.tsc_offset += delta;
vcpu->cpu = cpu;
}
}

static void svm_vcpu_put(struct kvm_vcpu *vcpu)
{
rdtscll(vcpu->host_tsc);
put_cpu();
}

Expand Down

0 comments on commit 0cc5064

Please sign in to comment.