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 VCPU_ID 0
21
22 #define X86_FEATURE_PDCM (1<<15)
23 #define PMU_CAP_FW_WRITES (1ULL << 13)
24 #define PMU_CAP_LBR_FMT 0x3f
25
26 union cpuid10_eax {
27 struct {
28 unsigned int version_id:8;
29 unsigned int num_counters:8;
30 unsigned int bit_width:8;
31 unsigned int mask_length:8;
32 } split;
33 unsigned int full;
34 };
35
36 union perf_capabilities {
37 struct {
38 u64 lbr_format:6;
39 u64 pebs_trap:1;
40 u64 pebs_arch_reg:1;
41 u64 pebs_format:4;
42 u64 smm_freeze:1;
43 u64 full_width_write:1;
44 u64 pebs_baseline:1;
45 u64 perf_metrics:1;
46 u64 pebs_output_pt_available:1;
47 u64 anythread_deprecated:1;
48 };
49 u64 capabilities;
50 };
51
guest_code(void)52 static void guest_code(void)
53 {
54 wrmsr(MSR_IA32_PERF_CAPABILITIES, PMU_CAP_LBR_FMT);
55 }
56
main(int argc,char * argv[])57 int main(int argc, char *argv[])
58 {
59 struct kvm_cpuid2 *cpuid;
60 struct kvm_cpuid_entry2 *entry_1_0;
61 struct kvm_cpuid_entry2 *entry_a_0;
62 bool pdcm_supported = false;
63 struct kvm_vm *vm;
64 int ret;
65 union cpuid10_eax eax;
66 union perf_capabilities host_cap;
67
68 host_cap.capabilities = kvm_get_feature_msr(MSR_IA32_PERF_CAPABILITIES);
69 host_cap.capabilities &= (PMU_CAP_FW_WRITES | PMU_CAP_LBR_FMT);
70
71 /* Create VM */
72 vm = vm_create_default(VCPU_ID, 0, guest_code);
73 cpuid = kvm_get_supported_cpuid();
74
75 if (kvm_get_cpuid_max_basic() >= 0xa) {
76 entry_1_0 = kvm_get_supported_cpuid_index(1, 0);
77 entry_a_0 = kvm_get_supported_cpuid_index(0xa, 0);
78 pdcm_supported = entry_1_0 && !!(entry_1_0->ecx & X86_FEATURE_PDCM);
79 eax.full = entry_a_0->eax;
80 }
81 if (!pdcm_supported) {
82 print_skip("MSR_IA32_PERF_CAPABILITIES is not supported by the vCPU");
83 exit(KSFT_SKIP);
84 }
85 if (!eax.split.version_id) {
86 print_skip("PMU is not supported by the vCPU");
87 exit(KSFT_SKIP);
88 }
89
90 /* testcase 1, set capabilities when we have PDCM bit */
91 vcpu_set_cpuid(vm, VCPU_ID, cpuid);
92 vcpu_set_msr(vm, 0, MSR_IA32_PERF_CAPABILITIES, PMU_CAP_FW_WRITES);
93
94 /* check capabilities can be retrieved with KVM_GET_MSR */
95 ASSERT_EQ(vcpu_get_msr(vm, VCPU_ID, MSR_IA32_PERF_CAPABILITIES), PMU_CAP_FW_WRITES);
96
97 /* check whatever we write with KVM_SET_MSR is _not_ modified */
98 vcpu_run(vm, VCPU_ID);
99 ASSERT_EQ(vcpu_get_msr(vm, VCPU_ID, MSR_IA32_PERF_CAPABILITIES), PMU_CAP_FW_WRITES);
100
101 /* testcase 2, check valid LBR formats are accepted */
102 vcpu_set_msr(vm, 0, MSR_IA32_PERF_CAPABILITIES, 0);
103 ASSERT_EQ(vcpu_get_msr(vm, VCPU_ID, MSR_IA32_PERF_CAPABILITIES), 0);
104
105 vcpu_set_msr(vm, 0, MSR_IA32_PERF_CAPABILITIES, host_cap.lbr_format);
106 ASSERT_EQ(vcpu_get_msr(vm, VCPU_ID, MSR_IA32_PERF_CAPABILITIES), (u64)host_cap.lbr_format);
107
108 /* testcase 3, check invalid LBR format is rejected */
109 /* Note, on Arch LBR capable platforms, LBR_FMT in perf capability msr is 0x3f,
110 * to avoid the failure, use a true invalid format 0x30 for the test. */
111 ret = _vcpu_set_msr(vm, 0, MSR_IA32_PERF_CAPABILITIES, 0x30);
112 TEST_ASSERT(ret == 0, "Bad PERF_CAPABILITIES didn't fail.");
113
114 printf("Completed perf capability tests.\n");
115 kvm_vm_free(vm);
116 }
117