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@xxxxxxxxxx> Reviewed-by: Jim Mattson <jmattson@xxxxxxxxxx> --- 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 --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; -- 2.19.0.rc0.228.g281dcd1b4d0-goog