From patchwork Wed Dec 16 05:48:03 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sheng Yang X-Patchwork-Id: 68295 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.2) with ESMTP id nBI4ixkj005715 for ; Fri, 18 Dec 2009 04:45:23 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1760329AbZLPFsf (ORCPT ); Wed, 16 Dec 2009 00:48:35 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1761046AbZLPFsa (ORCPT ); Wed, 16 Dec 2009 00:48:30 -0500 Received: from mga02.intel.com ([134.134.136.20]:28497 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1761105AbZLPFs0 (ORCPT ); Wed, 16 Dec 2009 00:48:26 -0500 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP; 15 Dec 2009 21:46:56 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.47,404,1257148800"; d="scan'208";a="476542823" Received: from syang10-desktop.sh.intel.com (HELO syang10-desktop) ([10.239.36.76]) by orsmga002.jf.intel.com with ESMTP; 15 Dec 2009 21:48:11 -0800 Received: from yasker by syang10-desktop with local (Exim 4.69) (envelope-from ) id 1NKmkK-0004zX-Kz; Wed, 16 Dec 2009 13:48:24 +0800 From: Sheng Yang To: Avi Kivity , Marcelo Tosatti Cc: kvm@vger.kernel.org, Sheng Yang Subject: [PATCH 2/4] KVM: Extended shared_msr_global to per CPU Date: Wed, 16 Dec 2009 13:48:03 +0800 Message-Id: <1260942485-19156-3-git-send-email-sheng@linux.intel.com> X-Mailer: git-send-email 1.6.3.3 In-Reply-To: <1260942485-19156-1-git-send-email-sheng@linux.intel.com> References: <1260942485-19156-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 diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index dd15d7a..4262450 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -92,16 +92,16 @@ module_param_named(ignore_msrs, ignore_msrs, bool, S_IRUGO | S_IWUSR); struct kvm_shared_msrs_global { int nr; - struct kvm_shared_msr { - u32 msr; - u64 value; - } msrs[KVM_NR_SHARED_MSRS]; + u32 msrs[KVM_NR_SHARED_MSRS]; }; struct kvm_shared_msrs { struct user_return_notifier urn; bool registered; - u64 current_value[KVM_NR_SHARED_MSRS]; + struct kvm_shared_msr_values { + u64 host; + u64 curr; + } values[KVM_NR_SHARED_MSRS]; }; static struct kvm_shared_msrs_global __read_mostly shared_msrs_global; @@ -146,53 +146,73 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { static void kvm_on_user_return(struct user_return_notifier *urn) { unsigned slot; - struct kvm_shared_msr *global; struct kvm_shared_msrs *locals = container_of(urn, struct kvm_shared_msrs, urn); + struct kvm_shared_msr_values *values; for (slot = 0; slot < shared_msrs_global.nr; ++slot) { - global = &shared_msrs_global.msrs[slot]; - if (global->value != locals->current_value[slot]) { - wrmsrl(global->msr, global->value); - locals->current_value[slot] = global->value; + values = &locals->values[slot]; + if (values->host != values->curr) { + wrmsrl(shared_msrs_global.msrs[slot], values->host); + values->curr = values->host; } } locals->registered = false; user_return_notifier_unregister(urn); } -void kvm_define_shared_msr(unsigned slot, u32 msr) +static void shared_msr_update(void *data) { - int cpu; + struct kvm_shared_msrs *smsr; + u32 msr = *(u32 *)data; + int slot; u64 value; + smsr = &get_cpu_var(shared_msrs); + /* only read, and nobody should modify it at this time, + * so don't need lock */ + for (slot = 0; slot < shared_msrs_global.nr; slot++) + if (shared_msrs_global.msrs[slot] == msr) + break; + if (slot >= shared_msrs_global.nr) { + printk(KERN_ERR "kvm: can't find the defined MSR!"); + return; + } + rdmsrl_safe(msr, &value); + smsr->values[slot].host = value; + smsr->values[slot].curr = value; + put_cpu_var(shared_msrs); +} + +void kvm_define_shared_msr(unsigned slot, u32 msr) +{ if (slot >= shared_msrs_global.nr) shared_msrs_global.nr = slot + 1; - shared_msrs_global.msrs[slot].msr = msr; - rdmsrl_safe(msr, &value); - shared_msrs_global.msrs[slot].value = value; - for_each_online_cpu(cpu) - per_cpu(shared_msrs, cpu).current_value[slot] = value; + shared_msrs_global.msrs[slot] = msr; + /* we need ensured the shared_msr_global have been updated */ + smp_wmb(); + smp_call_function(shared_msr_update, &msr, 1); + shared_msr_update(&msr); } EXPORT_SYMBOL_GPL(kvm_define_shared_msr); static void kvm_shared_msr_cpu_online(void) { unsigned i; - struct kvm_shared_msrs *locals = &__get_cpu_var(shared_msrs); + struct kvm_shared_msrs *smsr = &__get_cpu_var(shared_msrs); for (i = 0; i < shared_msrs_global.nr; ++i) - locals->current_value[i] = shared_msrs_global.msrs[i].value; + smsr->values[i].curr = smsr->values[i].host; } void kvm_set_shared_msr(unsigned slot, u64 value, u64 mask) { struct kvm_shared_msrs *smsr = &__get_cpu_var(shared_msrs); - if (((value ^ smsr->current_value[slot]) & mask) == 0) + if (((value ^ smsr->values[slot].curr) & mask) == 0) return; - smsr->current_value[slot] = value; - wrmsrl(shared_msrs_global.msrs[slot].msr, value); + smsr->values[slot].curr = value; + wrmsrl(shared_msrs_global.msrs[slot], value); if (!smsr->registered) { smsr->urn.on_user_return = kvm_on_user_return; user_return_notifier_register(&smsr->urn);