All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Hornyack <peterhornyack@google.com>
To: kvm list <kvm@vger.kernel.org>, Gleb Natapov <gleb@kernel.org>,
	Paolo Bonzini <pbonzini@redhat.com>
Cc: Joerg Roedel <joro@8bytes.org>,
	Peter Hornyack <peterhornyack@google.com>
Subject: [RFC PATCH 4/5] KVM: x86: enable unhandled MSR exits for vmx
Date: Tue, 18 Aug 2015 11:46:54 -0700	[thread overview]
Message-ID: <1439923615-10600-5-git-send-email-peterhornyack@google.com> (raw)
In-Reply-To: <1439923615-10600-1-git-send-email-peterhornyack@google.com>

Set the vm's unhandled_msr_exits flag when user space calls the
KVM_ENABLE_CAP ioctl with KVM_CAP_UNHANDLED_MSR_EXITS. After kvm fails
to handle a guest rdmsr or wrmsr, check this flag and exit to user space
with KVM_EXIT_MSR rather than immediately injecting a GP fault.

On reentry into kvm, use the complete_userspace_io callback path to call
vmx_complete_userspace_msr. Complete the MSR access if user space was
able to handle it successfully, or fail the MSR access and inject a GP
fault if user space could not handle the access.

Signed-off-by: Peter Hornyack <peterhornyack@google.com>
---
 arch/x86/include/asm/kvm_host.h |  1 +
 arch/x86/kvm/vmx.c              | 74 ++++++++++++++++++++++++++++++++++++++++-
 arch/x86/kvm/x86.c              | 12 +++++++
 3 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index a6e145b1e271..1b06cea06a8e 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -682,6 +682,7 @@ struct kvm_arch {
 	u32 bsp_vcpu_id;
 
 	u64 disabled_quirks;
+	bool unhandled_msr_exits;
 };
 
 struct kvm_vm_stat {
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 27fec385d79d..ba26d382d785 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -32,6 +32,7 @@
 #include <linux/slab.h>
 #include <linux/tboot.h>
 #include <linux/hrtimer.h>
+#include <uapi/linux/kvm.h>
 #include "kvm_cache_regs.h"
 #include "x86.h"
 
@@ -5491,6 +5492,53 @@ static void fail_wrmsr(struct kvm_vcpu *vcpu, const struct msr_data *msr)
 	kvm_inject_gp(vcpu, 0);
 }
 
+/*
+ * On success, returns 1 so that __vcpu_run() will happen next. On error,
+ * returns 0.
+ */
+static int vmx_complete_userspace_msr(struct kvm_vcpu *vcpu)
+{
+	struct msr_data msr;
+
+	if (vcpu->run->msr.index != vcpu->arch.regs[VCPU_REGS_RCX]) {
+		pr_debug("msr.index 0x%x changed, does not match ecx 0x%lx\n",
+			 vcpu->run->msr.index,
+			 vcpu->arch.regs[VCPU_REGS_RCX]);
+		goto err_out;
+	}
+	msr.index = vcpu->run->msr.index;
+	msr.data = vcpu->run->msr.data;
+	msr.host_initiated = false;
+
+	switch (vcpu->run->msr.direction) {
+	case KVM_EXIT_MSR_RDMSR:
+		if (vcpu->run->msr.handled == KVM_EXIT_MSR_HANDLED)
+			complete_rdmsr(vcpu, &msr);
+		else
+			fail_rdmsr(vcpu, &msr);
+		break;
+	case KVM_EXIT_MSR_WRMSR:
+		if (vcpu->run->msr.handled == KVM_EXIT_MSR_HANDLED)
+			complete_wrmsr(vcpu, &msr);
+		else
+			fail_wrmsr(vcpu, &msr);
+		break;
+	default:
+		pr_debug("bad msr.direction %u\n", vcpu->run->msr.direction);
+		goto err_out;
+	}
+
+	return 1;
+err_out:
+	vcpu->run->exit_reason = KVM_EXIT_MSR;
+	vcpu->run->msr.direction = KVM_EXIT_MSR_COMPLETION_FAILED;
+	return 0;
+}
+
+/*
+ * Returns 1 if the rdmsr handling is complete; returns 0 if kvm should exit to
+ * user space to handle this rdmsr.
+ */
 static int handle_rdmsr(struct kvm_vcpu *vcpu)
 {
 	u32 ecx = vcpu->arch.regs[VCPU_REGS_RCX];
@@ -5499,6 +5547,16 @@ static int handle_rdmsr(struct kvm_vcpu *vcpu)
 	msr_info.index = ecx;
 	msr_info.host_initiated = false;
 	if (vmx_get_msr(vcpu, &msr_info)) {
+		if (vcpu->kvm->arch.unhandled_msr_exits) {
+			vcpu->run->exit_reason = KVM_EXIT_MSR;
+			vcpu->run->msr.direction = KVM_EXIT_MSR_RDMSR;
+			vcpu->run->msr.index = msr_info.index;
+			vcpu->run->msr.data = 0;
+			vcpu->run->msr.handled = 0;
+			vcpu->arch.complete_userspace_io =
+					vmx_complete_userspace_msr;
+			return 0;
+		}
 		fail_rdmsr(vcpu, &msr_info);
 		return 1;
 	}
@@ -5508,6 +5566,10 @@ static int handle_rdmsr(struct kvm_vcpu *vcpu)
 	return 1;
 }
 
