From mboxrd@z Thu Jan 1 00:00:00 1970 From: Fernando Luis =?ISO-8859-1?Q?V=E1zquez?= Cao Subject: [PATCH] kvm: clear guest TSC on reset Date: Tue, 03 Dec 2013 16:08:20 +0900 Message-ID: <1386054500.25757.10.camel@nexus> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: QUOTED-PRINTABLE Cc: kvm@vger.kernel.org, Will Auld To: Paolo Bonzini , Gleb Natapov Return-path: Received: from tama50.ecl.ntt.co.jp ([129.60.39.147]:43356 "EHLO tama50.ecl.ntt.co.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751145Ab3LCHOw (ORCPT ); Tue, 3 Dec 2013 02:14:52 -0500 Sender: kvm-owner@vger.kernel.org List-ID: VCPU TSC is not cleared by a warm reset (*), which leaves many Linux guests vulnerable to the overflow in cyc2ns_offset fixed by upstream commit 9993bc635d01a6ee7f6b833b4ee65ce7c06350b1 ("sched/x86: Fix overfl= ow in cyc2ns_offset"). To put it in a nutshell, if a Linux guest without the patch above appli= ed has been up more than 208 days and attempts a warm reset chances are th= at the newly booted kernel will panic or hang. (*) Intel Xeon E5 processors show the same broken behavior due to the errata "TSC is Not Affected by Warm Reset" (Intel=C2=AE Xeon=C2= =AE Processor E5 Family Specification Update - August 2013): "The TSC (Time Stamp Counter MSR 10H) should be cleared on reset. Due to this erratum the TSC is not affected by warm reset." Cc: stable@vger.kernel.org Cc: Will Auld Signed-off-by: Fernando Luis Vazquez Cao --- diff -urNp linux-3.13-rc2-orig/arch/x86/kvm/x86.c linux-3.13-rc2/arch/x= 86/kvm/x86.c --- linux-3.13-rc2-orig/arch/x86/kvm/x86.c 2013-11-30 05:57:14.00000000= 0 +0900 +++ linux-3.13-rc2/arch/x86/kvm/x86.c 2013-12-03 14:51:53.747600839 +09= 00 @@ -6716,18 +6716,24 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu return r; } =20 -int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) +static void kvm_tsc_reset(struct kvm_vcpu *vcpu) { - int r; struct msr_data msr; =20 - r =3D vcpu_load(vcpu); - if (r) - return r; msr.data =3D 0x0; msr.index =3D MSR_IA32_TSC; msr.host_initiated =3D true; kvm_write_tsc(vcpu, &msr); +} + +int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) +{ + int r; + + r =3D vcpu_load(vcpu); + if (r) + return r; + kvm_tsc_reset(vcpu); vcpu_put(vcpu); =20 return r; @@ -6770,6 +6776,10 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcp =20 kvm_pmu_reset(vcpu); =20 + kvm_tsc_reset(vcpu); + if (guest_cpuid_has_tsc_adjust(vcpu)) + vcpu->arch.ia32_tsc_adjust_msr =3D 0x0; + memset(vcpu->arch.regs, 0, sizeof(vcpu->arch.regs)); vcpu->arch.regs_avail =3D ~0; vcpu->arch.regs_dirty =3D ~0;