Commit b9181c8e authored by Like Xu's avatar Like Xu Committed by Paolo Bonzini

KVM: x86/pmu: Avoid exposing Intel BTS feature

The BTS feature (including the ability to set the BTS and BTINT
bits in the DEBUGCTL MSR) is currently unsupported on KVM.

But we may try using the BTS facility on a PEBS enabled guest like this:
    perf record -e branches:u -c 1 -d ls
and then we would encounter the following call trace:

 [] unchecked MSR access error: WRMSR to 0x1d9 (tried to write 0x00000000000003c0)
        at rIP: 0xffffffff810745e4 (native_write_msr+0x4/0x20)
 [] Call Trace:
 []  intel_pmu_enable_bts+0x5d/0x70
 []  bts_event_add+0x54/0x70
 []  event_sched_in+0xee/0x290

As it lacks any CPUID indicator or perf_capabilities valid bit
fields to prompt for this information, the platform would hint
the Intel BTS feature unavailable to guest by setting the
BTS_UNAVAIL bit in the IA32_MISC_ENABLE.
Signed-off-by: default avatarLike Xu <likexu@tencent.com>
Message-Id: <20220601031925.59693-3-likexu@tencent.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent d7808f73
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
#define pmu_to_vcpu(pmu) (container_of((pmu), struct kvm_vcpu, arch.pmu)) #define pmu_to_vcpu(pmu) (container_of((pmu), struct kvm_vcpu, arch.pmu))
#define pmc_to_pmu(pmc) (&(pmc)->vcpu->arch.pmu) #define pmc_to_pmu(pmc) (&(pmc)->vcpu->arch.pmu)
#define MSR_IA32_MISC_ENABLE_PMU_RO_MASK (MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL | \
MSR_IA32_MISC_ENABLE_BTS_UNAVAIL)
/* retrieve the 4 bits for EN and PMI out of IA32_FIXED_CTR_CTRL */ /* retrieve the 4 bits for EN and PMI out of IA32_FIXED_CTR_CTRL */
#define fixed_ctrl_field(ctrl_reg, idx) (((ctrl_reg) >> ((idx)*4)) & 0xf) #define fixed_ctrl_field(ctrl_reg, idx) (((ctrl_reg) >> ((idx)*4)) & 0xf)
......
...@@ -536,6 +536,8 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) ...@@ -536,6 +536,8 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
pmu->pebs_enable_mask = ~0ull; pmu->pebs_enable_mask = ~0ull;
pmu->pebs_data_cfg_mask = ~0ull; pmu->pebs_data_cfg_mask = ~0ull;
vcpu->arch.ia32_misc_enable_msr |= MSR_IA32_MISC_ENABLE_PMU_RO_MASK;
entry = kvm_find_cpuid_entry(vcpu, 0xa, 0); entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
if (!entry || !vcpu->kvm->arch.enable_pmu) if (!entry || !vcpu->kvm->arch.enable_pmu)
return; return;
...@@ -623,7 +625,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) ...@@ -623,7 +625,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
~((1ull << pmu->nr_arch_gp_counters) - 1); ~((1ull << pmu->nr_arch_gp_counters) - 1);
} }
} else { } else {
vcpu->arch.ia32_misc_enable_msr |= MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL;
vcpu->arch.perf_capabilities &= ~PERF_CAP_PEBS_MASK; vcpu->arch.perf_capabilities &= ~PERF_CAP_PEBS_MASK;
} }
} }
......
...@@ -3548,12 +3548,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) ...@@ -3548,12 +3548,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
break; break;
case MSR_IA32_MISC_ENABLE: { case MSR_IA32_MISC_ENABLE: {
u64 old_val = vcpu->arch.ia32_misc_enable_msr; u64 old_val = vcpu->arch.ia32_misc_enable_msr;
u64 pmu_mask = MSR_IA32_MISC_ENABLE_EMON | u64 pmu_mask = MSR_IA32_MISC_ENABLE_PMU_RO_MASK |
MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL; MSR_IA32_MISC_ENABLE_EMON;
/* RO bits */ /* RO bits */
if (!msr_info->host_initiated && if (!msr_info->host_initiated &&
((old_val ^ data) & MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL)) ((old_val ^ data) & MSR_IA32_MISC_ENABLE_PMU_RO_MASK))
return 1; return 1;
/* /*
......
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