xref: /linux/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
14f1bd6b1SJinrong Liang // SPDX-License-Identifier: GPL-2.0
24f1bd6b1SJinrong Liang /*
34f1bd6b1SJinrong Liang  * Copyright (C) 2023, Tencent, Inc.
44f1bd6b1SJinrong Liang  */
54f1bd6b1SJinrong Liang #include <x86intrin.h>
64f1bd6b1SJinrong Liang 
74f1bd6b1SJinrong Liang #include "pmu.h"
84f1bd6b1SJinrong Liang #include "processor.h"
94f1bd6b1SJinrong Liang 
105bb9af07SSean Christopherson /* Number of iterations of the loop for the guest measurement payload. */
115bb9af07SSean Christopherson #define NUM_LOOPS			10
125bb9af07SSean Christopherson 
135bb9af07SSean Christopherson /* Each iteration of the loop retires one branch instruction. */
145bb9af07SSean Christopherson #define NUM_BRANCH_INSNS_RETIRED	(NUM_LOOPS)
155bb9af07SSean Christopherson 
16*4669de42SMaxim Levitsky /*
17*4669de42SMaxim Levitsky  * Number of instructions in each loop. 1 CLFLUSH/CLFLUSHOPT/NOP, 1 MFENCE,
18*4669de42SMaxim Levitsky  * 1 LOOP.
19*4669de42SMaxim Levitsky  */
20*4669de42SMaxim Levitsky #define NUM_INSNS_PER_LOOP		3
215bb9af07SSean Christopherson 
224f1bd6b1SJinrong Liang /*
234f1bd6b1SJinrong Liang  * Number of "extra" instructions that will be counted, i.e. the number of
245bb9af07SSean Christopherson  * instructions that are needed to set up the loop and then disable the
25*4669de42SMaxim Levitsky  * counter.  2 MOV, 2 XOR, 1 WRMSR.
264f1bd6b1SJinrong Liang  */
27*4669de42SMaxim Levitsky #define NUM_EXTRA_INSNS			5
285bb9af07SSean Christopherson 
295bb9af07SSean Christopherson /* Total number of instructions retired within the measured section. */
305bb9af07SSean Christopherson #define NUM_INSNS_RETIRED		(NUM_LOOPS * NUM_INSNS_PER_LOOP + NUM_EXTRA_INSNS)
315bb9af07SSean Christopherson 
324f1bd6b1SJinrong Liang 
334f1bd6b1SJinrong Liang static uint8_t kvm_pmu_version;
344f1bd6b1SJinrong Liang static bool kvm_has_perf_caps;
354f1bd6b1SJinrong Liang 
pmu_vm_create_with_one_vcpu(struct kvm_vcpu ** vcpu,void * guest_code,uint8_t pmu_version,uint64_t perf_capabilities)364f1bd6b1SJinrong Liang static struct kvm_vm *pmu_vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,
374f1bd6b1SJinrong Liang 						  void *guest_code,
384f1bd6b1SJinrong Liang 						  uint8_t pmu_version,
394f1bd6b1SJinrong Liang 						  uint64_t perf_capabilities)
404f1bd6b1SJinrong Liang {
414f1bd6b1SJinrong Liang 	struct kvm_vm *vm;
424f1bd6b1SJinrong Liang 
434f1bd6b1SJinrong Liang 	vm = vm_create_with_one_vcpu(vcpu, guest_code);
444f1bd6b1SJinrong Liang 	sync_global_to_guest(vm, kvm_pmu_version);
454f1bd6b1SJinrong Liang 
464f1bd6b1SJinrong Liang 	/*
474f1bd6b1SJinrong Liang 	 * Set PERF_CAPABILITIES before PMU version as KVM disallows enabling
484f1bd6b1SJinrong Liang 	 * features via PERF_CAPABILITIES if the guest doesn't have a vPMU.
494f1bd6b1SJinrong Liang 	 */
504f1bd6b1SJinrong Liang 	if (kvm_has_perf_caps)
514f1bd6b1SJinrong Liang 		vcpu_set_msr(*vcpu, MSR_IA32_PERF_CAPABILITIES, perf_capabilities);
524f1bd6b1SJinrong Liang 
534f1bd6b1SJinrong Liang 	vcpu_set_cpuid_property(*vcpu, X86_PROPERTY_PMU_VERSION, pmu_version);
544f1bd6b1SJinrong Liang 	return vm;
554f1bd6b1SJinrong Liang }
564f1bd6b1SJinrong Liang 
run_vcpu(struct kvm_vcpu * vcpu)574f1bd6b1SJinrong Liang static void run_vcpu(struct kvm_vcpu *vcpu)
584f1bd6b1SJinrong Liang {
594f1bd6b1SJinrong Liang 	struct ucall uc;
604f1bd6b1SJinrong Liang 
614f1bd6b1SJinrong Liang 	do {
624f1bd6b1SJinrong Liang 		vcpu_run(vcpu);
634f1bd6b1SJinrong Liang 		switch (get_ucall(vcpu, &uc)) {
644f1bd6b1SJinrong Liang 		case UCALL_SYNC:
654f1bd6b1SJinrong Liang 			break;
664f1bd6b1SJinrong Liang 		case UCALL_ABORT:
674f1bd6b1SJinrong Liang 			REPORT_GUEST_ASSERT(uc);
684f1bd6b1SJinrong Liang 			break;
694f1bd6b1SJinrong Liang 		case UCALL_PRINTF:
704f1bd6b1SJinrong Liang 			pr_info("%s", uc.buffer);
714f1bd6b1SJinrong Liang 			break;
724f1bd6b1SJinrong Liang 		case UCALL_DONE:
734f1bd6b1SJinrong Liang 			break;
744f1bd6b1SJinrong Liang 		default:
754f1bd6b1SJinrong Liang 			TEST_FAIL("Unexpected ucall: %lu", uc.cmd);
764f1bd6b1SJinrong Liang 		}
774f1bd6b1SJinrong Liang 	} while (uc.cmd != UCALL_DONE);
784f1bd6b1SJinrong Liang }
794f1bd6b1SJinrong Liang 
guest_get_pmu_version(void)804f1bd6b1SJinrong Liang static uint8_t guest_get_pmu_version(void)
814f1bd6b1SJinrong Liang {
824f1bd6b1SJinrong Liang 	/*
834f1bd6b1SJinrong Liang 	 * Return the effective PMU version, i.e. the minimum between what KVM
844f1bd6b1SJinrong Liang 	 * supports and what is enumerated to the guest.  The host deliberately
854f1bd6b1SJinrong Liang 	 * advertises a PMU version to the guest beyond what is actually
864f1bd6b1SJinrong Liang 	 * supported by KVM to verify KVM doesn't freak out and do something
874f1bd6b1SJinrong Liang 	 * bizarre with an architecturally valid, but unsupported, version.
884f1bd6b1SJinrong Liang 	 */
894f1bd6b1SJinrong Liang 	return min_t(uint8_t, kvm_pmu_version, this_cpu_property(X86_PROPERTY_PMU_VERSION));
904f1bd6b1SJinrong Liang }
914f1bd6b1SJinrong Liang 
924f1bd6b1SJinrong Liang /*
934f1bd6b1SJinrong Liang  * If an architectural event is supported and guaranteed to generate at least
944f1bd6b1SJinrong Liang  * one "hit, assert that its count is non-zero.  If an event isn't supported or
954f1bd6b1SJinrong Liang  * the test can't guarantee the associated action will occur, then all bets are
964f1bd6b1SJinrong Liang  * off regarding the count, i.e. no checks can be done.
974f1bd6b1SJinrong Liang  *
984f1bd6b1SJinrong Liang  * Sanity check that in all cases, the event doesn't count when it's disabled,
994f1bd6b1SJinrong Liang  * and that KVM correctly emulates the write of an arbitrary value.
1004f1bd6b1SJinrong Liang  */
guest_assert_event_count(uint8_t idx,struct kvm_x86_pmu_feature event,uint32_t pmc,uint32_t pmc_msr)1014f1bd6b1SJinrong Liang static void guest_assert_event_count(uint8_t idx,
1024f1bd6b1SJinrong Liang 				     struct kvm_x86_pmu_feature event,
1034f1bd6b1SJinrong Liang 				     uint32_t pmc, uint32_t pmc_msr)
1044f1bd6b1SJinrong Liang {
1054f1bd6b1SJinrong Liang 	uint64_t count;
1064f1bd6b1SJinrong Liang 
1074f1bd6b1SJinrong Liang 	count = _rdpmc(pmc);
1084f1bd6b1SJinrong Liang 	if (!this_pmu_has(event))
1094f1bd6b1SJinrong Liang 		goto sanity_checks;
1104f1bd6b1SJinrong Liang 
1114f1bd6b1SJinrong Liang 	switch (idx) {
1124f1bd6b1SJinrong Liang 	case INTEL_ARCH_INSTRUCTIONS_RETIRED_INDEX:
1134f1bd6b1SJinrong Liang 		GUEST_ASSERT_EQ(count, NUM_INSNS_RETIRED);
1144f1bd6b1SJinrong Liang 		break;
1154f1bd6b1SJinrong Liang 	case INTEL_ARCH_BRANCHES_RETIRED_INDEX:
1165bb9af07SSean Christopherson 		GUEST_ASSERT_EQ(count, NUM_BRANCH_INSNS_RETIRED);
1174f1bd6b1SJinrong Liang 		break;
118b55e7adfSSean Christopherson 	case INTEL_ARCH_LLC_REFERENCES_INDEX:
119b55e7adfSSean Christopherson 	case INTEL_ARCH_LLC_MISSES_INDEX:
120b55e7adfSSean Christopherson 		if (!this_cpu_has(X86_FEATURE_CLFLUSHOPT) &&
121b55e7adfSSean Christopherson 		    !this_cpu_has(X86_FEATURE_CLFLUSH))
122b55e7adfSSean Christopherson 			break;
123b55e7adfSSean Christopherson 		fallthrough;
1244f1bd6b1SJinrong Liang 	case INTEL_ARCH_CPU_CYCLES_INDEX:
1254f1bd6b1SJinrong Liang 	case INTEL_ARCH_REFERENCE_CYCLES_INDEX:
1264f1bd6b1SJinrong Liang 		GUEST_ASSERT_NE(count, 0);
1274f1bd6b1SJinrong Liang 		break;
1284a447b13SDapeng Mi 	case INTEL_ARCH_TOPDOWN_SLOTS_INDEX:
1294a447b13SDapeng Mi 		GUEST_ASSERT(count >= NUM_INSNS_RETIRED);
1304a447b13SDapeng Mi 		break;
1314f1bd6b1SJinrong Liang 	default:
1324f1bd6b1SJinrong Liang 		break;
1334f1bd6b1SJinrong Liang 	}
1344f1bd6b1SJinrong Liang 
1354f1bd6b1SJinrong Liang sanity_checks:
1365bb9af07SSean Christopherson 	__asm__ __volatile__("loop ." : "+c"((int){NUM_LOOPS}));
1374f1bd6b1SJinrong Liang 	GUEST_ASSERT_EQ(_rdpmc(pmc), count);
1384f1bd6b1SJinrong Liang 
1394f1bd6b1SJinrong Liang 	wrmsr(pmc_msr, 0xdead);
1404f1bd6b1SJinrong Liang 	GUEST_ASSERT_EQ(_rdpmc(pmc), 0xdead);
1414f1bd6b1SJinrong Liang }
1424f1bd6b1SJinrong Liang 
143b55e7adfSSean Christopherson /*
144b55e7adfSSean Christopherson  * Enable and disable the PMC in a monolithic asm blob to ensure that the
145b55e7adfSSean Christopherson  * compiler can't insert _any_ code into the measured sequence.  Note, ECX
146b55e7adfSSean Christopherson  * doesn't need to be clobbered as the input value, @pmc_msr, is restored
147b55e7adfSSean Christopherson  * before the end of the sequence.
148b55e7adfSSean Christopherson  *
149b55e7adfSSean Christopherson  * If CLFUSH{,OPT} is supported, flush the cacheline containing (at least) the
150*4669de42SMaxim Levitsky  * CLFUSH{,OPT} instruction on each loop iteration to force LLC references and
151*4669de42SMaxim Levitsky  * misses, i.e. to allow testing that those events actually count.
152cd34fd8cSSean Christopherson  *
153cd34fd8cSSean Christopherson  * If forced emulation is enabled (and specified), force emulation on a subset
154cd34fd8cSSean Christopherson  * of the measured code to verify that KVM correctly emulates instructions and
155cd34fd8cSSean Christopherson  * branches retired events in conjunction with hardware also counting said
156cd34fd8cSSean Christopherson  * events.
157b55e7adfSSean Christopherson  */
158cd34fd8cSSean Christopherson #define GUEST_MEASURE_EVENT(_msr, _value, clflush, FEP)				\
159b55e7adfSSean Christopherson do {										\
160b55e7adfSSean Christopherson 	__asm__ __volatile__("wrmsr\n\t"					\
161*4669de42SMaxim Levitsky 			     " mov $" __stringify(NUM_LOOPS) ", %%ecx\n\t"	\
162*4669de42SMaxim Levitsky 			     "1:\n\t"						\
163b55e7adfSSean Christopherson 			     clflush "\n\t"					\
164b55e7adfSSean Christopherson 			     "mfence\n\t"					\
165*4669de42SMaxim Levitsky 			     FEP "loop 1b\n\t"					\
166cd34fd8cSSean Christopherson 			     FEP "mov %%edi, %%ecx\n\t"				\
167cd34fd8cSSean Christopherson 			     FEP "xor %%eax, %%eax\n\t"				\
168cd34fd8cSSean Christopherson 			     FEP "xor %%edx, %%edx\n\t"				\
169b55e7adfSSean Christopherson 			     "wrmsr\n\t"					\
170b55e7adfSSean Christopherson 			     :: "a"((uint32_t)_value), "d"(_value >> 32),	\
171b55e7adfSSean Christopherson 				"c"(_msr), "D"(_msr)				\
172b55e7adfSSean Christopherson 	);									\
173b55e7adfSSean Christopherson } while (0)
174b55e7adfSSean Christopherson 
175cd34fd8cSSean Christopherson #define GUEST_TEST_EVENT(_idx, _event, _pmc, _pmc_msr, _ctrl_msr, _value, FEP)	\
176cd34fd8cSSean Christopherson do {										\
177cd34fd8cSSean Christopherson 	wrmsr(pmc_msr, 0);							\
178cd34fd8cSSean Christopherson 										\
179cd34fd8cSSean Christopherson 	if (this_cpu_has(X86_FEATURE_CLFLUSHOPT))				\
180*4669de42SMaxim Levitsky 		GUEST_MEASURE_EVENT(_ctrl_msr, _value, "clflushopt .", FEP);	\
181cd34fd8cSSean Christopherson 	else if (this_cpu_has(X86_FEATURE_CLFLUSH))				\
182*4669de42SMaxim Levitsky 		GUEST_MEASURE_EVENT(_ctrl_msr, _value, "clflush .", FEP);	\
183cd34fd8cSSean Christopherson 	else									\
184cd34fd8cSSean Christopherson 		GUEST_MEASURE_EVENT(_ctrl_msr, _value, "nop", FEP);		\
185cd34fd8cSSean Christopherson 										\
186cd34fd8cSSean Christopherson 	guest_assert_event_count(_idx, _event, _pmc, _pmc_msr);			\
187cd34fd8cSSean Christopherson } while (0)
188cd34fd8cSSean Christopherson 
__guest_test_arch_event(uint8_t idx,struct kvm_x86_pmu_feature event,uint32_t pmc,uint32_t pmc_msr,uint32_t ctrl_msr,uint64_t ctrl_msr_value)1894f1bd6b1SJinrong Liang static void __guest_test_arch_event(uint8_t idx, struct kvm_x86_pmu_feature event,
1904f1bd6b1SJinrong Liang 				    uint32_t pmc, uint32_t pmc_msr,
1914f1bd6b1SJinrong Liang 				    uint32_t ctrl_msr, uint64_t ctrl_msr_value)
1924f1bd6b1SJinrong Liang {
193cd34fd8cSSean Christopherson 	GUEST_TEST_EVENT(idx, event, pmc, pmc_msr, ctrl_msr, ctrl_msr_value, "");
1944f1bd6b1SJinrong Liang 
195cd34fd8cSSean Christopherson 	if (is_forced_emulation_enabled)
196cd34fd8cSSean Christopherson 		GUEST_TEST_EVENT(idx, event, pmc, pmc_msr, ctrl_msr, ctrl_msr_value, KVM_FEP);
1974f1bd6b1SJinrong Liang }
1984f1bd6b1SJinrong Liang 
1993e26b825SJinrong Liang #define X86_PMU_FEATURE_NULL						\
2003e26b825SJinrong Liang ({									\
2013e26b825SJinrong Liang 	struct kvm_x86_pmu_feature feature = {};			\
2023e26b825SJinrong Liang 									\
2033e26b825SJinrong Liang 	feature;							\
2043e26b825SJinrong Liang })
2053e26b825SJinrong Liang 
pmu_is_null_feature(struct kvm_x86_pmu_feature event)2063e26b825SJinrong Liang static bool pmu_is_null_feature(struct kvm_x86_pmu_feature event)
2073e26b825SJinrong Liang {
2083e26b825SJinrong Liang 	return !(*(u64 *)&event);
2093e26b825SJinrong Liang }
2103e26b825SJinrong Liang 
guest_test_arch_event(uint8_t idx)2114f1bd6b1SJinrong Liang static void guest_test_arch_event(uint8_t idx)
2124f1bd6b1SJinrong Liang {
2134f1bd6b1SJinrong Liang 	const struct {
2144f1bd6b1SJinrong Liang 		struct kvm_x86_pmu_feature gp_event;
2153e26b825SJinrong Liang 		struct kvm_x86_pmu_feature fixed_event;
2164f1bd6b1SJinrong Liang 	} intel_event_to_feature[] = {
2173e26b825SJinrong Liang 		[INTEL_ARCH_CPU_CYCLES_INDEX]		 = { X86_PMU_FEATURE_CPU_CYCLES, X86_PMU_FEATURE_CPU_CYCLES_FIXED },
2183e26b825SJinrong Liang 		[INTEL_ARCH_INSTRUCTIONS_RETIRED_INDEX]	 = { X86_PMU_FEATURE_INSNS_RETIRED, X86_PMU_FEATURE_INSNS_RETIRED_FIXED },
2193e26b825SJinrong Liang 		/*
2203e26b825SJinrong Liang 		 * Note, the fixed counter for reference cycles is NOT the same
2213e26b825SJinrong Liang 		 * as the general purpose architectural event.  The fixed counter
2223e26b825SJinrong Liang 		 * explicitly counts at the same frequency as the TSC, whereas
2233e26b825SJinrong Liang 		 * the GP event counts at a fixed, but uarch specific, frequency.
2243e26b825SJinrong Liang 		 * Bundle them here for simplicity.
2253e26b825SJinrong Liang 		 */
2263e26b825SJinrong Liang 		[INTEL_ARCH_REFERENCE_CYCLES_INDEX]	 = { X86_PMU_FEATURE_REFERENCE_CYCLES, X86_PMU_FEATURE_REFERENCE_TSC_CYCLES_FIXED },
2273e26b825SJinrong Liang 		[INTEL_ARCH_LLC_REFERENCES_INDEX]	 = { X86_PMU_FEATURE_LLC_REFERENCES, X86_PMU_FEATURE_NULL },
2283e26b825SJinrong Liang 		[INTEL_ARCH_LLC_MISSES_INDEX]		 = { X86_PMU_FEATURE_LLC_MISSES, X86_PMU_FEATURE_NULL },
2293e26b825SJinrong Liang 		[INTEL_ARCH_BRANCHES_RETIRED_INDEX]	 = { X86_PMU_FEATURE_BRANCH_INSNS_RETIRED, X86_PMU_FEATURE_NULL },
2303e26b825SJinrong Liang 		[INTEL_ARCH_BRANCHES_MISPREDICTED_INDEX] = { X86_PMU_FEATURE_BRANCHES_MISPREDICTED, X86_PMU_FEATURE_NULL },
2313e26b825SJinrong Liang 		[INTEL_ARCH_TOPDOWN_SLOTS_INDEX]	 = { X86_PMU_FEATURE_TOPDOWN_SLOTS, X86_PMU_FEATURE_TOPDOWN_SLOTS_FIXED },
2324f1bd6b1SJinrong Liang 	};
2334f1bd6b1SJinrong Liang 
2344f1bd6b1SJinrong Liang 	uint32_t nr_gp_counters = this_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);
2354f1bd6b1SJinrong Liang 	uint32_t pmu_version = guest_get_pmu_version();
2364f1bd6b1SJinrong Liang 	/* PERF_GLOBAL_CTRL exists only for Architectural PMU Version 2+. */
2374f1bd6b1SJinrong Liang 	bool guest_has_perf_global_ctrl = pmu_version >= 2;
2383e26b825SJinrong Liang 	struct kvm_x86_pmu_feature gp_event, fixed_event;
2394f1bd6b1SJinrong Liang 	uint32_t base_pmc_msr;
2404f1bd6b1SJinrong Liang 	unsigned int i;
2414f1bd6b1SJinrong Liang 
2424f1bd6b1SJinrong Liang 	/* The host side shouldn't invoke this without a guest PMU. */
2434f1bd6b1SJinrong Liang 	GUEST_ASSERT(pmu_version);
2444f1bd6b1SJinrong Liang 
2454f1bd6b1SJinrong Liang 	if (this_cpu_has(X86_FEATURE_PDCM) &&
2464f1bd6b1SJinrong Liang 	    rdmsr(MSR_IA32_PERF_CAPABILITIES) & PMU_CAP_FW_WRITES)
2474f1bd6b1SJinrong Liang 		base_pmc_msr = MSR_IA32_PMC0;
2484f1bd6b1SJinrong Liang 	else
2494f1bd6b1SJinrong Liang 		base_pmc_msr = MSR_IA32_PERFCTR0;
2504f1bd6b1SJinrong Liang 
2514f1bd6b1SJinrong Liang 	gp_event = intel_event_to_feature[idx].gp_event;
2524f1bd6b1SJinrong Liang 	GUEST_ASSERT_EQ(idx, gp_event.f.bit);
2534f1bd6b1SJinrong Liang 
2544f1bd6b1SJinrong Liang 	GUEST_ASSERT(nr_gp_counters);
2554f1bd6b1SJinrong Liang 
2564f1bd6b1SJinrong Liang 	for (i = 0; i < nr_gp_counters; i++) {
2574f1bd6b1SJinrong Liang 		uint64_t eventsel = ARCH_PERFMON_EVENTSEL_OS |
2584f1bd6b1SJinrong Liang 				    ARCH_PERFMON_EVENTSEL_ENABLE |
2594f1bd6b1SJinrong Liang 				    intel_pmu_arch_events[idx];
2604f1bd6b1SJinrong Liang 
2614f1bd6b1SJinrong Liang 		wrmsr(MSR_P6_EVNTSEL0 + i, 0);
2624f1bd6b1SJinrong Liang 		if (guest_has_perf_global_ctrl)
2634f1bd6b1SJinrong Liang 			wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, BIT_ULL(i));
2644f1bd6b1SJinrong Liang 
2654f1bd6b1SJinrong Liang 		__guest_test_arch_event(idx, gp_event, i, base_pmc_msr + i,
2664f1bd6b1SJinrong Liang 					MSR_P6_EVNTSEL0 + i, eventsel);
2674f1bd6b1SJinrong Liang 	}
2683e26b825SJinrong Liang 
2693e26b825SJinrong Liang 	if (!guest_has_perf_global_ctrl)
2703e26b825SJinrong Liang 		return;
2713e26b825SJinrong Liang 
2723e26b825SJinrong Liang 	fixed_event = intel_event_to_feature[idx].fixed_event;
2733e26b825SJinrong Liang 	if (pmu_is_null_feature(fixed_event) || !this_pmu_has(fixed_event))
2743e26b825SJinrong Liang 		return;
2753e26b825SJinrong Liang 
2763e26b825SJinrong Liang 	i = fixed_event.f.bit;
2773e26b825SJinrong Liang 
2783e26b825SJinrong Liang 	wrmsr(MSR_CORE_PERF_FIXED_CTR_CTRL, FIXED_PMC_CTRL(i, FIXED_PMC_KERNEL));
2793e26b825SJinrong Liang 
2803e26b825SJinrong Liang 	__guest_test_arch_event(idx, fixed_event, i | INTEL_RDPMC_FIXED,
2813e26b825SJinrong Liang 				MSR_CORE_PERF_FIXED_CTR0 + i,
2823e26b825SJinrong Liang 				MSR_CORE_PERF_GLOBAL_CTRL,
2833e26b825SJinrong Liang 				FIXED_PMC_GLOBAL_CTRL_ENABLE(i));
2844f1bd6b1SJinrong Liang }
2854f1bd6b1SJinrong Liang 
guest_test_arch_events(void)2864f1bd6b1SJinrong Liang static void guest_test_arch_events(void)
2874f1bd6b1SJinrong Liang {
2884f1bd6b1SJinrong Liang 	uint8_t i;
2894f1bd6b1SJinrong Liang 
2904f1bd6b1SJinrong Liang 	for (i = 0; i < NR_INTEL_ARCH_EVENTS; i++)
2914f1bd6b1SJinrong Liang 		guest_test_arch_event(i);
2924f1bd6b1SJinrong Liang 
2934f1bd6b1SJinrong Liang 	GUEST_DONE();
2944f1bd6b1SJinrong Liang }
2954f1bd6b1SJinrong Liang 
test_arch_events(uint8_t pmu_version,uint64_t perf_capabilities,uint8_t length,uint8_t unavailable_mask)2964f1bd6b1SJinrong Liang static void test_arch_events(uint8_t pmu_version, uint64_t perf_capabilities,
2974f1bd6b1SJinrong Liang 			     uint8_t length, uint8_t unavailable_mask)
2984f1bd6b1SJinrong Liang {
2994f1bd6b1SJinrong Liang 	struct kvm_vcpu *vcpu;
3004f1bd6b1SJinrong Liang 	struct kvm_vm *vm;
3014f1bd6b1SJinrong Liang 
3024f1bd6b1SJinrong Liang 	/* Testing arch events requires a vPMU (there are no negative tests). */
3034f1bd6b1SJinrong Liang 	if (!pmu_version)
3044f1bd6b1SJinrong Liang 		return;
3054f1bd6b1SJinrong Liang 
3064f1bd6b1SJinrong Liang 	vm = pmu_vm_create_with_one_vcpu(&vcpu, guest_test_arch_events,
3074f1bd6b1SJinrong Liang 					 pmu_version, perf_capabilities);
3084f1bd6b1SJinrong Liang 
3094f1bd6b1SJinrong Liang 	vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_EBX_BIT_VECTOR_LENGTH,
3104f1bd6b1SJinrong Liang 				length);
3114f1bd6b1SJinrong Liang 	vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_EVENTS_MASK,
3124f1bd6b1SJinrong Liang 				unavailable_mask);
3134f1bd6b1SJinrong Liang 
3144f1bd6b1SJinrong Liang 	run_vcpu(vcpu);
3154f1bd6b1SJinrong Liang 
3164f1bd6b1SJinrong Liang 	kvm_vm_free(vm);
3174f1bd6b1SJinrong Liang }
3184f1bd6b1SJinrong Liang 
3197137cf75SJinrong Liang /*
3207137cf75SJinrong Liang  * Limit testing to MSRs that are actually defined by Intel (in the SDM).  MSRs
3217137cf75SJinrong Liang  * that aren't defined counter MSRs *probably* don't exist, but there's no
3227137cf75SJinrong Liang  * guarantee that currently undefined MSR indices won't be used for something
3237137cf75SJinrong Liang  * other than PMCs in the future.
3247137cf75SJinrong Liang  */
3257137cf75SJinrong Liang #define MAX_NR_GP_COUNTERS	8
3267137cf75SJinrong Liang #define MAX_NR_FIXED_COUNTERS	3
3277137cf75SJinrong Liang 
3287137cf75SJinrong Liang #define GUEST_ASSERT_PMC_MSR_ACCESS(insn, msr, expect_gp, vector)		\
3297137cf75SJinrong Liang __GUEST_ASSERT(expect_gp ? vector == GP_VECTOR : !vector,			\
3307137cf75SJinrong Liang 	       "Expected %s on " #insn "(0x%x), got vector %u",			\
3317137cf75SJinrong Liang 	       expect_gp ? "#GP" : "no fault", msr, vector)			\
3327137cf75SJinrong Liang 
3337137cf75SJinrong Liang #define GUEST_ASSERT_PMC_VALUE(insn, msr, val, expected)			\
3347137cf75SJinrong Liang 	__GUEST_ASSERT(val == expected_val,					\
3357137cf75SJinrong Liang 		       "Expected " #insn "(0x%x) to yield 0x%lx, got 0x%lx",	\
3367137cf75SJinrong Liang 		       msr, expected_val, val);
3377137cf75SJinrong Liang 
guest_test_rdpmc(uint32_t rdpmc_idx,bool expect_success,uint64_t expected_val)338a8a37f55SSean Christopherson static void guest_test_rdpmc(uint32_t rdpmc_idx, bool expect_success,
339a8a37f55SSean Christopherson 			     uint64_t expected_val)
340a8a37f55SSean Christopherson {
341a8a37f55SSean Christopherson 	uint8_t vector;
342a8a37f55SSean Christopherson 	uint64_t val;
343a8a37f55SSean Christopherson 
344a8a37f55SSean Christopherson 	vector = rdpmc_safe(rdpmc_idx, &val);
345a8a37f55SSean Christopherson 	GUEST_ASSERT_PMC_MSR_ACCESS(RDPMC, rdpmc_idx, !expect_success, vector);
346a8a37f55SSean Christopherson 	if (expect_success)
347a8a37f55SSean Christopherson 		GUEST_ASSERT_PMC_VALUE(RDPMC, rdpmc_idx, val, expected_val);
348a8a37f55SSean Christopherson 
349a8a37f55SSean Christopherson 	if (!is_forced_emulation_enabled)
350a8a37f55SSean Christopherson 		return;
351a8a37f55SSean Christopherson 
352a8a37f55SSean Christopherson 	vector = rdpmc_safe_fep(rdpmc_idx, &val);
353a8a37f55SSean Christopherson 	GUEST_ASSERT_PMC_MSR_ACCESS(RDPMC, rdpmc_idx, !expect_success, vector);
354a8a37f55SSean Christopherson 	if (expect_success)
355a8a37f55SSean Christopherson 		GUEST_ASSERT_PMC_VALUE(RDPMC, rdpmc_idx, val, expected_val);
356a8a37f55SSean Christopherson }
357a8a37f55SSean Christopherson 
guest_rd_wr_counters(uint32_t base_msr,uint8_t nr_possible_counters,uint8_t nr_counters,uint32_t or_mask)3587137cf75SJinrong Liang static void guest_rd_wr_counters(uint32_t base_msr, uint8_t nr_possible_counters,
359c7d7c76eSJinrong Liang 				 uint8_t nr_counters, uint32_t or_mask)
3607137cf75SJinrong Liang {
361a8a37f55SSean Christopherson 	const bool pmu_has_fast_mode = !guest_get_pmu_version();
3627137cf75SJinrong Liang 	uint8_t i;
3637137cf75SJinrong Liang 
3647137cf75SJinrong Liang 	for (i = 0; i < nr_possible_counters; i++) {
3657137cf75SJinrong Liang 		/*
3667137cf75SJinrong Liang 		 * TODO: Test a value that validates full-width writes and the
3677137cf75SJinrong Liang 		 * width of the counters.
3687137cf75SJinrong Liang 		 */
3697137cf75SJinrong Liang 		const uint64_t test_val = 0xffff;
3707137cf75SJinrong Liang 		const uint32_t msr = base_msr + i;
371c7d7c76eSJinrong Liang 
372c7d7c76eSJinrong Liang 		/*
373c7d7c76eSJinrong Liang 		 * Fixed counters are supported if the counter is less than the
374c7d7c76eSJinrong Liang 		 * number of enumerated contiguous counters *or* the counter is
375c7d7c76eSJinrong Liang 		 * explicitly enumerated in the supported counters mask.
376c7d7c76eSJinrong Liang 		 */
377c7d7c76eSJinrong Liang 		const bool expect_success = i < nr_counters || (or_mask & BIT(i));
3787137cf75SJinrong Liang 
3797137cf75SJinrong Liang 		/*
3807137cf75SJinrong Liang 		 * KVM drops writes to MSR_P6_PERFCTR[0|1] if the counters are
3817137cf75SJinrong Liang 		 * unsupported, i.e. doesn't #GP and reads back '0'.
3827137cf75SJinrong Liang 		 */
3837137cf75SJinrong Liang 		const uint64_t expected_val = expect_success ? test_val : 0;
3847137cf75SJinrong Liang 		const bool expect_gp = !expect_success && msr != MSR_P6_PERFCTR0 &&
3857137cf75SJinrong Liang 				       msr != MSR_P6_PERFCTR1;
386a8a37f55SSean Christopherson 		uint32_t rdpmc_idx;
3877137cf75SJinrong Liang 		uint8_t vector;
3887137cf75SJinrong Liang 		uint64_t val;
3897137cf75SJinrong Liang 
3907137cf75SJinrong Liang 		vector = wrmsr_safe(msr, test_val);
3917137cf75SJinrong Liang 		GUEST_ASSERT_PMC_MSR_ACCESS(WRMSR, msr, expect_gp, vector);
3927137cf75SJinrong Liang 
3937137cf75SJinrong Liang 		vector = rdmsr_safe(msr, &val);
3947137cf75SJinrong Liang 		GUEST_ASSERT_PMC_MSR_ACCESS(RDMSR, msr, expect_gp, vector);
3957137cf75SJinrong Liang 
3967137cf75SJinrong Liang 		/* On #GP, the result of RDMSR is undefined. */
3977137cf75SJinrong Liang 		if (!expect_gp)
3987137cf75SJinrong Liang 			GUEST_ASSERT_PMC_VALUE(RDMSR, msr, val, expected_val);
3997137cf75SJinrong Liang 
400a8a37f55SSean Christopherson 		/*
401a8a37f55SSean Christopherson 		 * Redo the read tests with RDPMC, which has different indexing
402a8a37f55SSean Christopherson 		 * semantics and additional capabilities.
403a8a37f55SSean Christopherson 		 */
404a8a37f55SSean Christopherson 		rdpmc_idx = i;
405a8a37f55SSean Christopherson 		if (base_msr == MSR_CORE_PERF_FIXED_CTR0)
406a8a37f55SSean Christopherson 			rdpmc_idx |= INTEL_RDPMC_FIXED;
407a8a37f55SSean Christopherson 
408a8a37f55SSean Christopherson 		guest_test_rdpmc(rdpmc_idx, expect_success, expected_val);
409a8a37f55SSean Christopherson 
410a8a37f55SSean Christopherson 		/*
411a8a37f55SSean Christopherson 		 * KVM doesn't support non-architectural PMUs, i.e. it should
412a8a37f55SSean Christopherson 		 * impossible to have fast mode RDPMC.  Verify that attempting
413a8a37f55SSean Christopherson 		 * to use fast RDPMC always #GPs.
414a8a37f55SSean Christopherson 		 */
415a8a37f55SSean Christopherson 		GUEST_ASSERT(!expect_success || !pmu_has_fast_mode);
416a8a37f55SSean Christopherson 		rdpmc_idx |= INTEL_RDPMC_FAST;
417a8a37f55SSean Christopherson 		guest_test_rdpmc(rdpmc_idx, false, -1ull);
418a8a37f55SSean Christopherson 
4197137cf75SJinrong Liang 		vector = wrmsr_safe(msr, 0);
4207137cf75SJinrong Liang 		GUEST_ASSERT_PMC_MSR_ACCESS(WRMSR, msr, expect_gp, vector);
4217137cf75SJinrong Liang 	}
4227137cf75SJinrong Liang }
4237137cf75SJinrong Liang 
guest_test_gp_counters(void)4247137cf75SJinrong Liang static void guest_test_gp_counters(void)
4257137cf75SJinrong Liang {
42608a82824SSean Christopherson 	uint8_t pmu_version = guest_get_pmu_version();
4277137cf75SJinrong Liang 	uint8_t nr_gp_counters = 0;
4287137cf75SJinrong Liang 	uint32_t base_msr;
4297137cf75SJinrong Liang 
43008a82824SSean Christopherson 	if (pmu_version)
4317137cf75SJinrong Liang 		nr_gp_counters = this_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);
4327137cf75SJinrong Liang 
43308a82824SSean Christopherson 	/*
43408a82824SSean Christopherson 	 * For v2+ PMUs, PERF_GLOBAL_CTRL's architectural post-RESET value is
43508a82824SSean Christopherson 	 * "Sets bits n-1:0 and clears the upper bits", where 'n' is the number
43608a82824SSean Christopherson 	 * of GP counters.  If there are no GP counters, require KVM to leave
43708a82824SSean Christopherson 	 * PERF_GLOBAL_CTRL '0'.  This edge case isn't covered by the SDM, but
43808a82824SSean Christopherson 	 * follow the spirit of the architecture and only globally enable GP
43908a82824SSean Christopherson 	 * counters, of which there are none.
44008a82824SSean Christopherson 	 */
44108a82824SSean Christopherson 	if (pmu_version > 1) {
44208a82824SSean Christopherson 		uint64_t global_ctrl = rdmsr(MSR_CORE_PERF_GLOBAL_CTRL);
44308a82824SSean Christopherson 
44408a82824SSean Christopherson 		if (nr_gp_counters)
44508a82824SSean Christopherson 			GUEST_ASSERT_EQ(global_ctrl, GENMASK_ULL(nr_gp_counters - 1, 0));
44608a82824SSean Christopherson 		else
44708a82824SSean Christopherson 			GUEST_ASSERT_EQ(global_ctrl, 0);
44808a82824SSean Christopherson 	}
44908a82824SSean Christopherson 
4507137cf75SJinrong Liang 	if (this_cpu_has(X86_FEATURE_PDCM) &&
4517137cf75SJinrong Liang 	    rdmsr(MSR_IA32_PERF_CAPABILITIES) & PMU_CAP_FW_WRITES)
4527137cf75SJinrong Liang 		base_msr = MSR_IA32_PMC0;
4537137cf75SJinrong Liang 	else
4547137cf75SJinrong Liang 		base_msr = MSR_IA32_PERFCTR0;
4557137cf75SJinrong Liang 
456c7d7c76eSJinrong Liang 	guest_rd_wr_counters(base_msr, MAX_NR_GP_COUNTERS, nr_gp_counters, 0);
457787071fdSJinrong Liang 	GUEST_DONE();
4587137cf75SJinrong Liang }
4597137cf75SJinrong Liang 
test_gp_counters(uint8_t pmu_version,uint64_t perf_capabilities,uint8_t nr_gp_counters)4607137cf75SJinrong Liang static void test_gp_counters(uint8_t pmu_version, uint64_t perf_capabilities,
4617137cf75SJinrong Liang 			     uint8_t nr_gp_counters)
4627137cf75SJinrong Liang {
4637137cf75SJinrong Liang 	struct kvm_vcpu *vcpu;
4647137cf75SJinrong Liang 	struct kvm_vm *vm;
4657137cf75SJinrong Liang 
4667137cf75SJinrong Liang 	vm = pmu_vm_create_with_one_vcpu(&vcpu, guest_test_gp_counters,
4677137cf75SJinrong Liang 					 pmu_version, perf_capabilities);
4687137cf75SJinrong Liang 
4697137cf75SJinrong Liang 	vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_NR_GP_COUNTERS,
4707137cf75SJinrong Liang 				nr_gp_counters);
4717137cf75SJinrong Liang 
4727137cf75SJinrong Liang 	run_vcpu(vcpu);
4737137cf75SJinrong Liang 
4747137cf75SJinrong Liang 	kvm_vm_free(vm);
4757137cf75SJinrong Liang }
4767137cf75SJinrong Liang 
guest_test_fixed_counters(void)477c7d7c76eSJinrong Liang static void guest_test_fixed_counters(void)
478c7d7c76eSJinrong Liang {
479c7d7c76eSJinrong Liang 	uint64_t supported_bitmask = 0;
480c7d7c76eSJinrong Liang 	uint8_t nr_fixed_counters = 0;
481787071fdSJinrong Liang 	uint8_t i;
482c7d7c76eSJinrong Liang 
483c7d7c76eSJinrong Liang 	/* Fixed counters require Architectural vPMU Version 2+. */
484c7d7c76eSJinrong Liang 	if (guest_get_pmu_version() >= 2)
485c7d7c76eSJinrong Liang 		nr_fixed_counters = this_cpu_property(X86_PROPERTY_PMU_NR_FIXED_COUNTERS);
486c7d7c76eSJinrong Liang 
487c7d7c76eSJinrong Liang 	/*
488c7d7c76eSJinrong Liang 	 * The supported bitmask for fixed counters was introduced in PMU
489c7d7c76eSJinrong Liang 	 * version 5.
490c7d7c76eSJinrong Liang 	 */
491c7d7c76eSJinrong Liang 	if (guest_get_pmu_version() >= 5)
492c7d7c76eSJinrong Liang 		supported_bitmask = this_cpu_property(X86_PROPERTY_PMU_FIXED_COUNTERS_BITMASK);
493c7d7c76eSJinrong Liang 
494c7d7c76eSJinrong Liang 	guest_rd_wr_counters(MSR_CORE_PERF_FIXED_CTR0, MAX_NR_FIXED_COUNTERS,
495c7d7c76eSJinrong Liang 			     nr_fixed_counters, supported_bitmask);
496787071fdSJinrong Liang 
497787071fdSJinrong Liang 	for (i = 0; i < MAX_NR_FIXED_COUNTERS; i++) {
498787071fdSJinrong Liang 		uint8_t vector;
499787071fdSJinrong Liang 		uint64_t val;
500787071fdSJinrong Liang 
501787071fdSJinrong Liang 		if (i >= nr_fixed_counters && !(supported_bitmask & BIT_ULL(i))) {
502787071fdSJinrong Liang 			vector = wrmsr_safe(MSR_CORE_PERF_FIXED_CTR_CTRL,
503787071fdSJinrong Liang 					    FIXED_PMC_CTRL(i, FIXED_PMC_KERNEL));
504787071fdSJinrong Liang 			__GUEST_ASSERT(vector == GP_VECTOR,
505787071fdSJinrong Liang 				       "Expected #GP for counter %u in FIXED_CTR_CTRL", i);
506787071fdSJinrong Liang 
507787071fdSJinrong Liang 			vector = wrmsr_safe(MSR_CORE_PERF_GLOBAL_CTRL,
508787071fdSJinrong Liang 					    FIXED_PMC_GLOBAL_CTRL_ENABLE(i));
509787071fdSJinrong Liang 			__GUEST_ASSERT(vector == GP_VECTOR,
510787071fdSJinrong Liang 				       "Expected #GP for counter %u in PERF_GLOBAL_CTRL", i);
511787071fdSJinrong Liang 			continue;
512787071fdSJinrong Liang 		}
513787071fdSJinrong Liang 
514787071fdSJinrong Liang 		wrmsr(MSR_CORE_PERF_FIXED_CTR0 + i, 0);
515787071fdSJinrong Liang 		wrmsr(MSR_CORE_PERF_FIXED_CTR_CTRL, FIXED_PMC_CTRL(i, FIXED_PMC_KERNEL));
516787071fdSJinrong Liang 		wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, FIXED_PMC_GLOBAL_CTRL_ENABLE(i));
5175bb9af07SSean Christopherson 		__asm__ __volatile__("loop ." : "+c"((int){NUM_LOOPS}));
518787071fdSJinrong Liang 		wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0);
519787071fdSJinrong Liang 		val = rdmsr(MSR_CORE_PERF_FIXED_CTR0 + i);
520787071fdSJinrong Liang 
521787071fdSJinrong Liang 		GUEST_ASSERT_NE(val, 0);
522787071fdSJinrong Liang 	}
523787071fdSJinrong Liang 	GUEST_DONE();
524c7d7c76eSJinrong Liang }
525c7d7c76eSJinrong Liang 
test_fixed_counters(uint8_t pmu_version,uint64_t perf_capabilities,uint8_t nr_fixed_counters,uint32_t supported_bitmask)526c7d7c76eSJinrong Liang static void test_fixed_counters(uint8_t pmu_version, uint64_t perf_capabilities,
527c7d7c76eSJinrong Liang 				uint8_t nr_fixed_counters,
528c7d7c76eSJinrong Liang 				uint32_t supported_bitmask)
529c7d7c76eSJinrong Liang {
530c7d7c76eSJinrong Liang 	struct kvm_vcpu *vcpu;
531c7d7c76eSJinrong Liang 	struct kvm_vm *vm;
532c7d7c76eSJinrong Liang 
533c7d7c76eSJinrong Liang 	vm = pmu_vm_create_with_one_vcpu(&vcpu, guest_test_fixed_counters,
534c7d7c76eSJinrong Liang 					 pmu_version, perf_capabilities);
535c7d7c76eSJinrong Liang 
536c7d7c76eSJinrong Liang 	vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_FIXED_COUNTERS_BITMASK,
537c7d7c76eSJinrong Liang 				supported_bitmask);
538c7d7c76eSJinrong Liang 	vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_NR_FIXED_COUNTERS,
539c7d7c76eSJinrong Liang 				nr_fixed_counters);
540c7d7c76eSJinrong Liang 
541c7d7c76eSJinrong Liang 	run_vcpu(vcpu);
542c7d7c76eSJinrong Liang 
543c7d7c76eSJinrong Liang 	kvm_vm_free(vm);
544c7d7c76eSJinrong Liang }
545c7d7c76eSJinrong Liang 
test_intel_counters(void)5464f1bd6b1SJinrong Liang static void test_intel_counters(void)
5474f1bd6b1SJinrong Liang {
5484f1bd6b1SJinrong Liang 	uint8_t nr_arch_events = kvm_cpu_property(X86_PROPERTY_PMU_EBX_BIT_VECTOR_LENGTH);
549c7d7c76eSJinrong Liang 	uint8_t nr_fixed_counters = kvm_cpu_property(X86_PROPERTY_PMU_NR_FIXED_COUNTERS);
5507137cf75SJinrong Liang 	uint8_t nr_gp_counters = kvm_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);
5514f1bd6b1SJinrong Liang 	uint8_t pmu_version = kvm_cpu_property(X86_PROPERTY_PMU_VERSION);
5524f1bd6b1SJinrong Liang 	unsigned int i;
5534f1bd6b1SJinrong Liang 	uint8_t v, j;
5544f1bd6b1SJinrong Liang 	uint32_t k;
5554f1bd6b1SJinrong Liang 
5564f1bd6b1SJinrong Liang 	const uint64_t perf_caps[] = {
5574f1bd6b1SJinrong Liang 		0,
5584f1bd6b1SJinrong Liang 		PMU_CAP_FW_WRITES,
5594f1bd6b1SJinrong Liang 	};
5604f1bd6b1SJinrong Liang 
5614f1bd6b1SJinrong Liang 	/*
5624f1bd6b1SJinrong Liang 	 * Test up to PMU v5, which is the current maximum version defined by
5634f1bd6b1SJinrong Liang 	 * Intel, i.e. is the last version that is guaranteed to be backwards
5644f1bd6b1SJinrong Liang 	 * compatible with KVM's existing behavior.
5654f1bd6b1SJinrong Liang 	 */
5664f1bd6b1SJinrong Liang 	uint8_t max_pmu_version = max_t(typeof(pmu_version), pmu_version, 5);
5674f1bd6b1SJinrong Liang 
5684f1bd6b1SJinrong Liang 	/*
5694f1bd6b1SJinrong Liang 	 * Detect the existence of events that aren't supported by selftests.
5704f1bd6b1SJinrong Liang 	 * This will (obviously) fail any time the kernel adds support for a
5714f1bd6b1SJinrong Liang 	 * new event, but it's worth paying that price to keep the test fresh.
5724f1bd6b1SJinrong Liang 	 */
5734f1bd6b1SJinrong Liang 	TEST_ASSERT(nr_arch_events <= NR_INTEL_ARCH_EVENTS,
5744f1bd6b1SJinrong Liang 		    "New architectural event(s) detected; please update this test (length = %u, mask = %x)",
5754f1bd6b1SJinrong Liang 		    nr_arch_events, kvm_cpu_property(X86_PROPERTY_PMU_EVENTS_MASK));
5764f1bd6b1SJinrong Liang 
5774f1bd6b1SJinrong Liang 	/*
5784f1bd6b1SJinrong Liang 	 * Force iterating over known arch events regardless of whether or not
5794f1bd6b1SJinrong Liang 	 * KVM/hardware supports a given event.
5804f1bd6b1SJinrong Liang 	 */
5814f1bd6b1SJinrong Liang 	nr_arch_events = max_t(typeof(nr_arch_events), nr_arch_events, NR_INTEL_ARCH_EVENTS);
5824f1bd6b1SJinrong Liang 
5834f1bd6b1SJinrong Liang 	for (v = 0; v <= max_pmu_version; v++) {
5844f1bd6b1SJinrong Liang 		for (i = 0; i < ARRAY_SIZE(perf_caps); i++) {
5854f1bd6b1SJinrong Liang 			if (!kvm_has_perf_caps && perf_caps[i])
5864f1bd6b1SJinrong Liang 				continue;
5874f1bd6b1SJinrong Liang 
5884f1bd6b1SJinrong Liang 			pr_info("Testing arch events, PMU version %u, perf_caps = %lx\n",
5894f1bd6b1SJinrong Liang 				v, perf_caps[i]);
5904f1bd6b1SJinrong Liang 			/*
5914f1bd6b1SJinrong Liang 			 * To keep the total runtime reasonable, test every
5924f1bd6b1SJinrong Liang 			 * possible non-zero, non-reserved bitmap combination
5934f1bd6b1SJinrong Liang 			 * only with the native PMU version and the full bit
5944f1bd6b1SJinrong Liang 			 * vector length.
5954f1bd6b1SJinrong Liang 			 */
5964f1bd6b1SJinrong Liang 			if (v == pmu_version) {
5974f1bd6b1SJinrong Liang 				for (k = 1; k < (BIT(nr_arch_events) - 1); k++)
5984f1bd6b1SJinrong Liang 					test_arch_events(v, perf_caps[i], nr_arch_events, k);
5994f1bd6b1SJinrong Liang 			}
6004f1bd6b1SJinrong Liang 			/*
6014f1bd6b1SJinrong Liang 			 * Test single bits for all PMU version and lengths up
6024f1bd6b1SJinrong Liang 			 * the number of events +1 (to verify KVM doesn't do
6034f1bd6b1SJinrong Liang 			 * weird things if the guest length is greater than the
6044f1bd6b1SJinrong Liang 			 * host length).  Explicitly test a mask of '0' and all
6054f1bd6b1SJinrong Liang 			 * ones i.e. all events being available and unavailable.
6064f1bd6b1SJinrong Liang 			 */
6074f1bd6b1SJinrong Liang 			for (j = 0; j <= nr_arch_events + 1; j++) {
6084f1bd6b1SJinrong Liang 				test_arch_events(v, perf_caps[i], j, 0);
6094f1bd6b1SJinrong Liang 				test_arch_events(v, perf_caps[i], j, 0xff);
6104f1bd6b1SJinrong Liang 
6114f1bd6b1SJinrong Liang 				for (k = 0; k < nr_arch_events; k++)
6124f1bd6b1SJinrong Liang 					test_arch_events(v, perf_caps[i], j, BIT(k));
6134f1bd6b1SJinrong Liang 			}
6147137cf75SJinrong Liang 
6157137cf75SJinrong Liang 			pr_info("Testing GP counters, PMU version %u, perf_caps = %lx\n",
6167137cf75SJinrong Liang 				v, perf_caps[i]);
6177137cf75SJinrong Liang 			for (j = 0; j <= nr_gp_counters; j++)
6187137cf75SJinrong Liang 				test_gp_counters(v, perf_caps[i], j);
619c7d7c76eSJinrong Liang 
620c7d7c76eSJinrong Liang 			pr_info("Testing fixed counters, PMU version %u, perf_caps = %lx\n",
621c7d7c76eSJinrong Liang 				v, perf_caps[i]);
622c7d7c76eSJinrong Liang 			for (j = 0; j <= nr_fixed_counters; j++) {
623c7d7c76eSJinrong Liang 				for (k = 0; k <= (BIT(nr_fixed_counters) - 1); k++)
624c7d7c76eSJinrong Liang 					test_fixed_counters(v, perf_caps[i], j, k);
625c7d7c76eSJinrong Liang 			}
6264f1bd6b1SJinrong Liang 		}
6274f1bd6b1SJinrong Liang 	}
6284f1bd6b1SJinrong Liang }
6294f1bd6b1SJinrong Liang 
main(int argc,char * argv[])6304f1bd6b1SJinrong Liang int main(int argc, char *argv[])
6314f1bd6b1SJinrong Liang {
632c85e9867SSean Christopherson 	TEST_REQUIRE(kvm_is_pmu_enabled());
6334f1bd6b1SJinrong Liang 
6344f1bd6b1SJinrong Liang 	TEST_REQUIRE(host_cpu_is_intel);
6354f1bd6b1SJinrong Liang 	TEST_REQUIRE(kvm_cpu_has_p(X86_PROPERTY_PMU_VERSION));
6364f1bd6b1SJinrong Liang 	TEST_REQUIRE(kvm_cpu_property(X86_PROPERTY_PMU_VERSION) > 0);
6374f1bd6b1SJinrong Liang 
6384f1bd6b1SJinrong Liang 	kvm_pmu_version = kvm_cpu_property(X86_PROPERTY_PMU_VERSION);
6394f1bd6b1SJinrong Liang 	kvm_has_perf_caps = kvm_cpu_has(X86_FEATURE_PDCM);
6404f1bd6b1SJinrong Liang 
6414f1bd6b1SJinrong Liang 	test_intel_counters();
6424f1bd6b1SJinrong Liang 
6434f1bd6b1SJinrong Liang 	return 0;
6444f1bd6b1SJinrong Liang }
645