From patchwork Wed Jun 30 04:25:16 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sheng Yang X-Patchwork-Id: 108732 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.4/8.14.3) with ESMTP id o5U4RZCa021720 for ; Wed, 30 Jun 2010 04:27:36 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750878Ab0F3E1Q (ORCPT ); Wed, 30 Jun 2010 00:27:16 -0400 Received: from mga02.intel.com ([134.134.136.20]:48909 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750743Ab0F3E1P (ORCPT ); Wed, 30 Jun 2010 00:27:15 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga101.jf.intel.com with ESMTP; 29 Jun 2010 21:26:25 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.53,509,1272870000"; d="scan'208";a="634899248" Received: from syang10-desktop.sh.intel.com (HELO syang10-desktop) ([10.239.36.189]) by orsmga001.jf.intel.com with ESMTP; 29 Jun 2010 21:27:07 -0700 Received: from yasker by syang10-desktop with local (Exim 4.71) (envelope-from ) id 1OTorN-0002BB-Gl; Wed, 30 Jun 2010 12:25:17 +0800 From: Sheng Yang To: Avi Kivity , Marcelo Tosatti Cc: Jan Kiszka , Joerg Roedel , kvm@vger.kernel.org, Sheng Yang Subject: [PATCH v6 2/2] KVM: Using workqueue for WBINVD Date: Wed, 30 Jun 2010 12:25:16 +0800 Message-Id: <1277871916-8348-2-git-send-email-sheng@linux.intel.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1277871916-8348-1-git-send-email-sheng@linux.intel.com> References: <1277871916-8348-1-git-send-email-sheng@linux.intel.com> 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.3 (demeter.kernel.org [140.211.167.41]); Wed, 30 Jun 2010 04:27:36 +0000 (UTC) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 2bda624..6e0b793 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index eea75f5..13f7c88 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -153,6 +153,9 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { u64 __read_mostly host_xcr0; +static struct workqueue_struct *wbinvd_wq; +static DEFINE_PER_CPU(struct work_struct, wbinvd_work); + static inline u32 bit(int bitno) { return 1 << (bitno & 31); @@ -1783,7 +1786,7 @@ out: return r; } -static void wbinvd_ipi(void *garbage) +static void wbinvd_do_work(struct work_struct *work) { wbinvd(); } @@ -1800,9 +1803,11 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) if (need_emulate_wbinvd(vcpu)) { if (kvm_x86_ops->has_wbinvd_exit()) cpumask_set_cpu(cpu, vcpu->arch.wbinvd_dirty_mask); - else if (vcpu->cpu != -1 && vcpu->cpu != cpu) - smp_call_function_single(vcpu->cpu, - wbinvd_ipi, NULL, 1); + else if (vcpu->cpu != -1 && vcpu->cpu != cpu) { + queue_work_on(vcpu->cpu, wbinvd_wq, + &per_cpu(wbinvd_work, vcpu->cpu)); + flush_workqueue(wbinvd_wq); + } } kvm_x86_ops->vcpu_load(vcpu, cpu); @@ -3672,12 +3677,16 @@ int emulate_invlpg(struct kvm_vcpu *vcpu, gva_t address) int kvm_emulate_wbinvd(struct kvm_vcpu *vcpu) { + int cpu; + if (!need_emulate_wbinvd(vcpu)) return X86EMUL_CONTINUE; if (kvm_x86_ops->has_wbinvd_exit()) { - smp_call_function_many(vcpu->arch.wbinvd_dirty_mask, - wbinvd_ipi, NULL, 1); + for_each_cpu(cpu, vcpu->arch.wbinvd_dirty_mask) + queue_work_on(cpu, wbinvd_wq, + &per_cpu(wbinvd_work, cpu)); + flush_workqueue(wbinvd_wq); cpumask_clear(vcpu->arch.wbinvd_dirty_mask); } wbinvd(); @@ -4179,7 +4188,7 @@ EXPORT_SYMBOL_GPL(kvm_after_handle_nmi); int kvm_arch_init(void *opaque) { - int r; + int r, cpu; struct kvm_x86_ops *ops = (struct kvm_x86_ops *)opaque; if (kvm_x86_ops) { @@ -4218,6 +4227,16 @@ int kvm_arch_init(void *opaque) if (cpu_has_xsave) host_xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK); + for_each_possible_cpu(cpu) { + INIT_WORK(&per_cpu(wbinvd_work, cpu), wbinvd_do_work); + } + + wbinvd_wq = create_workqueue("kvm_wbinvd"); + if (!wbinvd_wq) { + r = -ENOMEM; + goto out; + } + return 0; out: @@ -4226,6 +4245,8 @@ out: void kvm_arch_exit(void) { + destroy_workqueue(wbinvd_wq); + perf_unregister_guest_info_callbacks(&kvm_guest_cbs); if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))