1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Test for VMX-pmu perf capability msr
4  *
5  * Copyright (C) 2021 Intel Corporation
6  *
7  * Test to check the effect of various CPUID settings on
8  * MSR_IA32_PERF_CAPABILITIES MSR, and check that what
9  * we write with KVM_SET_MSR is _not_ modified by the guest
10  * and check it can be retrieved with KVM_GET_MSR, also test
11  * the invalid LBR formats are rejected.
12  */
13 
14 #define _GNU_SOURCE /* for program_invocation_short_name */
15 #include <sys/ioctl.h>
16 
17 #include "kvm_util.h"
18 #include "vmx.h"
19 
20 #define PMU_CAP_FW_WRITES	(1ULL << 13)
21 #define PMU_CAP_LBR_FMT		0x3f
22 
23 union perf_capabilities {
24 	struct {
25 		u64	lbr_format:6;
26 		u64	pebs_trap:1;
27 		u64	pebs_arch_reg:1;
28 		u64	pebs_format:4;
29 		u64	smm_freeze:1;
30 		u64	full_width_write:1;
31 		u64 pebs_baseline:1;
32 		u64	perf_metrics:1;
33 		u64	pebs_output_pt_available:1;
34 		u64	anythread_deprecated:1;
35 	};
36 	u64	capabilities;
37 };
38 
39 static void guest_code(void)
40 {
41 	wrmsr(MSR_IA32_PERF_CAPABILITIES, PMU_CAP_LBR_FMT);
42 }
43 
44 int main(int argc, char *argv[])
45 {
46 	struct kvm_vm *vm;
47 	struct kvm_vcpu *vcpu;
48 	int ret;
49 	union perf_capabilities host_cap;
50 	uint64_t val;
51 
52 	host_cap.capabilities = kvm_get_feature_msr(MSR_IA32_PERF_CAPABILITIES);
53 	host_cap.capabilities &= (PMU_CAP_FW_WRITES | PMU_CAP_LBR_FMT);
54 
55 	/* Create VM */
56 	vm = vm_create_with_one_vcpu(&vcpu, guest_code);
57 
58 	TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_PDCM));
59 
60 	TEST_REQUIRE(kvm_cpu_has_p(X86_PROPERTY_PMU_VERSION));
61 	TEST_REQUIRE(kvm_cpu_property(X86_PROPERTY_PMU_VERSION) > 0);
62 
63 	/* testcase 1, set capabilities when we have PDCM bit */
64 	vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, PMU_CAP_FW_WRITES);
65 
66 	/* check capabilities can be retrieved with KVM_GET_MSR */
67 	ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_PERF_CAPABILITIES), PMU_CAP_FW_WRITES);
68 
69 	/* check whatever we write with KVM_SET_MSR is _not_ modified */
70 	vcpu_run(vcpu);
71 	ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_PERF_CAPABILITIES), PMU_CAP_FW_WRITES);
72 
73 	/* testcase 2, check valid LBR formats are accepted */
74 	vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, 0);
75 	ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_PERF_CAPABILITIES), 0);
76 
77 	vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, host_cap.lbr_format);
78 	ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_PERF_CAPABILITIES), (u64)host_cap.lbr_format);
79 
80 	/*
81 	 * Testcase 3, check that an "invalid" LBR format is rejected.  Only an
82 	 * exact match of the host's format (and 0/disabled) is allowed.
83 	 */
84 	for (val = 1; val <= PMU_CAP_LBR_FMT; val++) {
85 		if (val == (host_cap.capabilities & PMU_CAP_LBR_FMT))
86 			continue;
87 
88 		ret = _vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, val);
89 		TEST_ASSERT(!ret, "Bad LBR FMT = 0x%lx didn't fail", val);
90 	}
91 
92 	printf("Completed perf capability tests.\n");
93 	kvm_vm_free(vm);
94 }
95