mirror of
https://github.com/torvalds/linux.git
synced 2024-11-29 15:41:36 +00:00
KVM: x86/pmu: Provide "error" semantics for unsupported-but-known PMU MSRs
Provide "error" semantics (read zeros, drop writes) for userspace accesses to MSRs that are ultimately unsupported for whatever reason, but for which KVM told userspace to save and restore the MSR, i.e. for MSRs that KVM included in KVM_GET_MSR_INDEX_LIST. Previously, KVM special cased a few PMU MSRs that were problematic at one point or another. Extend the treatment to all PMU MSRs, e.g. to avoid spurious unsupported accesses. Note, the logic can also be used for non-PMU MSRs, but as of today only PMU MSRs can end up being unsupported after KVM told userspace to save and restore them. Link: https://lore.kernel.org/r/20230124234905.3774678-7-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
parent
e33b6d79ac
commit
2de154f541
@ -3561,6 +3561,18 @@ static void record_steal_time(struct kvm_vcpu *vcpu)
|
||||
mark_page_dirty_in_slot(vcpu->kvm, ghc->memslot, gpa_to_gfn(ghc->gpa));
|
||||
}
|
||||
|
||||
static bool kvm_is_msr_to_save(u32 msr_index)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < num_msrs_to_save; i++) {
|
||||
if (msrs_to_save[i] == msr_index)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||
{
|
||||
u32 msr = msr_info->index;
|
||||
@ -3876,20 +3888,18 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||
vcpu->arch.guest_fpu.xfd_err = data;
|
||||
break;
|
||||
#endif
|
||||
case MSR_IA32_PEBS_ENABLE:
|
||||
case MSR_IA32_DS_AREA:
|
||||
case MSR_PEBS_DATA_CFG:
|
||||
case MSR_F15H_PERF_CTL0 ... MSR_F15H_PERF_CTR5:
|
||||
default:
|
||||
if (kvm_pmu_is_valid_msr(vcpu, msr))
|
||||
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.
|
||||
*/
|
||||
return !msr_info->host_initiated || data;
|
||||
default:
|
||||
if (kvm_pmu_is_valid_msr(vcpu, msr))
|
||||
return kvm_pmu_set_msr(vcpu, msr_info);
|
||||
if (msr_info->host_initiated && !data &&
|
||||
kvm_is_msr_to_save(msr))
|
||||
break;
|
||||
|
||||
return KVM_MSR_RET_INVALID;
|
||||
}
|
||||
return 0;
|
||||
@ -3979,20 +3989,6 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||
case MSR_DRAM_ENERGY_STATUS: /* DRAM controller */
|
||||
msr_info->data = 0;
|
||||
break;
|
||||
case MSR_IA32_PEBS_ENABLE:
|
||||
case MSR_IA32_DS_AREA:
|
||||
case MSR_PEBS_DATA_CFG:
|
||||
case MSR_F15H_PERF_CTL0 ... MSR_F15H_PERF_CTR5:
|
||||
if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
|
||||
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)
|
||||
return 1;
|
||||
msr_info->data = 0;
|
||||
break;
|
||||
case MSR_K7_EVNTSEL0 ... MSR_K7_EVNTSEL3:
|
||||
case MSR_K7_PERFCTR0 ... MSR_K7_PERFCTR3:
|
||||
case MSR_P6_PERFCTR0 ... MSR_P6_PERFCTR1:
|
||||
@ -4248,6 +4244,17 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||
default:
|
||||
if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
|
||||
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_INVALID;
|
||||
}
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user