From 8a56c6cd5979e5cddaa9886419dde1f58a4cecde Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 14 Mar 2013 07:45:49 -0400 Subject: [PATCH] Fix divide by zero on host TSC calibration failure (rhbz 859282) --- ...-handle-host-TSC-calibration-failure.patch | 58 +++++++++++++++++++ kernel.spec | 11 +++- 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 VMX-x86-handle-host-TSC-calibration-failure.patch diff --git a/VMX-x86-handle-host-TSC-calibration-failure.patch b/VMX-x86-handle-host-TSC-calibration-failure.patch new file mode 100644 index 000000000..6b6ddd2d2 --- /dev/null +++ b/VMX-x86-handle-host-TSC-calibration-failure.patch @@ -0,0 +1,58 @@ +@@ -, +, @@ + VMX: x86: handle host TSC calibration failure + + 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 + Signed-off-by: Gleb Natapov +--- a/arch/x86/kvm/x86.c ++++ a/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 diff --git a/kernel.spec b/kernel.spec index bd182bf27..6c55b26dd 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -740,6 +740,9 @@ Patch21271: drm-i915-bounds-check-execbuffer-relocation-count.patch Patch21273: cfg80211-mac80211-disconnect-on-suspend.patch Patch21274: mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.9.patch +#rhbz 859282 +Patch21275: VMX-x86-handle-host-TSC-calibration-failure.patch + Patch22000: weird-root-dentry-name-debug.patch #selinux ptrace child permissions @@ -1438,6 +1441,9 @@ ApplyPatch drm-i915-bounds-check-execbuffer-relocation-count.patch ApplyPatch cfg80211-mac80211-disconnect-on-suspend.patch ApplyPatch mac80211_fixes_for_ieee80211_do_stop_while_suspend_v3.9.patch +#rhbz 859282 +ApplyPatch VMX-x86-handle-host-TSC-calibration-failure.patch + # END OF PATCH APPLICATIONS %endif @@ -2279,6 +2285,9 @@ fi # ||----w | # || || %changelog +* Fri Mar 15 2013 Josh Boyer +- Fix divide by zero on host TSC calibration failure (rhbz 859282) + * Fri Mar 15 2013 Josh Boyer - 3.9.0-0.rc2.git1.1 - Linux v3.9-rc2-292-ga2362d2 - Fixes CVE-2013-1860 kernel: usb: cdc-wdm buffer overflow triggered by device