Skip to content

Commit 370d536

Browse files
committed
KVM: selftests: Extend {kvm,this}_pmu_has() to support fixed counters
Extend the kvm_x86_pmu_feature framework to allow querying for fixed counters via {kvm,this}_pmu_has(). Like architectural events, checking for a fixed counter annoyingly requires checking multiple CPUID fields, as a fixed counter exists if: FxCtr[i]_is_supported := ECX[i] || (EDX[4:0] > i); Note, KVM currently doesn't actually support exposing fixed counters via the bitmask, but that will hopefully change sooner than later, and Intel's SDM explicitly "recommends" checking both the number of counters and the mask. Rename the intermedate "anti_feature" field to simply 'f' since the fixed counter bitmask (thankfully) doesn't have reversed polarity like the architectural events bitmask. Note, ideally the helpers would use BUILD_BUG_ON() to assert on the incoming register, but the expected usage in PMU tests can't guarantee the inputs are compile-time constants. Opportunistically define macros for all of the known architectural events and fixed counters. Tested-by: Dapeng Mi <dapeng1.mi@linux.intel.com> Link: https://lore.kernel.org/r/20240109230250.424295-15-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent ff76d77 commit 370d536

File tree

1 file changed

+47
-18
lines changed

1 file changed

+47
-18
lines changed

tools/testing/selftests/kvm/include/x86_64/processor.h

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -282,24 +282,41 @@ struct kvm_x86_cpu_property {
282282
* that indicates the feature is _not_ supported, and a property that states
283283
* the length of the bit mask of unsupported features. A feature is supported
284284
* if the size of the bit mask is larger than the "unavailable" bit, and said
285-
* bit is not set.
285+
* bit is not set. Fixed counters also bizarre enumeration, but inverted from
286+
* arch events for general purpose counters. Fixed counters are supported if a
287+
* feature flag is set **OR** the total number of fixed counters is greater
288+
* than index of the counter.
286289
*
287-
* Wrap the "unavailable" feature to simplify checking whether or not a given
288-
* architectural event is supported.
290+
* Wrap the events for general purpose and fixed counters to simplify checking
291+
* whether or not a given architectural event is supported.
289292
*/
290293
struct kvm_x86_pmu_feature {
291-
struct kvm_x86_cpu_feature anti_feature;
294+
struct kvm_x86_cpu_feature f;
292295
};
293-
#define KVM_X86_PMU_FEATURE(__bit) \
294-
({ \
295-
struct kvm_x86_pmu_feature feature = { \
296-
.anti_feature = KVM_X86_CPU_FEATURE(0xa, 0, EBX, __bit), \
297-
}; \
298-
\
299-
feature; \
296+
#define KVM_X86_PMU_FEATURE(__reg, __bit) \
297+
({ \
298+
struct kvm_x86_pmu_feature feature = { \
299+
.f = KVM_X86_CPU_FEATURE(0xa, 0, __reg, __bit), \
300+
}; \
301+
\
302+
kvm_static_assert(KVM_CPUID_##__reg == KVM_CPUID_EBX || \
303+
KVM_CPUID_##__reg == KVM_CPUID_ECX); \
304+
feature; \
300305
})
301306

302-
#define X86_PMU_FEATURE_BRANCH_INSNS_RETIRED KVM_X86_PMU_FEATURE(5)
307+
#define X86_PMU_FEATURE_CPU_CYCLES KVM_X86_PMU_FEATURE(EBX, 0)
308+
#define X86_PMU_FEATURE_INSNS_RETIRED KVM_X86_PMU_FEATURE(EBX, 1)
309+
#define X86_PMU_FEATURE_REFERENCE_CYCLES KVM_X86_PMU_FEATURE(EBX, 2)
310+
#define X86_PMU_FEATURE_LLC_REFERENCES KVM_X86_PMU_FEATURE(EBX, 3)
311+
#define X86_PMU_FEATURE_LLC_MISSES KVM_X86_PMU_FEATURE(EBX, 4)
312+
#define X86_PMU_FEATURE_BRANCH_INSNS_RETIRED KVM_X86_PMU_FEATURE(EBX, 5)
313+
#define X86_PMU_FEATURE_BRANCHES_MISPREDICTED KVM_X86_PMU_FEATURE(EBX, 6)
314+
#define X86_PMU_FEATURE_TOPDOWN_SLOTS KVM_X86_PMU_FEATURE(EBX, 7)
315+
316+
#define X86_PMU_FEATURE_INSNS_RETIRED_FIXED KVM_X86_PMU_FEATURE(ECX, 0)
317+
#define X86_PMU_FEATURE_CPU_CYCLES_FIXED KVM_X86_PMU_FEATURE(ECX, 1)
318+
#define X86_PMU_FEATURE_REFERENCE_TSC_CYCLES_FIXED KVM_X86_PMU_FEATURE(ECX, 2)
319+
#define X86_PMU_FEATURE_TOPDOWN_SLOTS_FIXED KVM_X86_PMU_FEATURE(ECX, 3)
303320

304321
static inline unsigned int x86_family(unsigned int eax)
305322
{
@@ -698,10 +715,16 @@ static __always_inline bool this_cpu_has_p(struct kvm_x86_cpu_property property)
698715

699716
static inline bool this_pmu_has(struct kvm_x86_pmu_feature feature)
700717
{
701-
uint32_t nr_bits = this_cpu_property(X86_PROPERTY_PMU_EBX_BIT_VECTOR_LENGTH);
718+
uint32_t nr_bits;
719+
720+
if (feature.f.reg == KVM_CPUID_EBX) {
721+
nr_bits = this_cpu_property(X86_PROPERTY_PMU_EBX_BIT_VECTOR_LENGTH);
722+
return nr_bits > feature.f.bit && !this_cpu_has(feature.f);
723+
}
702724

703-
return nr_bits > feature.anti_feature.bit &&
704-
!this_cpu_has(feature.anti_feature);
725+
GUEST_ASSERT(feature.f.reg == KVM_CPUID_ECX);
726+
nr_bits = this_cpu_property(X86_PROPERTY_PMU_NR_FIXED_COUNTERS);
727+
return nr_bits > feature.f.bit || this_cpu_has(feature.f);
705728
}
706729

707730
static __always_inline uint64_t this_cpu_supported_xcr0(void)
@@ -917,10 +940,16 @@ static __always_inline bool kvm_cpu_has_p(struct kvm_x86_cpu_property property)
917940

918941
static inline bool kvm_pmu_has(struct kvm_x86_pmu_feature feature)
919942
{
920-
uint32_t nr_bits = kvm_cpu_property(X86_PROPERTY_PMU_EBX_BIT_VECTOR_LENGTH);
943+
uint32_t nr_bits;
944+
945+
if (feature.f.reg == KVM_CPUID_EBX) {
946+
nr_bits = kvm_cpu_property(X86_PROPERTY_PMU_EBX_BIT_VECTOR_LENGTH);
947+
return nr_bits > feature.f.bit && !kvm_cpu_has(feature.f);
948+
}
921949

922-
return nr_bits > feature.anti_feature.bit &&
923-
!kvm_cpu_has(feature.anti_feature);
950+
TEST_ASSERT_EQ(feature.f.reg, KVM_CPUID_ECX);
951+
nr_bits = kvm_cpu_property(X86_PROPERTY_PMU_NR_FIXED_COUNTERS);
952+
return nr_bits > feature.f.bit || kvm_cpu_has(feature.f);
924953
}
925954

926955
static __always_inline uint64_t kvm_cpu_supported_xcr0(void)

0 commit comments

Comments
 (0)