| From 3f49bf6fab36572bb345db5c6980a806d9f0dde1 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 7 Mar 2022 17:24:52 -0800 |
| Subject: KVM: x86/pmu: Use different raw event masks for AMD and Intel |
| |
| From: Jim Mattson <jmattson@google.com> |
| |
| [ Upstream commit 95b065bf5c431c06c68056a03a5853b660640ecc ] |
| |
| The third nybble of AMD's event select overlaps with Intel's IN_TX and |
| IN_TXCP bits. Therefore, we can't use AMD64_RAW_EVENT_MASK on Intel |
| platforms that support TSX. |
| |
| Declare a raw_event_mask in the kvm_pmu structure, initialize it in |
| the vendor-specific pmu_refresh() functions, and use that mask for |
| PERF_TYPE_RAW configurations in reprogram_gp_counter(). |
| |
| Fixes: 710c47651431 ("KVM: x86/pmu: Use AMD64_RAW_EVENT_MASK for PERF_TYPE_RAW") |
| Signed-off-by: Jim Mattson <jmattson@google.com> |
| Message-Id: <20220308012452.3468611-1-jmattson@google.com> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| arch/x86/include/asm/kvm_host.h | 1 + |
| arch/x86/kvm/pmu.c | 3 ++- |
| arch/x86/kvm/svm/pmu.c | 1 + |
| arch/x86/kvm/vmx/pmu_intel.c | 1 + |
| 4 files changed, 5 insertions(+), 1 deletion(-) |
| |
| diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h |
| index 5d3645b325e2..92c119831ed4 100644 |
| --- a/arch/x86/include/asm/kvm_host.h |
| +++ b/arch/x86/include/asm/kvm_host.h |
| @@ -503,6 +503,7 @@ struct kvm_pmu { |
| u64 global_ctrl_mask; |
| u64 global_ovf_ctrl_mask; |
| u64 reserved_bits; |
| + u64 raw_event_mask; |
| u8 version; |
| struct kvm_pmc gp_counters[INTEL_PMC_MAX_GENERIC]; |
| struct kvm_pmc fixed_counters[INTEL_PMC_MAX_FIXED]; |
| diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c |
| index de955ca58d17..255ef63a4354 100644 |
| --- a/arch/x86/kvm/pmu.c |
| +++ b/arch/x86/kvm/pmu.c |
| @@ -178,6 +178,7 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel) |
| struct kvm *kvm = pmc->vcpu->kvm; |
| struct kvm_pmu_event_filter *filter; |
| int i; |
| + struct kvm_pmu *pmu = vcpu_to_pmu(pmc->vcpu); |
| bool allow_event = true; |
| |
| if (eventsel & ARCH_PERFMON_EVENTSEL_PIN_CONTROL) |
| @@ -217,7 +218,7 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel) |
| } |
| |
| if (type == PERF_TYPE_RAW) |
| - config = eventsel & AMD64_RAW_EVENT_MASK; |
| + config = eventsel & pmu->raw_event_mask; |
| |
| if (pmc->current_config == eventsel && pmc_resume_counter(pmc)) |
| return; |
| diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c |
| index 7fadfe3c67e7..04e483471dbb 100644 |
| --- a/arch/x86/kvm/svm/pmu.c |
| +++ b/arch/x86/kvm/svm/pmu.c |
| @@ -282,6 +282,7 @@ static void amd_pmu_refresh(struct kvm_vcpu *vcpu) |
| |
| pmu->counter_bitmask[KVM_PMC_GP] = ((u64)1 << 48) - 1; |
| pmu->reserved_bits = 0xfffffff000280000ull; |
| + pmu->raw_event_mask = AMD64_RAW_EVENT_MASK; |
| pmu->version = 1; |
| /* not applicable to AMD; but clean them to prevent any fall out */ |
| pmu->counter_bitmask[KVM_PMC_FIXED] = 0; |
| diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c |
| index 60563a45f3eb..9e380a939c72 100644 |
| --- a/arch/x86/kvm/vmx/pmu_intel.c |
| +++ b/arch/x86/kvm/vmx/pmu_intel.c |
| @@ -476,6 +476,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) |
| pmu->counter_bitmask[KVM_PMC_FIXED] = 0; |
| pmu->version = 0; |
| pmu->reserved_bits = 0xffffffff00200000ull; |
| + pmu->raw_event_mask = X86_RAW_EVENT_MASK; |
| |
| entry = kvm_find_cpuid_entry(vcpu, 0xa, 0); |
| if (!entry) |
| -- |
| 2.35.1 |
| |