tools/testing/selftests/kvm/x86/pmu_counters_test.c
Source file repositories/reference/linux-study-clean/tools/testing/selftests/kvm/x86/pmu_counters_test.c
File Facts
- System
- Linux kernel
- Corpus path
tools/testing/selftests/kvm/x86/pmu_counters_test.c- Extension
.c- Size
- 22341 bytes
- Lines
- 697
- Domain
- Support Tooling And Documentation
- Bucket
- tools
- Inferred role
- Support Tooling And Documentation: implementation source
- Status
- source implementation candidate
Why This File Exists
Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.
- Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
x86intrin.hpmu.hprocessor.h
Detected Declarations
struct kvm_intel_pmu_eventfunction pmu_is_null_featurefunction intel_event_to_featurefunction run_vcpufunction guest_get_pmu_versionfunction guest_assert_event_countfunction __volatile__function __guest_test_arch_eventfunction guest_test_arch_eventfunction guest_test_arch_eventsfunction test_arch_eventsfunction guest_test_rdpmcfunction guest_rd_wr_countersfunction guest_test_gp_countersfunction test_gp_countersfunction guest_test_fixed_countersfunction __volatile__function test_fixed_countersfunction test_intel_countersfunction main
Annotated Snippet
struct kvm_intel_pmu_event {
struct kvm_x86_pmu_feature gp_event;
struct kvm_x86_pmu_feature fixed_event;
};
/*
* Wrap the array to appease the compiler, as the macros used to construct each
* kvm_x86_pmu_feature use syntax that's only valid in function scope, and the
* compiler often thinks the feature definitions aren't compile-time constants.
*/
static struct kvm_intel_pmu_event intel_event_to_feature(u8 idx)
{
const struct kvm_intel_pmu_event __intel_event_to_feature[] = {
[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, X86_PMU_FEATURE_INSNS_RETIRED_FIXED },
/*
* Note, the fixed counter for reference cycles is NOT the same as the
* general purpose architectural event. The fixed counter explicitly
* counts at the same frequency as the TSC, whereas the GP event counts
* at a fixed, but uarch specific, frequency. 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 },
[INTEL_ARCH_TOPDOWN_BE_BOUND_INDEX] = { X86_PMU_FEATURE_TOPDOWN_BE_BOUND, X86_PMU_FEATURE_NULL },
[INTEL_ARCH_TOPDOWN_BAD_SPEC_INDEX] = { X86_PMU_FEATURE_TOPDOWN_BAD_SPEC, X86_PMU_FEATURE_NULL },
[INTEL_ARCH_TOPDOWN_FE_BOUND_INDEX] = { X86_PMU_FEATURE_TOPDOWN_FE_BOUND, X86_PMU_FEATURE_NULL },
[INTEL_ARCH_TOPDOWN_RETIRING_INDEX] = { X86_PMU_FEATURE_TOPDOWN_RETIRING, X86_PMU_FEATURE_NULL },
[INTEL_ARCH_LBR_INSERTS_INDEX] = { X86_PMU_FEATURE_LBR_INSERTS, X86_PMU_FEATURE_NULL },
};
kvm_static_assert(ARRAY_SIZE(__intel_event_to_feature) == NR_INTEL_ARCH_EVENTS);
return __intel_event_to_feature[idx];
}
static struct kvm_vm *pmu_vm_create_with_one_vcpu(struct kvm_vcpu **vcpu,
void *guest_code,
u8 pmu_version,
u64 perf_capabilities)
{
struct kvm_vm *vm;
vm = vm_create_with_one_vcpu(vcpu, guest_code);
sync_global_to_guest(vm, kvm_pmu_version);
sync_global_to_guest(vm, hardware_pmu_arch_events);
/*
* Set PERF_CAPABILITIES before PMU version as KVM disallows enabling
* features via PERF_CAPABILITIES if the guest doesn't have a vPMU.
*/
if (kvm_has_perf_caps)
vcpu_set_msr(*vcpu, MSR_IA32_PERF_CAPABILITIES, perf_capabilities);
vcpu_set_cpuid_property(*vcpu, X86_PROPERTY_PMU_VERSION, pmu_version);
return vm;
}
static void run_vcpu(struct kvm_vcpu *vcpu)
{
struct ucall uc;
do {
vcpu_run(vcpu);
switch (get_ucall(vcpu, &uc)) {
case UCALL_SYNC:
break;
case UCALL_ABORT:
REPORT_GUEST_ASSERT(uc);
break;
case UCALL_PRINTF:
pr_info("%s", uc.buffer);
break;
case UCALL_DONE:
break;
default:
TEST_FAIL("Unexpected ucall: %lu", uc.cmd);
}
} while (uc.cmd != UCALL_DONE);
}
static u8 guest_get_pmu_version(void)
{
/*
* Return the effective PMU version, i.e. the minimum between what KVM
* supports and what is enumerated to the guest. The host deliberately
Annotation
- Immediate include surface: `x86intrin.h`, `pmu.h`, `processor.h`.
- Detected declarations: `struct kvm_intel_pmu_event`, `function pmu_is_null_feature`, `function intel_event_to_feature`, `function run_vcpu`, `function guest_get_pmu_version`, `function guest_assert_event_count`, `function __volatile__`, `function __guest_test_arch_event`, `function guest_test_arch_event`, `function guest_test_arch_events`.
- Atlas domain: Support Tooling And Documentation / tools.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.