From patchwork Tue Jun 21 12:21:59 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zachary Amsden X-Patchwork-Id: 901312 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p5LCM5ax021285 for ; Tue, 21 Jun 2011 12:22:05 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754261Ab1FUMWB (ORCPT ); Tue, 21 Jun 2011 08:22:01 -0400 Received: from mx1.redhat.com ([209.132.183.28]:5818 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753098Ab1FUMWB (ORCPT ); Tue, 21 Jun 2011 08:22:01 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p5LCM0BD010245 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 21 Jun 2011 08:22:00 -0400 Received: from [10.11.8.134] (vpn-8-134.rdu.redhat.com [10.11.8.134]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p5LCLxwD004264 for ; Tue, 21 Jun 2011 08:22:00 -0400 Message-ID: <4E008CE7.6020204@redhat.com> Date: Tue, 21 Jun 2011 05:21:59 -0700 From: Zachary Amsden User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.10) Gecko/20100621 Fedora/3.0.5-1.fc13 Thunderbird/3.0.5 MIME-Version: 1.0 To: kvm Subject: Fwd: [KVM TSC emulation 4/9] Fix last_guest_tsc / tsc_offset semantics X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Tue, 21 Jun 2011 12:22:06 +0000 (UTC) -------- Original Message -------- Subject: [KVM TSC emulation 4/9] Fix last_guest_tsc / tsc_offset semantics Date: Mon, 20 Jun 2011 16:59:32 -0700 From: Zachary Amsden To: Avi Kivity , Marcelo Tosatti , Glauber Costa , Frank Arnold , Joerg Roedel , Jan Kiszka , linux-kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Zachary Amsden , Avi Kivity , Marcelo Tosatti , Glauber Costa , Frank Arnold , Joerg Roedel , Jan Kiszka , linux-kvm@vger.kernel.org CC: Zachary Amsden , Zachary Amsden The variable last_guest_tsc was being used as an ad-hoc indicator that guest TSC has been initialized and recorded correctly. However, it may not have been, it could be that guest TSC has been set to some large value, the back to a small value (by, say, a software reboot). This defeats the logic and causes KVM to falsely assume that the guest TSC has gone backwards, marking the host TSC unstable, which is undesirable behavior. In addition, rather than try to compute an offset adjustment for the TSC on unstable platforms, just recompute the whole offset. This allows us to get rid of one callsite for adjust_tsc_offset, which is problematic because the units it takes are in guest units, but here, the computation was originally being done in host units. Doing this, and also recording last_guest_tsc when the TSC is written allow us to remove the tricky logic which depended on last_guest_tsc being zero to indicate a reset of uninitialized value. Instead, we now have the guarantee that the guest TSC offset is always at least something which will get us last_guest_tsc. Signed-off-by: Zachary Amsden --- arch/x86/kvm/x86.c | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 2176714..3bd2ca3 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1088,6 +1088,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, u64 data) vcpu->arch.hv_clock.tsc_timestamp = 0; vcpu->arch.last_tsc_write = data; vcpu->arch.last_tsc_nsec = ns; + vcpu->arch.last_guest_tsc = data; } EXPORT_SYMBOL_GPL(kvm_write_tsc); @@ -1156,7 +1157,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) * observed by the guest and ensure the new system time is greater. */ max_kernel_ns = 0; - if (vcpu->hv_clock.tsc_timestamp&& vcpu->last_guest_tsc) { + if (vcpu->hv_clock.tsc_timestamp) { max_kernel_ns = vcpu->last_guest_tsc - vcpu->hv_clock.tsc_timestamp; max_kernel_ns = pvclock_scale_delta(max_kernel_ns, @@ -2157,13 +2158,13 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) u64 tsc; kvm_get_msr(vcpu, MSR_IA32_TSC,&tsc); - tsc_delta = !vcpu->arch.last_guest_tsc ? 0 : - tsc - vcpu->arch.last_guest_tsc; - + tsc_delta = tsc - vcpu->arch.last_guest_tsc; if (tsc_delta< 0) mark_tsc_unstable("KVM discovered backwards TSC"); if (check_tsc_unstable()) { - kvm_x86_ops->adjust_tsc_offset(vcpu, -tsc_delta); + u64 offset = kvm_x86_ops->compute_tsc_offset(vcpu, + vcpu->arch.last_guest_tsc); + kvm_x86_ops->write_tsc_offset(vcpu, offset); vcpu->arch.tsc_catchup = 1; } kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);