Commit 64a5d7a1 authored by Sean Christopherson's avatar Sean Christopherson

KVM: x86: Suppress failures on userspace access to advertised, unsupported MSRs

Extend KVM's suppression of failures due to a userspace access to an
unsupported, but advertised as a "to save" MSR to all MSRs, not just those
that happen to reach the default case statements in kvm_get_msr_common()
and kvm_set_msr_common().  KVM's soon-to-be-established ABI is that if an
MSR is advertised to userspace, then userspace is allowed to read the MSR,
and write back the value that was read, i.e. why an MSR is unsupported
doesn't change KVM's ABI.

Practically speaking, this is very nearly a nop, as the only other paths
that return KVM_MSR_RET_UNSUPPORTED are {svm,vmx}_get_feature_msr(), and
it's unlikely, though not impossible, that userspace is using KVM_GET_MSRS
on unsupported MSRs.

The primary goal of moving the suppression to common code is to allow
returning KVM_MSR_RET_UNSUPPORTED as appropriate throughout KVM, without
having to manually handle the "is userspace accessing an advertised"
waiver.  I.e. this will allow formalizing KVM's ABI without incurring a
high maintenance cost.

Link: https://lore.kernel.org/r/20240802181935.292540-10-seanjc@google.comSigned-off-by: default avatarSean Christopherson <seanjc@google.com>
parent 3adef903
...@@ -512,6 +512,15 @@ static __always_inline int kvm_do_msr_access(struct kvm_vcpu *vcpu, u32 msr, ...@@ -512,6 +512,15 @@ static __always_inline int kvm_do_msr_access(struct kvm_vcpu *vcpu, u32 msr,
if (ret != KVM_MSR_RET_UNSUPPORTED) if (ret != KVM_MSR_RET_UNSUPPORTED)
return ret; return ret;
/*
* Userspace is allowed to read MSRs, and write '0' to MSRs, that KVM
* reports as to-be-saved, even if an MSR isn't fully supported.
* Simply check that @data is '0', which covers both the write '0' case
* and all reads (in which case @data is zeroed on failure; see above).
*/
if (host_initiated && !*data && kvm_is_msr_to_save(msr))
return 0;
if (!ignore_msrs) { if (!ignore_msrs) {
kvm_debug_ratelimited("unhandled %s: 0x%x data 0x%llx\n", kvm_debug_ratelimited("unhandled %s: 0x%x data 0x%llx\n",
op, msr, *data); op, msr, *data);
...@@ -4137,14 +4146,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) ...@@ -4137,14 +4146,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
if (kvm_pmu_is_valid_msr(vcpu, msr)) if (kvm_pmu_is_valid_msr(vcpu, msr))
return kvm_pmu_set_msr(vcpu, msr_info); return kvm_pmu_set_msr(vcpu, msr_info);
/*
* Userspace is allowed to write '0' to MSRs that KVM reports
* as to-be-saved, even if an MSRs isn't fully supported.
*/
if (msr_info->host_initiated && !data &&
kvm_is_msr_to_save(msr))
break;
return KVM_MSR_RET_UNSUPPORTED; return KVM_MSR_RET_UNSUPPORTED;
} }
return 0; return 0;
...@@ -4496,16 +4497,6 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) ...@@ -4496,16 +4497,6 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
if (kvm_pmu_is_valid_msr(vcpu, msr_info->index)) if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
return kvm_pmu_get_msr(vcpu, msr_info); return kvm_pmu_get_msr(vcpu, msr_info);
/*
* Userspace is allowed to read MSRs that KVM reports as
* to-be-saved, even if an MSR isn't fully supported.
*/
if (msr_info->host_initiated &&
kvm_is_msr_to_save(msr_info->index)) {
msr_info->data = 0;
break;
}
return KVM_MSR_RET_UNSUPPORTED; return KVM_MSR_RET_UNSUPPORTED;
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment