Commit 3e26b825 authored by Jinrong Liang's avatar Jinrong Liang Committed by Sean Christopherson

KVM: selftests: Test Intel PMU architectural events on fixed counters

Extend the PMU counters test to validate architectural events using fixed
counters.  The core logic is largely the same, the biggest difference
being that if a fixed counter exists, its associated event is available
(the SDM doesn't explicitly state this to be true, but it's KVM's ABI and
letting software program a fixed counter that doesn't actually count would
be quite bizarre).

Note, fixed counters rely on PERF_GLOBAL_CTRL.
Reviewed-by: default avatarJim Mattson <jmattson@google.com>
Reviewed-by: default avatarDapeng Mi <dapeng1.mi@linux.intel.com>
Co-developed-by: default avatarLike Xu <likexu@tencent.com>
Signed-off-by: default avatarLike Xu <likexu@tencent.com>
Signed-off-by: default avatarJinrong Liang <cloudliang@tencent.com>
Co-developed-by: default avatarSean Christopherson <seanjc@google.com>
Tested-by: default avatarDapeng Mi <dapeng1.mi@linux.intel.com>
Link: https://lore.kernel.org/r/20240109230250.424295-18-seanjc@google.comSigned-off-by: default avatarSean Christopherson <seanjc@google.com>
parent 4f1bd6b1
...@@ -150,26 +150,46 @@ static void __guest_test_arch_event(uint8_t idx, struct kvm_x86_pmu_feature even ...@@ -150,26 +150,46 @@ static void __guest_test_arch_event(uint8_t idx, struct kvm_x86_pmu_feature even
guest_assert_event_count(idx, event, pmc, pmc_msr); guest_assert_event_count(idx, event, pmc, pmc_msr);
} }
#define X86_PMU_FEATURE_NULL \
({ \
struct kvm_x86_pmu_feature feature = {}; \
\
feature; \
})
static bool pmu_is_null_feature(struct kvm_x86_pmu_feature event)
{
return !(*(u64 *)&event);
}
static void guest_test_arch_event(uint8_t idx) static void guest_test_arch_event(uint8_t idx)
{ {
const struct { const struct {
struct kvm_x86_pmu_feature gp_event; struct kvm_x86_pmu_feature gp_event;
struct kvm_x86_pmu_feature fixed_event;
} intel_event_to_feature[] = { } intel_event_to_feature[] = {
[INTEL_ARCH_CPU_CYCLES_INDEX] = { X86_PMU_FEATURE_CPU_CYCLES }, [INTEL_ARCH_CPU_CYCLES_INDEX] = { X86_PMU_FEATURE_CPU_CYCLES, X86_PMU_FEATURE_CPU_CYCLES_FIXED },
[INTEL_ARCH_INSTRUCTIONS_RETIRED_INDEX] = { X86_PMU_FEATURE_INSNS_RETIRED }, [INTEL_ARCH_INSTRUCTIONS_RETIRED_INDEX] = { X86_PMU_FEATURE_INSNS_RETIRED, X86_PMU_FEATURE_INSNS_RETIRED_FIXED },
[INTEL_ARCH_REFERENCE_CYCLES_INDEX] = { X86_PMU_FEATURE_REFERENCE_CYCLES }, /*
[INTEL_ARCH_LLC_REFERENCES_INDEX] = { X86_PMU_FEATURE_LLC_REFERENCES }, * Note, the fixed counter for reference cycles is NOT the same
[INTEL_ARCH_LLC_MISSES_INDEX] = { X86_PMU_FEATURE_LLC_MISSES }, * as the general purpose architectural event. The fixed counter
[INTEL_ARCH_BRANCHES_RETIRED_INDEX] = { X86_PMU_FEATURE_BRANCH_INSNS_RETIRED }, * explicitly counts at the same frequency as the TSC, whereas
[INTEL_ARCH_BRANCHES_MISPREDICTED_INDEX] = { X86_PMU_FEATURE_BRANCHES_MISPREDICTED }, * the GP event counts at a fixed, but uarch specific, frequency.
[INTEL_ARCH_TOPDOWN_SLOTS_INDEX] = { X86_PMU_FEATURE_TOPDOWN_SLOTS }, * Bundle them here for simplicity.
*/
[INTEL_ARCH_REFERENCE_CYCLES_INDEX] = { X86_PMU_FEATURE_REFERENCE_CYCLES, X86_PMU_FEATURE_REFERENCE_TSC_CYCLES_FIXED },
[INTEL_ARCH_LLC_REFERENCES_INDEX] = { X86_PMU_FEATURE_LLC_REFERENCES, X86_PMU_FEATURE_NULL },
[INTEL_ARCH_LLC_MISSES_INDEX] = { X86_PMU_FEATURE_LLC_MISSES, X86_PMU_FEATURE_NULL },
[INTEL_ARCH_BRANCHES_RETIRED_INDEX] = { X86_PMU_FEATURE_BRANCH_INSNS_RETIRED, X86_PMU_FEATURE_NULL },
[INTEL_ARCH_BRANCHES_MISPREDICTED_INDEX] = { X86_PMU_FEATURE_BRANCHES_MISPREDICTED, X86_PMU_FEATURE_NULL },
[INTEL_ARCH_TOPDOWN_SLOTS_INDEX] = { X86_PMU_FEATURE_TOPDOWN_SLOTS, X86_PMU_FEATURE_TOPDOWN_SLOTS_FIXED },
}; };
uint32_t nr_gp_counters = this_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS); uint32_t nr_gp_counters = this_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);
uint32_t pmu_version = guest_get_pmu_version(); uint32_t pmu_version = guest_get_pmu_version();
/* PERF_GLOBAL_CTRL exists only for Architectural PMU Version 2+. */ /* PERF_GLOBAL_CTRL exists only for Architectural PMU Version 2+. */
bool guest_has_perf_global_ctrl = pmu_version >= 2; bool guest_has_perf_global_ctrl = pmu_version >= 2;
struct kvm_x86_pmu_feature gp_event; struct kvm_x86_pmu_feature gp_event, fixed_event;
uint32_t base_pmc_msr; uint32_t base_pmc_msr;
unsigned int i; unsigned int i;
...@@ -199,6 +219,22 @@ static void guest_test_arch_event(uint8_t idx) ...@@ -199,6 +219,22 @@ static void guest_test_arch_event(uint8_t idx)
__guest_test_arch_event(idx, gp_event, i, base_pmc_msr + i, __guest_test_arch_event(idx, gp_event, i, base_pmc_msr + i,
MSR_P6_EVNTSEL0 + i, eventsel); MSR_P6_EVNTSEL0 + i, eventsel);
} }
if (!guest_has_perf_global_ctrl)
return;
fixed_event = intel_event_to_feature[idx].fixed_event;
if (pmu_is_null_feature(fixed_event) || !this_pmu_has(fixed_event))
return;
i = fixed_event.f.bit;
wrmsr(MSR_CORE_PERF_FIXED_CTR_CTRL, FIXED_PMC_CTRL(i, FIXED_PMC_KERNEL));
__guest_test_arch_event(idx, fixed_event, i | INTEL_RDPMC_FIXED,
MSR_CORE_PERF_FIXED_CTR0 + i,
MSR_CORE_PERF_GLOBAL_CTRL,
FIXED_PMC_GLOBAL_CTRL_ENABLE(i));
} }
static void guest_test_arch_events(void) static void guest_test_arch_events(void)
......
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