tools/testing/selftests/kvm/x86/pmu_event_filter_test.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/kvm/x86/pmu_event_filter_test.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/kvm/x86/pmu_event_filter_test.c
Extension
.c
Size
24345 bytes
Lines
886
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct __kvm_pmu_event_filter {
	__u32 action;
	__u32 nevents;
	__u32 fixed_counter_bitmap;
	__u32 flags;
	__u32 pad[4];
	__u64 events[KVM_PMU_EVENT_FILTER_MAX_EVENTS];
};

/*
 * This event list comprises Intel's known architectural events, plus AMD's
 * Branch Instructions Retired for Zen CPUs.  Note, AMD and Intel use the
 * same encoding for Instructions Retired.
 */
kvm_static_assert(INTEL_ARCH_INSTRUCTIONS_RETIRED == AMD_ZEN_INSTRUCTIONS_RETIRED);

static const struct __kvm_pmu_event_filter base_event_filter = {
	.nevents = ARRAY_SIZE(base_event_filter.events),
	.events = {
		INTEL_ARCH_CPU_CYCLES,
		INTEL_ARCH_INSTRUCTIONS_RETIRED,
		INTEL_ARCH_REFERENCE_CYCLES,
		INTEL_ARCH_LLC_REFERENCES,
		INTEL_ARCH_LLC_MISSES,
		INTEL_ARCH_BRANCHES_RETIRED,
		INTEL_ARCH_BRANCHES_MISPREDICTED,
		INTEL_ARCH_TOPDOWN_SLOTS,
		AMD_ZEN_BRANCHES_RETIRED,
	},
};

struct {
	u64 loads;
	u64 stores;
	u64 loads_stores;
	u64 branches_retired;
	u64 instructions_retired;
} pmc_results;

/*
 * If we encounter a #GP during the guest PMU sanity check, then the guest
 * PMU is not functional. Inform the hypervisor via GUEST_SYNC(0).
 */
static void guest_gp_handler(struct ex_regs *regs)
{
	GUEST_SYNC(-EFAULT);
}

/*
 * Check that we can write a new value to the given MSR and read it back.
 * The caller should provide a non-empty set of bits that are safe to flip.
 *
 * Return on success. GUEST_SYNC(0) on error.
 */
static void check_msr(u32 msr, u64 bits_to_flip)
{
	u64 v = rdmsr(msr) ^ bits_to_flip;

	wrmsr(msr, v);
	if (rdmsr(msr) != v)
		GUEST_SYNC(-EIO);

	v ^= bits_to_flip;
	wrmsr(msr, v);
	if (rdmsr(msr) != v)
		GUEST_SYNC(-EIO);
}

static void run_and_measure_loop(u32 msr_base)
{
	const u64 branches_retired = rdmsr(msr_base + 0);
	const u64 insn_retired = rdmsr(msr_base + 1);

	__asm__ __volatile__("loop ." : "+c"((int){NUM_BRANCHES}));

	pmc_results.branches_retired = rdmsr(msr_base + 0) - branches_retired;
	pmc_results.instructions_retired = rdmsr(msr_base + 1) - insn_retired;
}

static void intel_guest_code(void)
{
	check_msr(MSR_CORE_PERF_GLOBAL_CTRL, 1);
	check_msr(MSR_P6_EVNTSEL0, 0xffff);
	check_msr(MSR_IA32_PMC0, 0xffff);
	GUEST_SYNC(0);

	for (;;) {
		wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0);
		wrmsr(MSR_P6_EVNTSEL0, ARCH_PERFMON_EVENTSEL_ENABLE |
		      ARCH_PERFMON_EVENTSEL_OS | INTEL_ARCH_BRANCHES_RETIRED);

Annotation

Implementation Notes