From: Avi Kivity <avi@redhat.com>
To: linux-kernel@vger.kernel.org
Cc: kvm@vger.kernel.org
Subject: [PATCH 21/35] KVM: x86 shared msr infrastructure
Date: Thu, 19 Nov 2009 15:34:57 +0200 [thread overview]
Message-ID: <1258637711-11674-22-git-send-email-avi@redhat.com> (raw)
In-Reply-To: <1258637711-11674-1-git-send-email-avi@redhat.com>
The various syscall-related MSRs are fairly expensive to switch. Currently
we switch them on every vcpu preemption, which is far too often:
- if we're switching to a kernel thread (idle task, threaded interrupt,
kernel-mode virtio server (vhost-net), for example) and back, then
there's no need to switch those MSRs since kernel threasd won't
be exiting to userspace.
- if we're switching to another guest running an identical OS, most likely
those MSRs will have the same value, so there's little point in reloading
them.
- if we're running the same OS on the guest and host, the MSRs will have
identical values and reloading is unnecessary.
This patch uses the new user return notifiers to implement last-minute
switching, and checks the msr values to avoid unnecessary reloading.
Signed-off-by: Avi Kivity <avi@redhat.com>
---
arch/x86/include/asm/kvm_host.h | 3 +
arch/x86/kvm/Kconfig | 1 +
arch/x86/kvm/x86.c | 81 +++++++++++++++++++++++++++++++++++++++
3 files changed, 85 insertions(+), 0 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 0558ff8..26a74b7 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -809,4 +809,7 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu);
int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu);
int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
+void kvm_define_shared_msr(unsigned index, u32 msr);
+void kvm_set_shared_msr(unsigned index, u64 val);
+
#endif /* _ASM_X86_KVM_HOST_H */
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index b84e571..4cd4983 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -28,6 +28,7 @@ config KVM
select HAVE_KVM_IRQCHIP
select HAVE_KVM_EVENTFD
select KVM_APIC_ARCHITECTURE
+ select USER_RETURN_NOTIFIER
---help---
Support hosting fully virtualized guest machines using hardware
virtualization extensions. You will need a fairly recent
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e16cdc9..58c5cdd 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -37,6 +37,7 @@
#include <linux/iommu.h>
#include <linux/intel-iommu.h>
#include <linux/cpufreq.h>
+#include <linux/user-return-notifier.h>
#include <trace/events/kvm.h>
#undef TRACE_INCLUDE_FILE
#define CREATE_TRACE_POINTS
@@ -87,6 +88,25 @@ EXPORT_SYMBOL_GPL(kvm_x86_ops);
int ignore_msrs = 0;
module_param_named(ignore_msrs, ignore_msrs, bool, S_IRUGO | S_IWUSR);
+#define KVM_NR_SHARED_MSRS 16
+
+struct kvm_shared_msrs_global {
+ int nr;
+ struct kvm_shared_msr {
+ u32 msr;
+ u64 value;
+ } msrs[KVM_NR_SHARED_MSRS];
+};
+
+struct kvm_shared_msrs {
+ struct user_return_notifier urn;
+ bool registered;
+ u64 current_value[KVM_NR_SHARED_MSRS];
+};
+
+static struct kvm_shared_msrs_global __read_mostly shared_msrs_global;
+static DEFINE_PER_CPU(struct kvm_shared_msrs, shared_msrs);
+
struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "pf_fixed", VCPU_STAT(pf_fixed) },
{ "pf_guest", VCPU_STAT(pf_guest) },
@@ -123,6 +143,64 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ NULL }
};
+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);
+
+ 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;
+ }
+ }
+ locals->registered = false;
+ user_return_notifier_unregister(urn);
+}
+
+void kvm_define_shared_msr(unsigned slot, u32 msr)
+{
+ int cpu;
+ u64 value;
+
+ 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;
+}
+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);
+
+ for (i = 0; i < shared_msrs_global.nr; ++i)
+ locals->current_value[i] = shared_msrs_global.msrs[i].value;
+}
+
+void kvm_set_shared_msr(unsigned slot, u64 value)
+{
+ struct kvm_shared_msrs *smsr = &__get_cpu_var(shared_msrs);
+
+ if (value == smsr->current_value[slot])
+ return;
+ smsr->current_value[slot] = value;
+ wrmsrl(shared_msrs_global.msrs[slot].msr, value);
+ if (!smsr->registered) {
+ smsr->urn.on_user_return = kvm_on_user_return;
+ user_return_notifier_register(&smsr->urn);
+ smsr->registered = true;
+ }
+}
+EXPORT_SYMBOL_GPL(kvm_set_shared_msr);
+
unsigned long segment_base(u16 selector)
{
struct descriptor_table gdt;
@@ -4815,6 +4893,9 @@ int kvm_arch_hardware_enable(void *garbage)
int cpu = raw_smp_processor_id();
per_cpu(cpu_tsc_khz, cpu) = 0;
}
+
+ kvm_shared_msr_cpu_online();
+
return kvm_x86_ops->hardware_enable(garbage);
}
--
1.6.5.2
next prev parent reply other threads:[~2009-11-19 13:35 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-11-19 13:34 [PATCH 00/35] KVM updates for the 2.6.33 merge window (batch 2/2) Avi Kivity
2009-11-19 13:34 ` [PATCH 01/35] KVM: SVM: Add tracepoint for #vmexit because intr pending Avi Kivity
2009-11-19 13:34 ` [PATCH 02/35] KVM: SVM: Add tracepoint for invlpga instruction Avi Kivity
2009-11-19 13:34 ` [PATCH 03/35] KVM: SVM: Add tracepoint for skinit instruction Avi Kivity
2009-11-19 13:34 ` [PATCH 04/35] KVM: SVM: Remove nsvm_printk debugging code Avi Kivity
2009-11-19 13:34 ` [PATCH 05/35] KVM: introduce kvm_vcpu_on_spin Avi Kivity
2009-11-19 13:34 ` [PATCH 06/35] KVM: VMX: Add support for Pause-Loop Exiting Avi Kivity
2009-11-19 13:34 ` [PATCH 07/35] KVM: SVM: Support Pause Filter in AMD processors Avi Kivity
2009-11-19 13:34 ` [PATCH 08/35] KVM: x86: Harden against cpufreq Avi Kivity
2009-11-19 13:34 ` [PATCH 09/35] KVM: VMX: fix handle_pause declaration Avi Kivity
2009-11-19 13:34 ` [PATCH 10/35] KVM: x86: Drop unneeded CONFIG_HAS_IOMEM check Avi Kivity
2009-11-19 13:34 ` [PATCH 11/35] KVM: Xen PV-on-HVM guest support Avi Kivity
2009-11-19 13:34 ` [PATCH 12/35] KVM: x86: Fix guest single-stepping while interruptible Avi Kivity
2009-11-19 13:34 ` [PATCH 13/35] KVM: SVM: Cleanup NMI singlestep Avi Kivity
2009-11-19 13:34 ` [PATCH 14/35] KVM: fix irq_source_id size verification Avi Kivity
2009-11-19 13:34 ` [PATCH 15/35] KVM: allow userspace to adjust kvmclock offset Avi Kivity
2010-01-29 13:32 ` Alexander Graf
2010-02-01 18:54 ` Marcelo Tosatti
2010-02-01 21:42 ` patch kvm-allow-userspace-to-adjust-kvmclock-offset.patch added to 2.6.32-stable tree gregkh
2009-11-19 13:34 ` [PATCH 16/35] KVM: Enable 32bit dirty log pointers on 64bit host Avi Kivity
2009-11-19 13:34 ` [PATCH 17/35] KVM: VMX: Use macros instead of hex value on cr0 initialization Avi Kivity
2009-11-19 13:34 ` [PATCH 18/35] KVM: SVM: Reset cr0 properly on vcpu reset Avi Kivity
2009-11-19 13:34 ` [PATCH 19/35] KVM: SVM: init_vmcb(): remove redundant save->cr0 initialization Avi Kivity
2009-11-19 13:34 ` [PATCH 20/35] KVM: VMX: Move MSR_KERNEL_GS_BASE out of the vmx autoload msr area Avi Kivity
2009-11-19 13:34 ` Avi Kivity [this message]
2009-11-19 13:34 ` [PATCH 22/35] KVM: VMX: Use shared msr infrastructure Avi Kivity
2009-11-19 13:34 ` [PATCH 23/35] KVM: powerpc: Fix BUILD_BUG_ON condition Avi Kivity
2009-11-19 13:35 ` [PATCH 24/35] KVM: remove duplicated task_switch check Avi Kivity
2009-11-19 13:35 ` [PATCH 25/35] KVM: VMX: move CR3/PDPTR update to vmx_set_cr3 Avi Kivity
2009-11-19 13:35 ` [PATCH 26/35] KVM: MMU: update invlpg handler comment Avi Kivity
2009-11-19 13:35 ` [PATCH 27/35] KVM: VMX: Remove vmx->msr_offset_efer Avi Kivity
2009-11-19 13:35 ` [PATCH 28/35] KVM: x86: disallow multiple KVM_CREATE_IRQCHIP Avi Kivity
2009-11-19 13:35 ` [PATCH 29/35] KVM: x86: disallow KVM_{SET,GET}_LAPIC without allocated in-kernel lapic Avi Kivity
2009-11-19 13:35 ` [PATCH 30/35] KVM: only clear irq_source_id if irqchip is present Avi Kivity
2009-11-19 13:35 ` [PATCH 31/35] KVM: x86: Polish exception injection via KVM_SET_GUEST_DEBUG Avi Kivity
2009-11-19 13:35 ` [PATCH 32/35] KVM: Reorder IOCTLs in main kvm.h Avi Kivity
2009-11-19 13:35 ` [PATCH 33/35] KVM: Allow internal errors reported to userspace to carry extra data Avi Kivity
2009-11-19 13:35 ` [PATCH 34/35] KVM: VMX: Report unexpected simultaneous exceptions as internal errors Avi Kivity
2009-11-19 13:35 ` [PATCH 35/35] KVM: x86: Add KVM_GET/SET_VCPU_EVENTS Avi Kivity
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1258637711-11674-22-git-send-email-avi@redhat.com \
--to=avi@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox