Commit 1973cadd authored by Vitaly Kuznetsov's avatar Vitaly Kuznetsov Committed by Paolo Bonzini

KVM: x86/vPMU: Forbid writing to MSR_F15H_PERF MSRs when guest doesn't have...

KVM: x86/vPMU: Forbid writing to MSR_F15H_PERF MSRs when guest doesn't have X86_FEATURE_PERFCTR_CORE

MSR_F15H_PERF_CTL0-5, MSR_F15H_PERF_CTR0-5 MSRs are only available when
X86_FEATURE_PERFCTR_CORE CPUID bit was exposed to the guest. KVM, however,
allows these MSRs unconditionally because kvm_pmu_is_valid_msr() ->
amd_msr_idx_to_pmc() check always passes and because kvm_pmu_set_msr() ->
amd_pmu_set_msr() doesn't fail.

In case of a counter (CTRn), no big harm is done as we only increase
internal PMC's value but in case of an eventsel (CTLn), we go deep into
perf internals with a non-existing counter.

Note, kvm_get_msr_common() just returns '0' when these MSRs don't exist
and this also seems to contradict architectural behavior which is #GP
(I did check one old Opteron host) but changing this status quo is a bit
scarier.
Signed-off-by: default avatarVitaly Kuznetsov <vkuznets@redhat.com>
Message-Id: <20210323084515.1346540-1-vkuznets@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent ecaf088f
...@@ -98,6 +98,8 @@ static enum index msr_to_index(u32 msr) ...@@ -98,6 +98,8 @@ static enum index msr_to_index(u32 msr)
static inline struct kvm_pmc *get_gp_pmc_amd(struct kvm_pmu *pmu, u32 msr, static inline struct kvm_pmc *get_gp_pmc_amd(struct kvm_pmu *pmu, u32 msr,
enum pmu_type type) enum pmu_type type)
{ {
struct kvm_vcpu *vcpu = pmu_to_vcpu(pmu);
switch (msr) { switch (msr) {
case MSR_F15H_PERF_CTL0: case MSR_F15H_PERF_CTL0:
case MSR_F15H_PERF_CTL1: case MSR_F15H_PERF_CTL1:
...@@ -105,6 +107,9 @@ static inline struct kvm_pmc *get_gp_pmc_amd(struct kvm_pmu *pmu, u32 msr, ...@@ -105,6 +107,9 @@ static inline struct kvm_pmc *get_gp_pmc_amd(struct kvm_pmu *pmu, u32 msr,
case MSR_F15H_PERF_CTL3: case MSR_F15H_PERF_CTL3:
case MSR_F15H_PERF_CTL4: case MSR_F15H_PERF_CTL4:
case MSR_F15H_PERF_CTL5: case MSR_F15H_PERF_CTL5:
if (!guest_cpuid_has(vcpu, X86_FEATURE_PERFCTR_CORE))
return NULL;
fallthrough;
case MSR_K7_EVNTSEL0 ... MSR_K7_EVNTSEL3: case MSR_K7_EVNTSEL0 ... MSR_K7_EVNTSEL3:
if (type != PMU_TYPE_EVNTSEL) if (type != PMU_TYPE_EVNTSEL)
return NULL; return NULL;
...@@ -115,6 +120,9 @@ static inline struct kvm_pmc *get_gp_pmc_amd(struct kvm_pmu *pmu, u32 msr, ...@@ -115,6 +120,9 @@ static inline struct kvm_pmc *get_gp_pmc_amd(struct kvm_pmu *pmu, u32 msr,
case MSR_F15H_PERF_CTR3: case MSR_F15H_PERF_CTR3:
case MSR_F15H_PERF_CTR4: case MSR_F15H_PERF_CTR4:
case MSR_F15H_PERF_CTR5: case MSR_F15H_PERF_CTR5:
if (!guest_cpuid_has(vcpu, X86_FEATURE_PERFCTR_CORE))
return NULL;
fallthrough;
case MSR_K7_PERFCTR0 ... MSR_K7_PERFCTR3: case MSR_K7_PERFCTR0 ... MSR_K7_PERFCTR3:
if (type != PMU_TYPE_COUNTER) if (type != PMU_TYPE_COUNTER)
return NULL; return NULL;
......
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