From 1e99e37726d99dc5110b7925f6d946a743850095 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Wed, 12 Jun 2013 07:37:50 -0400 Subject: [PATCH] Fix KVM divide by zero error (rhbz 969644) --- ...andle-idiv-overflow-at-kvm_write_tsc.patch | 45 +++++++++++++++++++ kernel.spec | 7 +++ 2 files changed, 52 insertions(+) create mode 100644 KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch diff --git a/KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch b/KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch new file mode 100644 index 000000000..678e82953 --- /dev/null +++ b/KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch @@ -0,0 +1,45 @@ +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 */ + diff --git a/kernel.spec b/kernel.spec index 50818e82b..a4e9240c4 100644 --- a/kernel.spec +++ b/kernel.spec @@ -770,6 +770,9 @@ Patch25042: x86-range-make-add_range-use-blank-slot.patch #rhbz 950735 Patch25045: rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch +#rhbz 969644 +Patch25046: KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch + # END OF PATCH DEFINITIONS %endif @@ -1484,6 +1487,9 @@ ApplyPatch x86-range-make-add_range-use-blank-slot.patch #rhbz 950735 ApplyPatch rt2800-fix-RT5390-RT3290-TX-power-settings-regression.patch +#rhbz 969644 +ApplyPatch KVM-x86-handle-idiv-overflow-at-kvm_write_tsc.patch + # END OF PATCH APPLICATIONS %endif @@ -2290,6 +2296,7 @@ fi # || || %changelog * Wed Jun 12 2013 Josh Boyer +- Fix KVM divide by zero error (rhbz 969644) - Add fix for rt5390/rt3290 regression (rhbz 950735) * Tue Jun 11 2013 Dave Jones