Message ID | 20130612023112.GA26662@amt.cnet (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, Jun 11, 2013 at 11:31:12PM -0300, Marcelo Tosatti wrote: > > Its possible that idivl overflows (due to large delta stored in usdiff, > valid scenario). > > Create an exception handler to catch the overflow exception (division by zero > is protected by vcpu->arch.virtual_tsc_khz check), and interpret it accordingly > (delta is larger than USEC_PER_SEC). > > Fixes https://bugzilla.redhat.com/show_bug.cgi?id=969644 > > Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> > Applied, thanks. > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 094b5d9..64a4b03 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -1194,20 +1194,37 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr) > elapsed = ns - kvm->arch.last_tsc_nsec; > > if (vcpu->arch.virtual_tsc_khz) { > + int faulted = 0; > + > /* 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; > #else > /* do_div() only does unsigned */ > - asm("idivl %2; xor %%edx, %%edx" > - : "=A"(usdiff) > - : "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz)); > + asm("1: idivl %[divisor]\n" > + "2: xor %%edx, %%edx\n" > + " movl $0, %[faulted]\n" > + "3:\n" > + ".section .fixup,\"ax\"\n" > + "4: movl $1, %[faulted]\n" > + " jmp 3b\n" > + ".previous\n" > + > + _ASM_EXTABLE(1b, 4b) > + > + : "=A"(usdiff), [faulted] "=r" (faulted) > + : "A"(usdiff * 1000), [divisor] "rm"(vcpu->arch.virtual_tsc_khz)); > + > #endif > do_div(elapsed, 1000); > usdiff -= elapsed; > if (usdiff < 0) > usdiff = -usdiff; > + > + /* idivl overflow => difference is larger than USEC_PER_SEC */ > + if (faulted) > + usdiff = USEC_PER_SEC; > } else > usdiff = USEC_PER_SEC; /* disable TSC match window below */ > > -- > 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 -- 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 094b5d9..64a4b03 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1194,20 +1194,37 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr) elapsed = ns - kvm->arch.last_tsc_nsec; if (vcpu->arch.virtual_tsc_khz) { + int faulted = 0; + /* 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; #else /* do_div() only does unsigned */ - asm("idivl %2; xor %%edx, %%edx" - : "=A"(usdiff) - : "A"(usdiff * 1000), "rm"(vcpu->arch.virtual_tsc_khz)); + asm("1: idivl %[divisor]\n" + "2: xor %%edx, %%edx\n" + " movl $0, %[faulted]\n" + "3:\n" + ".section .fixup,\"ax\"\n" + "4: movl $1, %[faulted]\n" + " jmp 3b\n" + ".previous\n" + + _ASM_EXTABLE(1b, 4b) + + : "=A"(usdiff), [faulted] "=r" (faulted) + : "A"(usdiff * 1000), [divisor] "rm"(vcpu->arch.virtual_tsc_khz)); + #endif do_div(elapsed, 1000); usdiff -= elapsed; if (usdiff < 0) usdiff = -usdiff; + + /* idivl overflow => difference is larger than USEC_PER_SEC */ + if (faulted) + usdiff = USEC_PER_SEC; } else usdiff = USEC_PER_SEC; /* disable TSC match window below */
Its possible that idivl overflows (due to large delta stored in usdiff, valid scenario). Create an exception handler to catch the overflow exception (division by zero is protected by vcpu->arch.virtual_tsc_khz check), and interpret it accordingly (delta is larger than USEC_PER_SEC). Fixes https://bugzilla.redhat.com/show_bug.cgi?id=969644 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