+ kvm-expose-msrs-to-userspace-v2.patch added to -mm tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The patch titled
     KVM: Expose MSRs to userspace (v2)
has been added to the -mm tree.  Its filename is
     kvm-expose-msrs-to-userspace-v2.patch

See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find
out what to do about this

------------------------------------------------------
Subject: KVM: Expose MSRs to userspace (v2)
From: Avi Kivity <avi@xxxxxxxxxxxx>

Changes from v1:

 - get msrs and set msrs are now symmetric: both accept a list of msrs. it
   is now possible to retrieve a single msr.
 - a new KVM_GET_MSR_INDEX_LIST allows discovering which msrs are supported
   by kvm (previously this was integrated into KVM_GET_MSRS)
 - error handling is simpler and correcter
 - the implementation is collapsed into a single msr_io() function
 - avoid pointers in ioctl structs, instead use zero length arrays

Signed-off-by: Uri Lublin <uril@xxxxxxxxxxxx>
Signed-off-by: Avi Kivity <avi@xxxxxxxxxxxx>
Signed-off-by: Andrew Morton <akpm@xxxxxxxx>
---

 drivers/kvm/kvm_main.c |  177 +++++++++++++++++----------------------
 include/linux/kvm.h    |   14 +--
 2 files changed, 89 insertions(+), 102 deletions(-)

