From: Anthony L. <ali...@us...> - 2007-03-02 16:56:58
|
Leonard Norrgard wrote: > When a vcpu is migrated to another cpu, an unexpected difference in > current and previous cpu TSC values can cause a guest to wait > indefinitely. A known workaround has been to run kvm with taskset, > locking it to a single cpu. This patch modifies the guest viewable TSC > so that the TSC is guaranteed to be monotonically increasing. > > Thanks to Avi Kivity for help in pinpointing this issue and advice for > fixing it. > > Signed-off-by: Leonard Norrgård <vi...@re...> > Hi Leonard, Why not factor the common code into kvm_main.c and add a set_tsc_offset member to the kvm ops function table? Regards, Anthony Liguori > ------------------------------------------------------------------------ > > Index: linux-2.6/drivers/kvm/svm.c > =================================================================== > --- linux-2.6.orig/drivers/kvm/svm.c 2007-03-02 17:29:57.000000000 +0200 > +++ linux-2.6/drivers/kvm/svm.c 2007-03-02 17:31:15.000000000 +0200 > @@ -598,9 +598,45 @@ > kfree(vcpu->svm); > } > > +#ifdef CONFIG_SMP > +static void ipi_rdtscll(void *arg) > +{ > + u64 *tsc = arg; > + rdtscll(*tsc); > +} > +#endif > + > +/* > + * Switches to specified vcpu, until a matching vcpu_put(), but assumes > + * vcpu mutex is already taken. > + */ > static struct kvm_vcpu *svm_vcpu_load(struct kvm_vcpu *vcpu) > { > - get_cpu(); > + int cpu; > + > + cpu = get_cpu(); > + > +#ifdef CONFIG_SMP > + if (vcpu->cpu != cpu) { > + if (vcpu->cpu != -1) { > + u64 tsc_this, tsc_previous; > + > + /* Get TSC value for this and the previous cpu. */ > + rdtscll(tsc_this); > + smp_call_function_single(vcpu->cpu, ipi_rdtscll, > + &tsc_previous, 0, 1); > + > + /* > + * Make sure that the guest sees a monotonically > + * increasing TSC. > + */ > + vcpu->svm->vmcb->control.tsc_offset += > + tsc_previous - tsc_this; > + } > + } > +#endif > + > + vcpu->cpu = cpu; > return vcpu; > } > > Index: linux-2.6/drivers/kvm/vmx.c > =================================================================== > --- linux-2.6.orig/drivers/kvm/vmx.c 2007-03-02 17:30:01.000000000 +0200 > +++ linux-2.6/drivers/kvm/vmx.c 2007-03-02 17:30:17.000000000 +0200 > @@ -200,6 +200,14 @@ > #endif > } > > +#ifdef CONFIG_SMP > +static void ipi_rdtscll(void *arg) > +{ > + u64 *tsc = arg; > + rdtscll(*tsc); > +} > +#endif > + > /* > * Switches to specified vcpu, until a matching vcpu_put(), but assumes > * vcpu mutex is already taken. > @@ -230,6 +238,25 @@ > struct descriptor_table dt; > unsigned long sysenter_esp; > > +#ifdef CONFIG_SMP > + if (vcpu->cpu != -1) { > + u64 tsc_this, tsc_previous, guest_tsc_offset; > + > + /* Get TSC value for this and the previous cpu. */ > + rdtscll(tsc_this); > + smp_call_function_single(vcpu->cpu, ipi_rdtscll, > + &tsc_previous, 0, 1); > + > + /* > + * Make sure that the guest sees a monotonically > + * increasing TSC. > + */ > + guest_tsc_offset = vmcs_read64(TSC_OFFSET); > + vmcs_write64(TSC_OFFSET, guest_tsc_offset + > + tsc_previous - tsc_this); > + } > +#endif > + > vcpu->cpu = cpu; > /* > * Linux uses per-cpu TSS and GDT, so set these when switching > > ------------------------------------------------------------------------ > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get the chance to share your > opinions on IT & business topics through brief surveys-and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > ------------------------------------------------------------------------ > > _______________________________________________ > kvm-devel mailing list > kvm...@li... > https://lists.sourceforge.net/lists/listinfo/kvm-devel > |