+/*
+ * Returns 1 if the wrmsr handling is complete; returns 0 if kvm should exit to
+ * user space to handle this wrmsr.
+ */
 static int handle_wrmsr(struct kvm_vcpu *vcpu)
 {
 	struct msr_data msr;
@@ -5519,6 +5581,16 @@ static int handle_wrmsr(struct kvm_vcpu *vcpu)
 	msr.index = ecx;
 	msr.host_initiated = false;
 	if (kvm_set_msr(vcpu, &msr) != 0) {
+		if (vcpu->kvm->arch.unhandled_msr_exits) {
+			vcpu->run->exit_reason = KVM_EXIT_MSR;
+			vcpu->run->msr.direction = KVM_EXIT_MSR_WRMSR;
+			vcpu->run->msr.index = msr.index;
+			vcpu->run->msr.data = msr.data;
+			vcpu->run->msr.handled = 0;
+			vcpu->arch.complete_userspace_io =
+					vmx_complete_userspace_msr;
+			return 0;
+		}
 		fail_wrmsr(vcpu, &msr);
 		return 1;
 	}
@@ -8163,7 +8235,7 @@ static bool vmx_xsaves_supported(void)
 
 static bool vmx_msr_exits_supported(void)
 {
-	return false;
+	return true;
 }
 
 static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 4bbc2a1676c9..5c22f4655741 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2461,6 +2461,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 	case KVM_CAP_ENABLE_CAP_VM:
 	case KVM_CAP_DISABLE_QUIRKS:
 	case KVM_CAP_SET_BOOT_CPU_ID:
+	case KVM_CAP_UNHANDLED_MSR_EXITS:
 #ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
 	case KVM_CAP_ASSIGN_DEV_IRQ:
 	case KVM_CAP_PCI_2_3:
@@ -3568,6 +3569,17 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
 		kvm->arch.disabled_quirks = cap->args[0];
 		r = 0;
 		break;
+	case KVM_CAP_UNHANDLED_MSR_EXITS:
+		if (kvm_x86_ops->msr_exits_supported()) {
+			if (cap->args[0])
+				kvm->arch.unhandled_msr_exits = true;
+			else
+				kvm->arch.unhandled_msr_exits = false;
+			r = 0;
+		} else {
+			r = -EINVAL;
+		}
+		break;
 	default:
 		r = -EINVAL;
 		break;
-- 
2.5.0.276.gf5e568e


  parent reply	other threads:[~2015-08-18 18:47 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-08-18 18:46 [RFC PATCH 0/5] KVM: x86: exit to user space on unhandled MSR accesses Peter Hornyack
2015-08-18 18:46 ` [RFC PATCH 1/5] KVM: x86: refactor vmx rdmsr/wrmsr completion into new functions Peter Hornyack
2015-08-18 18:46 ` [RFC PATCH 2/5] KVM: add KVM_EXIT_MSR exit reason and capability Peter Hornyack
2015-12-18 21:25   ` Paolo Bonzini
2015-12-18 23:56     ` Peter Hornyack
2015-12-21 18:58     ` Peter Hornyack
2015-12-22  7:24       ` Pavel Fedin
2015-12-22 12:01         ` 'Roman Kagan'
2015-12-22 12:51           ` Pavel Fedin
2015-12-22 14:09             ` 'Roman Kagan'
2015-12-23  7:47               ` Pavel Fedin
2016-01-12  3:21         ` Peter Hornyack
2015-08-18 18:46 ` [RFC PATCH 3/5] KVM: x86: add msr_exits_supported to kvm_x86_ops Peter Hornyack
2015-08-24 23:15   ` Bandan Das
2015-08-18 18:46 ` Peter Hornyack [this message]
2015-08-24 23:14   ` [RFC PATCH 4/5] KVM: x86: enable unhandled MSR exits for vmx Bandan Das
2015-08-18 18:46 ` [RFC PATCH 5/5] KVM: x86: add trace events for unhandled MSR exits Peter Hornyack
2015-08-19 21:43 ` [RFC PATCH 0/5] KVM: x86: exit to user space on unhandled MSR accesses Bandan Das
2015-08-20 19:40   ` Peter Hornyack
2015-08-24 23:21     ` Bandan Das

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=1439923615-10600-5-git-send-email-peterhornyack@google.com \
    --to=peterhornyack@google.com \
    --cc=gleb@kernel.org \
    --cc=joro@8bytes.org \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.