diff -puN drivers/kvm/kvm_main.c~kvm-expose-msrs-to-userspace-v2 drivers/kvm/kvm_main.c
--- a/drivers/kvm/kvm_main.c~kvm-expose-msrs-to-userspace-v2
+++ a/drivers/kvm/kvm_main.c
@@ -126,6 +126,8 @@ static const u32 vmx_msr_index[] = {
 #define MSR_IA32_VMX_EXIT_CTLS_MSR		0x483
 #define MSR_IA32_VMX_ENTRY_CTLS_MSR		0x484
 
+#define MAX_IO_MSRS 256
+
 #define CR0_RESEVED_BITS 0xffffffff1ffaffc0ULL
 #define LMSW_GUEST_MASK 0x0eULL
 #define CR4_RESEVED_BITS (~((1ULL << 11) - 1))
@@ -3147,7 +3149,7 @@ static int kvm_dev_ioctl_set_sregs(struc
 
 /*
  * List of msr numbers which we expose to userspace through KVM_GET_MSRS
- * and KVM_SET_MSRS.
+ * and KVM_SET_MSRS, and KVM_GET_MSR_INDEX_LIST.
  */
 static u32 msrs_to_save[] = {
 	MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_ESP, MSR_IA32_SYSENTER_EIP,
@@ -3158,110 +3160,91 @@ static u32 msrs_to_save[] = {
 	MSR_IA32_TIME_STAMP_COUNTER,
 };
 
-static int kvm_dev_ioctl_get_msrs(struct kvm *kvm, struct kvm_msrs *msrs)
+
+/*
+ * Adapt set_msr() to msr_io()'s calling convention
+ */
+static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
+{
+	return set_msr(vcpu, index, *data);
+}
+
+/*
+ * Read or write a bunch of msrs. All parameters are kernel addresses.
+ *
+ * @return number of msrs set successfully.
+ */
+static int __msr_io(struct kvm *kvm, struct kvm_msrs *msrs,
+		    struct kvm_msr_entry *entries,
+		    int (*do_msr)(struct kvm_vcpu *vcpu,
+				  unsigned index, u64 *data))
 {
 	struct kvm_vcpu *vcpu;
-	struct kvm_msr_entry *entry, *entries;
-	int rc;
-	u32 size, num_entries, i;
+	int i;
 
 	if (msrs->vcpu < 0 || msrs->vcpu >= KVM_MAX_VCPUS)
 		return -EINVAL;
 
-	num_entries = ARRAY_SIZE(msrs_to_save);
-	if (msrs->nmsrs < num_entries) {
-		/* inform actual number of entries */
-		msrs->nmsrs = num_entries;
-		return -EINVAL;
-	}
-
 	vcpu = vcpu_load(kvm, msrs->vcpu);
 	if (!vcpu)
 		return -ENOENT;
 
-	msrs->nmsrs = num_entries; /* update to actual number of entries */
-	size = msrs->nmsrs * sizeof(struct kvm_msr_entry);
-	rc = -E2BIG;
-	if (size > 4096)
-		goto out_vcpu;
-
-	rc = -ENOMEM;
-	entries = vmalloc(size);
-	if (entries == NULL)
-		goto out_vcpu;
-
-	memset(entries, 0, size);
-	rc = -EINVAL;
-	for (i=0; i<num_entries; i++) {
-		entry = &entries[i];
-		entry->index = msrs_to_save[i];
-		if (get_msr(vcpu, entry->index, &entry->data))
-			goto out_free;
-	}
-
-	rc = -EFAULT;
-	if (copy_to_user(msrs->entries, entries, size))
-		goto out_free;
-
-	rc = 0;
-out_free:
-	vfree(entries);
+	for (i = 0; i < msrs->nmsrs; ++i)
+		if (do_msr(vcpu, entries[i].index, &entries[i].data))
+			break;
 
-out_vcpu:
 	vcpu_put(vcpu);
 
-	return rc;
+	return i;
 }
 
-static int kvm_dev_ioctl_set_msrs(struct kvm *kvm, struct kvm_msrs *msrs)
-{
-	struct kvm_vcpu *vcpu;
-	struct kvm_msr_entry *entry, *entries;
-	int rc;
-	u32 size, num_entries, i;
+/*
+ * Read or write a bunch of msrs. Parameters are user addresses.
+ *
+ * @return number of msrs set successfully.
+ */
+static int msr_io(struct kvm *kvm, struct kvm_msrs __user *user_msrs,
+		  int (*do_msr)(struct kvm_vcpu *vcpu,
+				unsigned index, u64 *data),
+		  int writeback)
+{
+	struct kvm_msrs msrs;
+	struct kvm_msr_entry *entries;
+	int r, n;
+	unsigned size;
 
-	if (msrs->vcpu < 0 || msrs->vcpu >= KVM_MAX_VCPUS)
-		return -EINVAL;
+	r = -EFAULT;
+	if (copy_from_user(&msrs, user_msrs, sizeof msrs))
+		goto out;
 
-	num_entries = ARRAY_SIZE(msrs_to_save);
-	if (msrs->nmsrs < num_entries) {
-		msrs->nmsrs = num_entries; /* inform actual size */
-		return -EINVAL;
-	}
+	r = -E2BIG;
+	if (msrs.nmsrs >= MAX_IO_MSRS)
+		goto out;
 
-	vcpu = vcpu_load(kvm, msrs->vcpu);
-	if (!vcpu)
-		return -ENOENT;
+	r = -ENOMEM;
+	size = sizeof(struct kvm_msr_entry) * msrs.nmsrs;
+	entries = vmalloc(size);
+	if (!entries)
+		goto out;
 
-	size = msrs->nmsrs * sizeof(struct kvm_msr_entry);
-	rc = -E2BIG;
-	if (size > 4096)
-		goto out_vcpu;
+	r = -EFAULT;
+	if (copy_from_user(entries, user_msrs->entries, size))
+		goto out_free;
 
-	rc = -ENOMEM;
-	entries = vmalloc(size);
-	if (entries == NULL)
-		goto out_vcpu;
+	r = n = __msr_io(kvm, &msrs, entries, do_msr);
+	if (r < 0)
+		goto out_free;
 
-	rc = -EFAULT;
-	if (copy_from_user(entries, msrs->entries, size))
+	r = -EFAULT;
+	if (writeback && copy_to_user(user_msrs->entries, entries, size))
 		goto out_free;
 
-	rc = -EINVAL;
-	for (i=0; i<num_entries; i++) {
-		entry = &entries[i];
-		if (set_msr(vcpu, entry->index,  entry->data))
-			goto out_free;
-	}
+	r = n;
 
-	rc = 0;
 out_free:
 	vfree(entries);
-
-out_vcpu:
-	vcpu_put(vcpu);
-
-	return rc;
+out:
+	return r;
 }
 
 /*
@@ -3505,32 +3488,32 @@ static long kvm_dev_ioctl(struct file *f
 			goto out;
 		break;
 	}
-	case KVM_GET_MSRS: {
-		struct kvm_msrs kvm_msrs;
+	case KVM_GET_MSRS:
+		r = msr_io(kvm, (void __user *)arg, get_msr, 1);
+		break;
+	case KVM_SET_MSRS:
+		r = msr_io(kvm, (void __user *)arg, do_set_msr, 0);
+		break;
+	case KVM_GET_MSR_INDEX_LIST: {
+		struct kvm_msr_list __user *user_msr_list = (void __user *)arg;
+		struct kvm_msr_list msr_list;
+		unsigned n;
 
 		r = -EFAULT;
-		if (copy_from_user(&kvm_msrs, (void *)arg, sizeof kvm_msrs))
+		if (copy_from_user(&msr_list, user_msr_list, sizeof msr_list))
 			goto out;
-		r = kvm_dev_ioctl_get_msrs(kvm, &kvm_msrs);
-		if (r)
+		n = msr_list.nmsrs;
+		msr_list.nmsrs = ARRAY_SIZE(msrs_to_save);
+		if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list))
 			goto out;
-		r = -EFAULT;
-		if (copy_to_user((void *)arg, &kvm_msrs, sizeof kvm_msrs))
+		r = -E2BIG;
+		if (n < ARRAY_SIZE(msrs_to_save))
 			goto out;
-		r = 0;
-		break;
-	}
-	case KVM_SET_MSRS: {
-		struct kvm_msrs kvm_msrs;
-
 		r = -EFAULT;
-		if (copy_from_user(&kvm_msrs, (void *)arg, sizeof kvm_msrs))
-			goto out;
-		r = kvm_dev_ioctl_set_msrs(kvm, &kvm_msrs);
-		if (r)
+		if (copy_to_user(user_msr_list->indices, &msrs_to_save,
+				 sizeof msrs_to_save))
 			goto out;
 		r = 0;
-		break;
 	}
 	default:
 		;
diff -puN include/linux/kvm.h~kvm-expose-msrs-to-userspace-v2 include/linux/kvm.h
--- a/include/linux/kvm.h~kvm-expose-msrs-to-userspace-v2
+++ a/include/linux/kvm.h
@@ -152,10 +152,13 @@ struct kvm_msrs {
 	__u32 vcpu;
 	__u32 nmsrs; /* number of msrs in entries */
 
-	union {
-		struct kvm_msr_entry __user *entries;
-		__u64 padding;
-	};
+	struct kvm_msr_entry entries[0];
+};
+
+/* for KVM_GET_MSR_INDEX_LIST */
+struct kvm_msr_list {
+	__u32 nmsrs; /* number of msrs in entries */
+	__u32 indices[0];
 };
 
 /* for KVM_TRANSLATE */
@@ -218,6 +221,7 @@ struct kvm_dirty_log {
 #define KVM_CREATE_VCPU           _IOW(KVMIO, 11, int /* vcpu_slot */)
 #define KVM_GET_DIRTY_LOG         _IOW(KVMIO, 12, struct kvm_dirty_log)
 #define KVM_GET_MSRS              _IOWR(KVMIO, 13, struct kvm_msrs)
-#define KVM_SET_MSRS              _IOW(KVMIO, 14, struct kvm_msrs)
+#define KVM_SET_MSRS              _IOWR(KVMIO, 14, struct kvm_msrs)
+#define KVM_GET_MSR_INDEX_LIST    _IOWR(KVMIO, 15, struct kvm_msr_list)
 
 #endif
_

Patches currently in -mm which might be from avi@xxxxxxxxxxxx are

kvm-userspace-interface.patch
kvm-intel-virtual-mode-extensions-definitions.patch
kvm-kvm-data-structures.patch
kvm-random-accessors-and-constants.patch
kvm-virtualization-infrastructure.patch
kvm-virtualization-infrastructure-kvm-fix-guest-cr4-corruption.patch
kvm-virtualization-infrastructure-include-desch.patch
kvm-virtualization-infrastructure-fix-segment-state-changes-across-processor-mode-switches.patch
kvm-virtualization-infrastructure-fix-asm-constraints-for-segment-loads.patch
kvm-virtualization-infrastructure-fix-mmu-reset-locking-when-setting-cr0.patch
kvm-memory-slot-management.patch
kvm-vcpu-creation-and-maintenance.patch
kvm-vcpu-creation-and-maintenance-segment-access-cleanup.patch
kvm-workaround-cr0cd-cache-disable-bit-leak-from-guest-to.patch
kvm-vcpu-execution-loop.patch
kvm-define-exit-handlers.patch
kvm-define-exit-handlers-pass-fs-gs-segment-bases-to-x86-emulator.patch
kvm-less-common-exit-handlers.patch
kvm-less-common-exit-handlers-handle-rdmsrmsr_efer.patch
kvm-mmu.patch
kvm-x86-emulator.patch
kvm-x86-emulator-fix-emulator-mov-cr-decoding.patch
kvm-plumbing.patch
kvm-dynamically-determine-which-msrs-to-load-and-save.patch
kvm-fix-calculation-of-initial-value-of-rdx-register.patch
kvm-avoid-using-vmx-instruction-directly.patch
kvm-avoid-using-vmx-instruction-directly-fix-asm-constraints.patch
kvm-expose-interrupt-bitmap.patch
kvm-add-time-stamp-counter-msr-and-accessors.patch
kvm-expose-msrs-to-userspace.patch
kvm-expose-msrs-to-userspace-v2.patch

-
To unsubscribe from this list: send the line "unsubscribe mm-commits" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Kernel Newbies FAQ]     [Kernel Archive]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Photo]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]

  Powered by Linux