Path: blob/master/tools/testing/selftests/kvm/x86/pmu_counters_test.c
38245 views
// SPDX-License-Identifier: GPL-2.01/*2* Copyright (C) 2023, Tencent, Inc.3*/4#include <x86intrin.h>56#include "pmu.h"7#include "processor.h"89/* Number of iterations of the loop for the guest measurement payload. */10#define NUM_LOOPS 101112/* Each iteration of the loop retires one branch instruction. */13#define NUM_BRANCH_INSNS_RETIRED (NUM_LOOPS)1415/*16* Number of instructions in each loop. 1 ENTER, 1 CLFLUSH/CLFLUSHOPT/NOP,17* 1 MFENCE, 1 MOV, 1 LEAVE, 1 LOOP.18*/19#define NUM_INSNS_PER_LOOP 62021/*22* Number of "extra" instructions that will be counted, i.e. the number of23* instructions that are needed to set up the loop and then disable the24* counter. 2 MOV, 2 XOR, 1 WRMSR.25*/26#define NUM_EXTRA_INSNS 52728/* Total number of instructions retired within the measured section. */29#define NUM_INSNS_RETIRED (NUM_LOOPS * NUM_INSNS_PER_LOOP + NUM_EXTRA_INSNS)3031/* Track which architectural events are supported by hardware. */32static uint32_t hardware_pmu_arch_events;3334static uint8_t kvm_pmu_version;35static bool kvm_has_perf_caps;3637#define X86_PMU_FEATURE_NULL \38({ \39struct kvm_x86_pmu_feature feature = {}; \40\41feature; \42})4344static bool pmu_is_null_feature(struct kvm_x86_pmu_feature event)45{46return !(*(u64 *)&event);47}4849struct kvm_intel_pmu_event {50struct kvm_x86_pmu_feature gp_event;51struct kvm_x86_pmu_feature fixed_event;52};5354/*55* Wrap the array to appease the compiler, as the macros used to construct each56* kvm_x86_pmu_feature use syntax that's only valid in function scope, and the57* compiler often thinks the feature definitions aren't compile-time constants.58*/59static struct kvm_intel_pmu_event intel_event_to_feature(uint8_t idx)60{61const struct kvm_intel_pmu_event __intel_event_to_feature[] = {62[INTEL_ARCH_CPU_CYCLES_INDEX] = { X86_PMU_FEATURE_CPU_CYCLES, X86_PMU_FEATURE_CPU_CYCLES_FIXED },63[INTEL_ARCH_INSTRUCTIONS_RETIRED_INDEX] = { X86_PMU_FEATURE_INSNS_RETIRED, X86_PMU_FEATURE_INSNS_RETIRED_FIXED },64/*65* Note, the fixed counter for reference cycles is NOT the same as the66* general purpose architectural event. The fixed counter explicitly67* counts at the same frequency as the TSC, whereas the GP event counts68* at a fixed, but uarch specific, frequency. Bundle them here for69* simplicity.70*/71[INTEL_ARCH_REFERENCE_CYCLES_INDEX] = { X86_PMU_FEATURE_REFERENCE_CYCLES, X86_PMU_FEATURE_REFERENCE_TSC_CYCLES_FIXED },72[INTEL_ARCH_LLC_REFERENCES_INDEX] = { X86_PMU_FEATURE_LLC_REFERENCES, X86_PMU_FEATURE_NULL },73[INTEL_ARCH_LLC_MISSES_INDEX] = { X86_PMU_FEATURE_LLC_MISSES, X86_PMU_FEATURE_NULL },74[INTEL_ARCH_BRANCHES_RETIRED_INDEX] = { X86_PMU_FEATURE_BRANCH_INSNS_RETIRED, X86_PMU_FEATURE_NULL },75[INTEL_ARCH_BRANCHES_MISPREDICTED_INDEX] = { X86_PMU_FEATURE_BRANCHES_MISPREDICTED, X86_PMU_FEATURE_NULL },76[INTEL_ARCH_TOPDOWN_SLOTS_INDEX] = { X86_PMU_FEATURE_TOPDOWN_SLOTS, X86_PMU_FEATURE_TOPDOWN_SLOTS_FIXED },77[INTEL_ARCH_TOPDOWN_BE_BOUND_INDEX] = { X86_PMU_FEATURE_TOPDOWN_BE_BOUND, X86_PMU_FEATURE_NULL },78[INTEL_ARCH_TOPDOWN_BAD_SPEC_INDEX] = { X86_PMU_FEATURE_TOPDOWN_BAD_SPEC, X86_PMU_FEATURE_NULL },79[INTEL_ARCH_TOPDOWN_FE_BOUND_INDEX] = { X86_PMU_FEATURE_TOPDOWN_FE_BOUND, X86_PMU_FEATURE_NULL },80[INTEL_ARCH_TOPDOWN_RETIRING_INDEX] = { X86_PMU_FEATURE_TOPDOWN_RETIRING, X86_PMU_FEATURE_NULL },81[INTEL_ARCH_LBR_INSERTS_INDEX] = { X86_PMU_FEATURE_LBR_INSERTS, X86_PMU_FEATURE_NULL },82};8384kvm_static_assert(ARRAY_SIZE(__intel_event_to_feature) == NR_INTEL_ARCH_EVENTS);8586return __intel_event_to_feature[idx];87}8889static struct kvm_vm *pmu_vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,90void *guest_code,91uint8_t pmu_version,92uint64_t perf_capabilities)93{94struct kvm_vm *vm;9596vm = vm_create_with_one_vcpu(vcpu, guest_code);97sync_global_to_guest(vm, kvm_pmu_version);98sync_global_to_guest(vm, hardware_pmu_arch_events);99100/*101* Set PERF_CAPABILITIES before PMU version as KVM disallows enabling102* features via PERF_CAPABILITIES if the guest doesn't have a vPMU.103*/104if (kvm_has_perf_caps)105vcpu_set_msr(*vcpu, MSR_IA32_PERF_CAPABILITIES, perf_capabilities);106107vcpu_set_cpuid_property(*vcpu, X86_PROPERTY_PMU_VERSION, pmu_version);108return vm;109}110111static void run_vcpu(struct kvm_vcpu *vcpu)112{113struct ucall uc;114115do {116vcpu_run(vcpu);117switch (get_ucall(vcpu, &uc)) {118case UCALL_SYNC:119break;120case UCALL_ABORT:121REPORT_GUEST_ASSERT(uc);122break;123case UCALL_PRINTF:124pr_info("%s", uc.buffer);125break;126case UCALL_DONE:127break;128default:129TEST_FAIL("Unexpected ucall: %lu", uc.cmd);130}131} while (uc.cmd != UCALL_DONE);132}133134static uint8_t guest_get_pmu_version(void)135{136/*137* Return the effective PMU version, i.e. the minimum between what KVM138* supports and what is enumerated to the guest. The host deliberately139* advertises a PMU version to the guest beyond what is actually140* supported by KVM to verify KVM doesn't freak out and do something141* bizarre with an architecturally valid, but unsupported, version.142*/143return min_t(uint8_t, kvm_pmu_version, this_cpu_property(X86_PROPERTY_PMU_VERSION));144}145146/*147* If an architectural event is supported and guaranteed to generate at least148* one "hit, assert that its count is non-zero. If an event isn't supported or149* the test can't guarantee the associated action will occur, then all bets are150* off regarding the count, i.e. no checks can be done.151*152* Sanity check that in all cases, the event doesn't count when it's disabled,153* and that KVM correctly emulates the write of an arbitrary value.154*/155static void guest_assert_event_count(uint8_t idx, uint32_t pmc, uint32_t pmc_msr)156{157uint64_t count;158159count = _rdpmc(pmc);160if (!(hardware_pmu_arch_events & BIT(idx)))161goto sanity_checks;162163switch (idx) {164case INTEL_ARCH_INSTRUCTIONS_RETIRED_INDEX:165/* Relax precise count check due to VM-EXIT/VM-ENTRY overcount issue */166if (this_pmu_has_errata(INSTRUCTIONS_RETIRED_OVERCOUNT))167GUEST_ASSERT(count >= NUM_INSNS_RETIRED);168else169GUEST_ASSERT_EQ(count, NUM_INSNS_RETIRED);170break;171case INTEL_ARCH_BRANCHES_RETIRED_INDEX:172/* Relax precise count check due to VM-EXIT/VM-ENTRY overcount issue */173if (this_pmu_has_errata(BRANCHES_RETIRED_OVERCOUNT))174GUEST_ASSERT(count >= NUM_BRANCH_INSNS_RETIRED);175else176GUEST_ASSERT_EQ(count, NUM_BRANCH_INSNS_RETIRED);177break;178case INTEL_ARCH_LLC_REFERENCES_INDEX:179case INTEL_ARCH_LLC_MISSES_INDEX:180if (!this_cpu_has(X86_FEATURE_CLFLUSHOPT) &&181!this_cpu_has(X86_FEATURE_CLFLUSH))182break;183fallthrough;184case INTEL_ARCH_CPU_CYCLES_INDEX:185case INTEL_ARCH_REFERENCE_CYCLES_INDEX:186case INTEL_ARCH_TOPDOWN_BE_BOUND_INDEX:187case INTEL_ARCH_TOPDOWN_FE_BOUND_INDEX:188GUEST_ASSERT_NE(count, 0);189break;190case INTEL_ARCH_TOPDOWN_SLOTS_INDEX:191case INTEL_ARCH_TOPDOWN_RETIRING_INDEX:192__GUEST_ASSERT(count >= NUM_INSNS_RETIRED,193"Expected top-down slots >= %u, got count = %lu",194NUM_INSNS_RETIRED, count);195break;196default:197break;198}199200sanity_checks:201__asm__ __volatile__("loop ." : "+c"((int){NUM_LOOPS}));202GUEST_ASSERT_EQ(_rdpmc(pmc), count);203204wrmsr(pmc_msr, 0xdead);205GUEST_ASSERT_EQ(_rdpmc(pmc), 0xdead);206}207208/*209* Enable and disable the PMC in a monolithic asm blob to ensure that the210* compiler can't insert _any_ code into the measured sequence. Note, ECX211* doesn't need to be clobbered as the input value, @pmc_msr, is restored212* before the end of the sequence.213*214* If CLFUSH{,OPT} is supported, flush the cacheline containing (at least) the215* CLFUSH{,OPT} instruction on each loop iteration to force LLC references and216* misses, i.e. to allow testing that those events actually count.217*218* If forced emulation is enabled (and specified), force emulation on a subset219* of the measured code to verify that KVM correctly emulates instructions and220* branches retired events in conjunction with hardware also counting said221* events.222*/223#define GUEST_MEASURE_EVENT(_msr, _value, clflush, FEP) \224do { \225__asm__ __volatile__("wrmsr\n\t" \226" mov $" __stringify(NUM_LOOPS) ", %%ecx\n\t" \227"1:\n\t" \228FEP "enter $0, $0\n\t" \229clflush "\n\t" \230"mfence\n\t" \231"mov %[m], %%eax\n\t" \232FEP "leave\n\t" \233FEP "loop 1b\n\t" \234FEP "mov %%edi, %%ecx\n\t" \235FEP "xor %%eax, %%eax\n\t" \236FEP "xor %%edx, %%edx\n\t" \237"wrmsr\n\t" \238:: "a"((uint32_t)_value), "d"(_value >> 32), \239"c"(_msr), "D"(_msr), [m]"m"(kvm_pmu_version) \240); \241} while (0)242243#define GUEST_TEST_EVENT(_idx, _pmc, _pmc_msr, _ctrl_msr, _value, FEP) \244do { \245wrmsr(_pmc_msr, 0); \246\247if (this_cpu_has(X86_FEATURE_CLFLUSHOPT)) \248GUEST_MEASURE_EVENT(_ctrl_msr, _value, "clflushopt %[m]", FEP); \249else if (this_cpu_has(X86_FEATURE_CLFLUSH)) \250GUEST_MEASURE_EVENT(_ctrl_msr, _value, "clflush %[m]", FEP); \251else \252GUEST_MEASURE_EVENT(_ctrl_msr, _value, "nop", FEP); \253\254guest_assert_event_count(_idx, _pmc, _pmc_msr); \255} while (0)256257static void __guest_test_arch_event(uint8_t idx, uint32_t pmc, uint32_t pmc_msr,258uint32_t ctrl_msr, uint64_t ctrl_msr_value)259{260GUEST_TEST_EVENT(idx, pmc, pmc_msr, ctrl_msr, ctrl_msr_value, "");261262if (is_forced_emulation_enabled)263GUEST_TEST_EVENT(idx, pmc, pmc_msr, ctrl_msr, ctrl_msr_value, KVM_FEP);264}265266static void guest_test_arch_event(uint8_t idx)267{268uint32_t nr_gp_counters = this_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);269uint32_t pmu_version = guest_get_pmu_version();270/* PERF_GLOBAL_CTRL exists only for Architectural PMU Version 2+. */271bool guest_has_perf_global_ctrl = pmu_version >= 2;272struct kvm_x86_pmu_feature gp_event, fixed_event;273uint32_t base_pmc_msr;274unsigned int i;275276/* The host side shouldn't invoke this without a guest PMU. */277GUEST_ASSERT(pmu_version);278279if (this_cpu_has(X86_FEATURE_PDCM) &&280rdmsr(MSR_IA32_PERF_CAPABILITIES) & PMU_CAP_FW_WRITES)281base_pmc_msr = MSR_IA32_PMC0;282else283base_pmc_msr = MSR_IA32_PERFCTR0;284285gp_event = intel_event_to_feature(idx).gp_event;286GUEST_ASSERT_EQ(idx, gp_event.f.bit);287288GUEST_ASSERT(nr_gp_counters);289290for (i = 0; i < nr_gp_counters; i++) {291uint64_t eventsel = ARCH_PERFMON_EVENTSEL_OS |292ARCH_PERFMON_EVENTSEL_ENABLE |293intel_pmu_arch_events[idx];294295wrmsr(MSR_P6_EVNTSEL0 + i, 0);296if (guest_has_perf_global_ctrl)297wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, BIT_ULL(i));298299__guest_test_arch_event(idx, i, base_pmc_msr + i,300MSR_P6_EVNTSEL0 + i, eventsel);301}302303if (!guest_has_perf_global_ctrl)304return;305306fixed_event = intel_event_to_feature(idx).fixed_event;307if (pmu_is_null_feature(fixed_event) || !this_pmu_has(fixed_event))308return;309310i = fixed_event.f.bit;311312wrmsr(MSR_CORE_PERF_FIXED_CTR_CTRL, FIXED_PMC_CTRL(i, FIXED_PMC_KERNEL));313314__guest_test_arch_event(idx, i | INTEL_RDPMC_FIXED,315MSR_CORE_PERF_FIXED_CTR0 + i,316MSR_CORE_PERF_GLOBAL_CTRL,317FIXED_PMC_GLOBAL_CTRL_ENABLE(i));318}319320static void guest_test_arch_events(void)321{322uint8_t i;323324for (i = 0; i < NR_INTEL_ARCH_EVENTS; i++)325guest_test_arch_event(i);326327GUEST_DONE();328}329330static void test_arch_events(uint8_t pmu_version, uint64_t perf_capabilities,331uint8_t length, uint32_t unavailable_mask)332{333struct kvm_vcpu *vcpu;334struct kvm_vm *vm;335336/* Testing arch events requires a vPMU (there are no negative tests). */337if (!pmu_version)338return;339340unavailable_mask &= GENMASK(X86_PROPERTY_PMU_EVENTS_MASK.hi_bit,341X86_PROPERTY_PMU_EVENTS_MASK.lo_bit);342343vm = pmu_vm_create_with_one_vcpu(&vcpu, guest_test_arch_events,344pmu_version, perf_capabilities);345346vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_EBX_BIT_VECTOR_LENGTH,347length);348vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_EVENTS_MASK,349unavailable_mask);350351run_vcpu(vcpu);352353kvm_vm_free(vm);354}355356/*357* Limit testing to MSRs that are actually defined by Intel (in the SDM). MSRs358* that aren't defined counter MSRs *probably* don't exist, but there's no359* guarantee that currently undefined MSR indices won't be used for something360* other than PMCs in the future.361*/362#define MAX_NR_GP_COUNTERS 8363#define MAX_NR_FIXED_COUNTERS 3364365#define GUEST_ASSERT_PMC_MSR_ACCESS(insn, msr, expect_gp, vector) \366__GUEST_ASSERT(expect_gp ? vector == GP_VECTOR : !vector, \367"Expected %s on " #insn "(0x%x), got %s", \368expect_gp ? "#GP" : "no fault", msr, ex_str(vector)) \369370#define GUEST_ASSERT_PMC_VALUE(insn, msr, val, expected) \371__GUEST_ASSERT(val == expected, \372"Expected " #insn "(0x%x) to yield 0x%lx, got 0x%lx", \373msr, expected, val);374375static void guest_test_rdpmc(uint32_t rdpmc_idx, bool expect_success,376uint64_t expected_val)377{378uint8_t vector;379uint64_t val;380381vector = rdpmc_safe(rdpmc_idx, &val);382GUEST_ASSERT_PMC_MSR_ACCESS(RDPMC, rdpmc_idx, !expect_success, vector);383if (expect_success)384GUEST_ASSERT_PMC_VALUE(RDPMC, rdpmc_idx, val, expected_val);385386if (!is_forced_emulation_enabled)387return;388389vector = rdpmc_safe_fep(rdpmc_idx, &val);390GUEST_ASSERT_PMC_MSR_ACCESS(RDPMC, rdpmc_idx, !expect_success, vector);391if (expect_success)392GUEST_ASSERT_PMC_VALUE(RDPMC, rdpmc_idx, val, expected_val);393}394395static void guest_rd_wr_counters(uint32_t base_msr, uint8_t nr_possible_counters,396uint8_t nr_counters, uint32_t or_mask)397{398const bool pmu_has_fast_mode = !guest_get_pmu_version();399uint8_t i;400401for (i = 0; i < nr_possible_counters; i++) {402/*403* TODO: Test a value that validates full-width writes and the404* width of the counters.405*/406const uint64_t test_val = 0xffff;407const uint32_t msr = base_msr + i;408409/*410* Fixed counters are supported if the counter is less than the411* number of enumerated contiguous counters *or* the counter is412* explicitly enumerated in the supported counters mask.413*/414const bool expect_success = i < nr_counters || (or_mask & BIT(i));415416/*417* KVM drops writes to MSR_P6_PERFCTR[0|1] if the counters are418* unsupported, i.e. doesn't #GP and reads back '0'.419*/420const uint64_t expected_val = expect_success ? test_val : 0;421const bool expect_gp = !expect_success && msr != MSR_P6_PERFCTR0 &&422msr != MSR_P6_PERFCTR1;423uint32_t rdpmc_idx;424uint8_t vector;425uint64_t val;426427vector = wrmsr_safe(msr, test_val);428GUEST_ASSERT_PMC_MSR_ACCESS(WRMSR, msr, expect_gp, vector);429430vector = rdmsr_safe(msr, &val);431GUEST_ASSERT_PMC_MSR_ACCESS(RDMSR, msr, expect_gp, vector);432433/* On #GP, the result of RDMSR is undefined. */434if (!expect_gp)435GUEST_ASSERT_PMC_VALUE(RDMSR, msr, val, expected_val);436437/*438* Redo the read tests with RDPMC, which has different indexing439* semantics and additional capabilities.440*/441rdpmc_idx = i;442if (base_msr == MSR_CORE_PERF_FIXED_CTR0)443rdpmc_idx |= INTEL_RDPMC_FIXED;444445guest_test_rdpmc(rdpmc_idx, expect_success, expected_val);446447/*448* KVM doesn't support non-architectural PMUs, i.e. it should449* impossible to have fast mode RDPMC. Verify that attempting450* to use fast RDPMC always #GPs.451*/452GUEST_ASSERT(!expect_success || !pmu_has_fast_mode);453rdpmc_idx |= INTEL_RDPMC_FAST;454guest_test_rdpmc(rdpmc_idx, false, -1ull);455456vector = wrmsr_safe(msr, 0);457GUEST_ASSERT_PMC_MSR_ACCESS(WRMSR, msr, expect_gp, vector);458}459}460461static void guest_test_gp_counters(void)462{463uint8_t pmu_version = guest_get_pmu_version();464uint8_t nr_gp_counters = 0;465uint32_t base_msr;466467if (pmu_version)468nr_gp_counters = this_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);469470/*471* For v2+ PMUs, PERF_GLOBAL_CTRL's architectural post-RESET value is472* "Sets bits n-1:0 and clears the upper bits", where 'n' is the number473* of GP counters. If there are no GP counters, require KVM to leave474* PERF_GLOBAL_CTRL '0'. This edge case isn't covered by the SDM, but475* follow the spirit of the architecture and only globally enable GP476* counters, of which there are none.477*/478if (pmu_version > 1) {479uint64_t global_ctrl = rdmsr(MSR_CORE_PERF_GLOBAL_CTRL);480481if (nr_gp_counters)482GUEST_ASSERT_EQ(global_ctrl, GENMASK_ULL(nr_gp_counters - 1, 0));483else484GUEST_ASSERT_EQ(global_ctrl, 0);485}486487if (this_cpu_has(X86_FEATURE_PDCM) &&488rdmsr(MSR_IA32_PERF_CAPABILITIES) & PMU_CAP_FW_WRITES)489base_msr = MSR_IA32_PMC0;490else491base_msr = MSR_IA32_PERFCTR0;492493guest_rd_wr_counters(base_msr, MAX_NR_GP_COUNTERS, nr_gp_counters, 0);494GUEST_DONE();495}496497static void test_gp_counters(uint8_t pmu_version, uint64_t perf_capabilities,498uint8_t nr_gp_counters)499{500struct kvm_vcpu *vcpu;501struct kvm_vm *vm;502503vm = pmu_vm_create_with_one_vcpu(&vcpu, guest_test_gp_counters,504pmu_version, perf_capabilities);505506vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_NR_GP_COUNTERS,507nr_gp_counters);508509run_vcpu(vcpu);510511kvm_vm_free(vm);512}513514static void guest_test_fixed_counters(void)515{516uint64_t supported_bitmask = 0;517uint8_t nr_fixed_counters = 0;518uint8_t i;519520/* Fixed counters require Architectural vPMU Version 2+. */521if (guest_get_pmu_version() >= 2)522nr_fixed_counters = this_cpu_property(X86_PROPERTY_PMU_NR_FIXED_COUNTERS);523524/*525* The supported bitmask for fixed counters was introduced in PMU526* version 5.527*/528if (guest_get_pmu_version() >= 5)529supported_bitmask = this_cpu_property(X86_PROPERTY_PMU_FIXED_COUNTERS_BITMASK);530531guest_rd_wr_counters(MSR_CORE_PERF_FIXED_CTR0, MAX_NR_FIXED_COUNTERS,532nr_fixed_counters, supported_bitmask);533534for (i = 0; i < MAX_NR_FIXED_COUNTERS; i++) {535uint8_t vector;536uint64_t val;537538if (i >= nr_fixed_counters && !(supported_bitmask & BIT_ULL(i))) {539vector = wrmsr_safe(MSR_CORE_PERF_FIXED_CTR_CTRL,540FIXED_PMC_CTRL(i, FIXED_PMC_KERNEL));541__GUEST_ASSERT(vector == GP_VECTOR,542"Expected #GP for counter %u in FIXED_CTR_CTRL", i);543544vector = wrmsr_safe(MSR_CORE_PERF_GLOBAL_CTRL,545FIXED_PMC_GLOBAL_CTRL_ENABLE(i));546__GUEST_ASSERT(vector == GP_VECTOR,547"Expected #GP for counter %u in PERF_GLOBAL_CTRL", i);548continue;549}550551wrmsr(MSR_CORE_PERF_FIXED_CTR0 + i, 0);552wrmsr(MSR_CORE_PERF_FIXED_CTR_CTRL, FIXED_PMC_CTRL(i, FIXED_PMC_KERNEL));553wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, FIXED_PMC_GLOBAL_CTRL_ENABLE(i));554__asm__ __volatile__("loop ." : "+c"((int){NUM_LOOPS}));555wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0);556val = rdmsr(MSR_CORE_PERF_FIXED_CTR0 + i);557558GUEST_ASSERT_NE(val, 0);559}560GUEST_DONE();561}562563static void test_fixed_counters(uint8_t pmu_version, uint64_t perf_capabilities,564uint8_t nr_fixed_counters,565uint32_t supported_bitmask)566{567struct kvm_vcpu *vcpu;568struct kvm_vm *vm;569570vm = pmu_vm_create_with_one_vcpu(&vcpu, guest_test_fixed_counters,571pmu_version, perf_capabilities);572573vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_FIXED_COUNTERS_BITMASK,574supported_bitmask);575vcpu_set_cpuid_property(vcpu, X86_PROPERTY_PMU_NR_FIXED_COUNTERS,576nr_fixed_counters);577578run_vcpu(vcpu);579580kvm_vm_free(vm);581}582583static void test_intel_counters(void)584{585uint8_t nr_fixed_counters = kvm_cpu_property(X86_PROPERTY_PMU_NR_FIXED_COUNTERS);586uint8_t nr_gp_counters = kvm_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);587uint8_t pmu_version = kvm_cpu_property(X86_PROPERTY_PMU_VERSION);588unsigned int i;589uint8_t v, j;590uint32_t k;591592const uint64_t perf_caps[] = {5930,594PMU_CAP_FW_WRITES,595};596597/*598* To keep the total runtime reasonable, test only a handful of select,599* semi-arbitrary values for the mask of unavailable PMU events. Test600* 0 (all events available) and all ones (no events available) as well601* as alternating bit sequencues, e.g. to detect if KVM is checking the602* wrong bit(s).603*/604const uint32_t unavailable_masks[] = {6050x0,6060xffffffffu,6070xaaaaaaaau,6080x55555555u,6090xf0f0f0f0u,6100x0f0f0f0fu,6110xa0a0a0a0u,6120x0a0a0a0au,6130x50505050u,6140x05050505u,615};616617/*618* Test up to PMU v5, which is the current maximum version defined by619* Intel, i.e. is the last version that is guaranteed to be backwards620* compatible with KVM's existing behavior.621*/622uint8_t max_pmu_version = max_t(typeof(pmu_version), pmu_version, 5);623624/*625* Detect the existence of events that aren't supported by selftests.626* This will (obviously) fail any time hardware adds support for a new627* event, but it's worth paying that price to keep the test fresh.628*/629TEST_ASSERT(this_cpu_property(X86_PROPERTY_PMU_EBX_BIT_VECTOR_LENGTH) <= NR_INTEL_ARCH_EVENTS,630"New architectural event(s) detected; please update this test (length = %u, mask = %x)",631this_cpu_property(X86_PROPERTY_PMU_EBX_BIT_VECTOR_LENGTH),632this_cpu_property(X86_PROPERTY_PMU_EVENTS_MASK));633634/*635* Iterate over known arch events irrespective of KVM/hardware support636* to verify that KVM doesn't reject programming of events just because637* the *architectural* encoding is unsupported. Track which events are638* supported in hardware; the guest side will validate supported events639* count correctly, even if *enumeration* of the event is unsupported640* by KVM and/or isn't exposed to the guest.641*/642for (i = 0; i < NR_INTEL_ARCH_EVENTS; i++) {643if (this_pmu_has(intel_event_to_feature(i).gp_event))644hardware_pmu_arch_events |= BIT(i);645}646647for (v = 0; v <= max_pmu_version; v++) {648for (i = 0; i < ARRAY_SIZE(perf_caps); i++) {649if (!kvm_has_perf_caps && perf_caps[i])650continue;651652pr_info("Testing arch events, PMU version %u, perf_caps = %lx\n",653v, perf_caps[i]);654655/*656* Test single bits for all PMU version and lengths up657* the number of events +1 (to verify KVM doesn't do658* weird things if the guest length is greater than the659* host length). Explicitly test a mask of '0' and all660* ones i.e. all events being available and unavailable.661*/662for (j = 0; j <= NR_INTEL_ARCH_EVENTS + 1; j++) {663for (k = 1; k < ARRAY_SIZE(unavailable_masks); k++)664test_arch_events(v, perf_caps[i], j, unavailable_masks[k]);665}666667pr_info("Testing GP counters, PMU version %u, perf_caps = %lx\n",668v, perf_caps[i]);669for (j = 0; j <= nr_gp_counters; j++)670test_gp_counters(v, perf_caps[i], j);671672pr_info("Testing fixed counters, PMU version %u, perf_caps = %lx\n",673v, perf_caps[i]);674for (j = 0; j <= nr_fixed_counters; j++) {675for (k = 0; k <= (BIT(nr_fixed_counters) - 1); k++)676test_fixed_counters(v, perf_caps[i], j, k);677}678}679}680}681682int main(int argc, char *argv[])683{684TEST_REQUIRE(kvm_is_pmu_enabled());685686TEST_REQUIRE(host_cpu_is_intel);687TEST_REQUIRE(kvm_cpu_has_p(X86_PROPERTY_PMU_VERSION));688TEST_REQUIRE(kvm_cpu_property(X86_PROPERTY_PMU_VERSION) > 0);689690kvm_pmu_version = kvm_cpu_property(X86_PROPERTY_PMU_VERSION);691kvm_has_perf_caps = kvm_cpu_has(X86_FEATURE_PDCM);692693test_intel_counters();694695return 0;696}697698699