diff mbox series

[1/2] kvm: x86: propagate KVM_GET/SET_MSRS failures to userspace

Message ID 20180829234241.103002-2-pshier@google.com (mailing list archive)
State New, archived
Headers show
Series Propagate accurate MSR access failures to userspace | expand

Commit Message

Peter Shier Aug. 29, 2018, 11:42 p.m. UTC
These IOCTLs return the number of MSRS successfully read/written but lose
error info in case of failure. Rename kvm_msrs.pad to kvm_msrs.errno and
use it to return cause of first failure.

Signed-off-by: Peter Shier <pshier@google.com>
Reviewed-by: Jim Mattson <jmattson@google.com>
---
 Documentation/virtual/kvm/api.txt | 12 +++++++++---
 arch/x86/include/uapi/asm/kvm.h   |  2 +-
 arch/x86/kvm/x86.c                | 26 +++++++++++++++++---------
 3 files changed, 27 insertions(+), 13 deletions(-)
diff mbox series

Patch

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index c664064f76fb6..b9b86e6727448 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -487,7 +487,7 @@  Capability: basic (vcpu), KVM_CAP_GET_MSR_FEATURES (system)
 Architectures: x86
 Type: system ioctl, vcpu ioctl
 Parameters: struct kvm_msrs (in/out)
-Returns: number of msrs successfully returned;
+Returns: number of msrs successfully read;
         -1 on error
 
 When used as a system ioctl:
@@ -500,9 +500,12 @@  When used as a vcpu ioctl:
 Reads model-specific registers from the vcpu.  Supported msr indices can
 be obtained using KVM_GET_MSR_INDEX_LIST in a system ioctl.
 
+If return value is non-negative and < kvm_msrs.nmsrs, then kvm_msrs.errno
+contains a (positive) value from errno.h for first MSR access that failed.
+
 struct kvm_msrs {
 	__u32 nmsrs; /* number of msrs in entries */
-	__u32 pad;
+	__u32 errno; /* error from 1st failed MSR access */
 
 	struct kvm_msr_entry entries[0];
 };
@@ -524,7 +527,8 @@  Capability: basic
 Architectures: x86
 Type: vcpu ioctl
 Parameters: struct kvm_msrs (in)
-Returns: 0 on success, -1 on error
+Returns: number of msrs successfully written;
+        -1 on error
 
 Writes model-specific registers to the vcpu.  See KVM_GET_MSRS for the
 data structures.
@@ -533,6 +537,8 @@  Application code should set the 'nmsrs' member (which indicates the
 size of the entries array), and the 'index' and 'data' members of each
 array entry.
 
+If return value is non-negative and < kvm_msrs.nmsrs, then kvm_msrs.errno
+contains a (positive) value from errno.h for first MSR access that failed.
 
 4.20 KVM_SET_CPUID
 
diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
index 86299efa804ad..c3783a059adf7 100644
--- a/arch/x86/include/uapi/asm/kvm.h
+++ b/arch/x86/include/uapi/asm/kvm.h
@@ -181,7 +181,7 @@  struct kvm_msr_entry {
 /* for KVM_GET_MSRS and KVM_SET_MSRS */
 struct kvm_msrs {
 	__u32 nmsrs; /* number of msrs in entries */
-	__u32 pad;
+	__u32 errno; /* error from 1st failed MSR access */
 
 	struct kvm_msr_entry entries[0];
 };
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 506bd2b4b8bb7..7d6ab722650e4 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2209,10 +2209,10 @@  static int set_msr_mce(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 			 */
 			if ((offset & 0x3) == 0 &&
 			    data != 0 && (data | (1 << 10)) != ~(u64)0)
-				return -1;
+				return 1;
 			if (!msr_info->host_initiated &&
 				(offset & 0x3) == 1 && data != 0)
-				return -1;
+				return 1;
 			vcpu->arch.mce_banks[offset] = data;
 			break;
 		}
@@ -2807,18 +2807,23 @@  EXPORT_SYMBOL_GPL(kvm_get_msr_common);
 /*
  * Read or write a bunch of msrs. All parameters are kernel addresses.
  *
- * @return number of msrs set successfully.
+ * @return number of msrs accessed successfully.
  */
 static int __msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs *msrs,
 		    struct kvm_msr_entry *entries,
 		    int (*do_msr)(struct kvm_vcpu *vcpu,
 				  unsigned index, u64 *data))
 {
-	int i;
+	int i, r;
 
-	for (i = 0; i < msrs->nmsrs; ++i)
-		if (do_msr(vcpu, entries[i].index, &entries[i].data))
+	for (i = 0; i < msrs->nmsrs; ++i) {
+		r = do_msr(vcpu, entries[i].index, &entries[i].data);
+		if (r) {
+			/* Convert non-standard returns to generic error */
+			msrs->errno = r > 0 ? EINVAL : -r;
 			break;
+		}
+	}
 
 	return i;
 }
@@ -2853,11 +2858,14 @@  static int msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs __user *user_msrs,
 		goto out;
 	}
 
-	r = n = __msr_io(vcpu, &msrs, entries, do_msr);
-	if (r < 0)
-		goto out_free;
+	msrs.errno = 0;
+	n = __msr_io(vcpu, &msrs, entries, do_msr);
 
 	r = -EFAULT;
+	if (copy_to_user(&user_msrs->errno, &msrs.errno,
+			 sizeof user_msrs->errno))
+		goto out_free;
+
 	if (writeback && copy_to_user(user_msrs->entries, entries, size))
 		goto out_free;