From patchwork Mon Sep 24 03:28:43 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Hao, Xudong" X-Patchwork-Id: 1496121 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id CE16DDF280 for ; Mon, 24 Sep 2012 03:25:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754938Ab2IXDZZ (ORCPT ); Sun, 23 Sep 2012 23:25:25 -0400 Received: from mga09.intel.com ([134.134.136.24]:53033 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754917Ab2IXDZY (ORCPT ); Sun, 23 Sep 2012 23:25:24 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP; 23 Sep 2012 20:25:10 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.80,471,1344236400"; d="scan'208";a="196785955" Received: from xhao-dev.sh.intel.com (HELO localhost.localdomain) ([10.239.48.48]) by orsmga001.jf.intel.com with ESMTP; 23 Sep 2012 20:25:11 -0700 From: Xudong Hao To: avi@redhat.com Cc: kvm@vger.kernel.org, xiantao.zhang@intel.com, Xudong Hao Subject: [PATCH v4] kvm/fpu: Enable fully eager restore kvm FPU Date: Mon, 24 Sep 2012 11:28:43 +0800 Message-Id: <1348457323-22616-1-git-send-email-xudong.hao@intel.com> X-Mailer: git-send-email 1.5.5 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Enable KVM FPU fully eager restore, if there is other FPU state which isn't tracked by CR0.TS bit. v4 changes from v3: - Wrap up some confused code with a clear functio lazy_fpu_allowed() - Update fpu while update cr4 too. v3 changes from v2: - Make fpu active explicitly while guest xsave is enabling and non-lazy xstate bit exist. v2 changes from v1: - Expand KVM_XSTATE_LAZY to 64 bits before negating it. Signed-off-by: Xudong Hao --- arch/x86/include/asm/kvm.h | 4 ++++ arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/svm.c | 1 + arch/x86/kvm/vmx.c | 1 + arch/x86/kvm/x86.c | 32 +++++++++++++++++++++++++++++++- 5 files changed, 38 insertions(+), 1 deletions(-) diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h index 521bf25..4c27056 100644 --- a/arch/x86/include/asm/kvm.h +++ b/arch/x86/include/asm/kvm.h @@ -8,6 +8,8 @@ #include #include +#include +#include /* Select x86 specific features in */ #define __KVM_HAVE_PIT @@ -30,6 +32,8 @@ /* Architectural interrupt line count. */ #define KVM_NR_INTERRUPTS 256 +#define KVM_XSTATE_LAZY (XSTATE_FP | XSTATE_SSE | XSTATE_YMM) + struct kvm_memory_alias { __u32 slot; /* this has a different namespace than memory slots */ __u32 flags; diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 0b902c9..25fef9e 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -826,6 +826,7 @@ unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu); void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw); void kvm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l); int kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr); +void update_lazy_fpu(struct kvm_vcpu *vcpu); int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata); int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 818fceb..fbdb44a 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -2941,6 +2941,7 @@ static int cr_interception(struct vcpu_svm *svm) break; case 4: err = kvm_set_cr4(&svm->vcpu, val); + update_lazy_fpu(vcpu); break; case 8: err = kvm_set_cr8(&svm->vcpu, val); diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 30bcb95..b3880c0 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -4488,6 +4488,7 @@ static int handle_cr(struct kvm_vcpu *vcpu) return 1; case 4: err = handle_set_cr4(vcpu, val); + update_lazy_fpu(vcpu); kvm_complete_insn_gp(vcpu, err); return 1; case 8: { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index fc2a0a1..2e14cec 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -544,6 +544,31 @@ void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw) } EXPORT_SYMBOL_GPL(kvm_lmsw); +/* + * KVM trigger FPU restore by #NM (via CR0.TS), + * only XCR0.bit0, XCR0.bit1, XCR0.bit2 is tracked + * by TS bit, there might be other FPU state is not tracked + * by TS bit. + * This function lazy_fpu_allowed() return true with any of + * the following cases: 1)xsave isn't enabled in guest; + * 2)all guest FPU states can be tracked by TS bit. + */ +static bool lazy_fpu_allowed(struct kvm_vcpu *vcpu) +{ + return !!(!kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE) || + !(vcpu->arch.xcr0 & ~((u64)KVM_XSTATE_LAZY))); +} + +void update_lazy_fpu(struct kvm_vcpu *vcpu) +{ + if (lazy_fpu_allowed(vcpu)) { + vcpu->fpu_active = 0; + kvm_x86_ops->fpu_deactivate(vcpu); + } + else + kvm_x86_ops->fpu_activate(vcpu); +} + int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) { u64 xcr0; @@ -571,6 +596,7 @@ int kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) kvm_inject_gp(vcpu, 0); return 1; } + update_lazy_fpu(vcpu); return 0; } EXPORT_SYMBOL_GPL(kvm_set_xcr); @@ -5985,7 +6011,11 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu) vcpu->guest_fpu_loaded = 0; fpu_save_init(&vcpu->arch.guest_fpu); ++vcpu->stat.fpu_reload; - kvm_make_request(KVM_REQ_DEACTIVATE_FPU, vcpu); + /* + * Make deactivate request while allow fpu lazy restore. + */ + if (lazy_fpu_allowed(vcpu)) + kvm_make_request(KVM_REQ_DEACTIVATE_FPU, vcpu); trace_kvm_fpu(0); }