/*
  * When called, it means the previous get/set msr reached an invalid msr.
- * Return 0 if we want to ignore/silent this failed msr access, or 1 if we want
- * to fail the caller.
+ * Return true if we want to ignore/silent this failed msr access.
  */
-static int kvm_msr_ignored_check(struct kvm_vcpu *vcpu, u32 msr,
-                                u64 data, bool write)
+static bool kvm_msr_ignored_check(struct kvm_vcpu *vcpu, u32 msr,
+                                 u64 data, bool write)
 {
        const char *op = write ? "wrmsr" : "rdmsr";
 
                        kvm_pr_unimpl("ignored %s: 0x%x data 0x%llx\n",
                                      op, msr, data);
                /* Mask the error */
-               return 0;
+               return true;
        } else {
                kvm_debug_ratelimited("unhandled %s: 0x%x data 0x%llx\n",
                                      op, msr, data);
-               return -ENOENT;
+               return false;
        }
 }
 
        if (r == KVM_MSR_RET_INVALID) {
                /* Unconditionally clear the output for simplicity */
                *data = 0;
-               r = kvm_msr_ignored_check(vcpu, index, 0, false);
+               if (kvm_msr_ignored_check(vcpu, index, 0, false))
+                       r = 0;
        }
 
        if (r)
        struct msr_data msr;
 
        if (!host_initiated && !kvm_msr_allowed(vcpu, index, KVM_MSR_FILTER_WRITE))
-               return -EPERM;
+               return KVM_MSR_RET_FILTERED;
 
        switch (index) {
        case MSR_FS_BASE:
        int ret = __kvm_set_msr(vcpu, index, data, host_initiated);
 
        if (ret == KVM_MSR_RET_INVALID)
-               ret = kvm_msr_ignored_check(vcpu, index, data, true);
+               if (kvm_msr_ignored_check(vcpu, index, data, true))
+                       ret = 0;
 
        return ret;
 }
        int ret;
 
        if (!host_initiated && !kvm_msr_allowed(vcpu, index, KVM_MSR_FILTER_READ))
-               return -EPERM;
+               return KVM_MSR_RET_FILTERED;
 
        msr.index = index;
        msr.host_initiated = host_initiated;
        if (ret == KVM_MSR_RET_INVALID) {
                /* Unconditionally clear *data for simplicity */
                *data = 0;
-               ret = kvm_msr_ignored_check(vcpu, index, 0, false);
+               if (kvm_msr_ignored_check(vcpu, index, 0, false))
+                       ret = 0;
        }
 
        return ret;
 static u64 kvm_msr_reason(int r)
 {
        switch (r) {
-       case -ENOENT:
+       case KVM_MSR_RET_INVALID:
                return KVM_MSR_EXIT_REASON_UNKNOWN;
-       case -EPERM:
+       case KVM_MSR_RET_FILTERED:
                return KVM_MSR_EXIT_REASON_FILTER;
        default:
                return KVM_MSR_EXIT_REASON_INVAL;
 
 int kvm_handle_invpcid(struct kvm_vcpu *vcpu, unsigned long type, gva_t gva);
 bool kvm_msr_allowed(struct kvm_vcpu *vcpu, u32 index, u32 type);
 
-#define  KVM_MSR_RET_INVALID  2
+/*
+ * Internal error codes that are used to indicate that MSR emulation encountered
+ * an error that should result in #GP in the guest, unless userspace
+ * handles it.
+ */
+#define  KVM_MSR_RET_INVALID   2       /* in-kernel MSR emulation #GP condition */
+#define  KVM_MSR_RET_FILTERED  3       /* #GP due to userspace MSR filter */
 
 #define __cr4_reserved_bits(__cpu_has, __c)             \
 ({                                                      \