Message ID | 20130312021024.GA21328@amt.cnet (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Mon, Mar 11, 2013 at 11:10:24PM -0300, Marcelo Tosatti wrote: > > If the host TSC calibration fails, tsc_khz is zero (see tsc_init.c). > Handle such case properly in KVM (instead of dividing by zero). > > https://bugzilla.redhat.com/show_bug.cgi?id=859282 > > Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> > Fixed small space/tab problem and applied. Thanks. > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 35b4912..19741b9 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -1079,6 +1079,10 @@ static void kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz) > u32 thresh_lo, thresh_hi; > int use_scaling = 0; > > + /* tsc_khz can be zero if TSC calibration fails */ > + if (this_tsc_khz == 0) > + return; > + > /* Compute a scale to convert nanoseconds in TSC cycles */ > kvm_get_time_scale(this_tsc_khz, NSEC_PER_SEC / 1000, > &vcpu->arch.virtual_tsc_shift, > @@ -1156,20 +1160,23 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr) > ns = get_kernel_ns(); > elapsed = ns - kvm->arch.last_tsc_nsec; > > - /* n.b - signed multiplication and division required */ > - usdiff = data - kvm->arch.last_tsc_write; > + if (vcpu->arch.virtual_tsc_khz) { > + /* n.b - signed multiplication and division required */ > + usdiff = data - kvm->arch.last_tsc_write; > #ifdef CONFIG_X86_64 > - usdiff = (usdiff * 1000) / vcpu->arch.virtual_tsc_khz; > + usdiff = (usdiff * 1000) / vcpu->arch.virtual_tsc_khz; > #else > - /* do_div() only does unsigned */ > - asm("idivl %2; xor %%edx, %%edx" > - : "=A"(usdiff) > - : "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz)); > + /* do_div() only does unsigned */ > + asm("idivl %2; xor %%edx, %%edx" > + : "=A"(usdiff) > + : "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz)); > #endif > - do_div(elapsed, 1000); > - usdiff -= elapsed; > - if (usdiff < 0) > - usdiff = -usdiff; > + do_div(elapsed, 1000); > + usdiff -= elapsed; > + if (usdiff < 0) > + usdiff = -usdiff; > + } else > + usdiff = USEC_PER_SEC; /* disable TSC match window below */ > > /* > * Special case: TSC write with a small delta (1 second) of virtual -- Gleb. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 35b4912..19741b9 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1079,6 +1079,10 @@ static void kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz) u32 thresh_lo, thresh_hi; int use_scaling = 0; + /* tsc_khz can be zero if TSC calibration fails */ + if (this_tsc_khz == 0) + return; + /* Compute a scale to convert nanoseconds in TSC cycles */ kvm_get_time_scale(this_tsc_khz, NSEC_PER_SEC / 1000, &vcpu->arch.virtual_tsc_shift, @@ -1156,20 +1160,23 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr) ns = get_kernel_ns(); elapsed = ns - kvm->arch.last_tsc_nsec; - /* n.b - signed multiplication and division required */ - usdiff = data - kvm->arch.last_tsc_write; + if (vcpu->arch.virtual_tsc_khz) { + /* n.b - signed multiplication and division required */ + usdiff = data - kvm->arch.last_tsc_write; #ifdef CONFIG_X86_64 - usdiff = (usdiff * 1000) / vcpu->arch.virtual_tsc_khz; + usdiff = (usdiff * 1000) / vcpu->arch.virtual_tsc_khz; #else - /* do_div() only does unsigned */ - asm("idivl %2; xor %%edx, %%edx" - : "=A"(usdiff) - : "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz)); + /* do_div() only does unsigned */ + asm("idivl %2; xor %%edx, %%edx" + : "=A"(usdiff) + : "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz)); #endif - do_div(elapsed, 1000); - usdiff -= elapsed; - if (usdiff < 0) - usdiff = -usdiff; + do_div(elapsed, 1000); + usdiff -= elapsed; + if (usdiff < 0) + usdiff = -usdiff; + } else + usdiff = USEC_PER_SEC; /* disable TSC match window below */ /* * Special case: TSC write with a small delta (1 second) of virtual
If the host TSC calibration fails, tsc_khz is zero (see tsc_init.c). Handle such case properly in KVM (instead of dividing by zero). https://bugzilla.redhat.com/show_bug.cgi?id=859282 Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html