From: Dapeng Mi On PerfMon v5, CPUID.0AH:ECX represents the fixed counter bitmask, while EDX[4:0] represents the number of contiguous fixed counters starting from 0. pmu_counters_test does not correctly set up these two fixed counter fields. For example, it may set EDX[4:0] to 0x0 while setting ECX to 0x1. It assumes that fixed counter 0 is available by checking: FxCtr[i]_is_supported := ECX[i] || (EDX[4:0] > i). However, this is an invalid setup because EDX[4:0] should not be zero when the number of contiguous fixed counters is 1. Correct the setting of EDX[4:0] when the fixed counter bitmask is present, and also handle the non-contiguous fixed counter case. Signed-off-by: Dapeng Mi Co-developed-by: Zide Chen Signed-off-by: Zide Chen --- .../selftests/kvm/x86/pmu_counters_test.c | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/kvm/x86/pmu_counters_test.c b/tools/testing/selftests/kvm/x86/pmu_counters_test.c index 38057754e024..6f38a35a4ea7 100644 --- a/tools/testing/selftests/kvm/x86/pmu_counters_test.c +++ b/tools/testing/selftests/kvm/x86/pmu_counters_test.c @@ -3,6 +3,7 @@ * Copyright (C) 2023, Tencent, Inc. */ #include +#include #include "pmu.h" #include "processor.h" @@ -659,6 +660,8 @@ static void test_intel_counters(void) u8 nr_gp_counters = kvm_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS); u8 pmu_version = kvm_cpu_property(X86_PROPERTY_PMU_VERSION); u64 advertised_perf_caps = kvm_get_feature_msr(MSR_IA32_PERF_CAPABILITIES); + unsigned long fixed_subset; + u32 fixed_bitmap = 0; unsigned int i; u8 v, j; u32 k; @@ -696,6 +699,12 @@ static void test_intel_counters(void) */ u8 max_pmu_version = max_t(typeof(pmu_version), pmu_version, 5); + if (nr_fixed_counters) + fixed_bitmap = GENMASK(nr_fixed_counters - 1, 0); + + if (pmu_version > 4) + fixed_bitmap |= kvm_cpu_property(X86_PROPERTY_PMU_FIXED_COUNTERS_BITMASK); + /* * Detect the existence of events that aren't supported by selftests. * This will (obviously) fail any time hardware adds support for a new @@ -750,9 +759,19 @@ static void test_intel_counters(void) pr_info("Testing fixed counters, PMU version %u, perf_caps = %lx\n", v, perf_caps[i]); - for (j = 0; j <= nr_fixed_counters; j++) { - for (k = 0; k <= (BIT(nr_fixed_counters) - 1); k++) - test_fixed_counters(v, perf_caps[i], j, k); + for (fixed_subset = 0; fixed_subset <= fixed_bitmap; fixed_subset++) { + u32 nr_contiguous; + + /* + * The loop walks all values from 0 to fixed_bitmap, so skip any + * value that is not a true subset of fixed_bitmap. + */ + if (fixed_subset & ~fixed_bitmap) + continue; + + nr_contiguous = find_first_zero_bit(&fixed_subset, + MAX_NR_FIXED_COUNTERS); + test_fixed_counters(v, perf_caps[i], nr_contiguous, fixed_subset); } pr_info("Testing Perf Metrics, PMU version %u, perf_caps = %lx\n", -- 2.54.0