spnego: add missing OID to oid registry
[sfrench/cifs-2.6.git] / tools / testing / selftests / kvm / x86_64 / vmx_pmu_caps_test.c
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 <linux/bitmap.h>
18
19 #include "kvm_util.h"
20 #include "vmx.h"
21
22 union perf_capabilities {
23         struct {
24                 u64     lbr_format:6;
25                 u64     pebs_trap:1;
26                 u64     pebs_arch_reg:1;
27                 u64     pebs_format:4;
28                 u64     smm_freeze:1;
29                 u64     full_width_write:1;
30                 u64 pebs_baseline:1;
31                 u64     perf_metrics:1;
32                 u64     pebs_output_pt_available:1;
33                 u64     anythread_deprecated:1;
34         };
35         u64     capabilities;
36 };
37
38 /*
39  * The LBR format and most PEBS features are immutable, all other features are
40  * fungible (if supported by the host and KVM).
41  */
42 static const union perf_capabilities immutable_caps = {
43         .lbr_format = -1,
44         .pebs_trap  = 1,
45         .pebs_arch_reg = 1,
46         .pebs_format = -1,
47         .pebs_baseline = 1,
48 };
49
50 static const union perf_capabilities format_caps = {
51         .lbr_format = -1,
52         .pebs_format = -1,
53 };
54
55 static void guest_code(uint64_t current_val)
56 {
57         uint8_t vector;
58         int i;
59
60         vector = wrmsr_safe(MSR_IA32_PERF_CAPABILITIES, current_val);
61         GUEST_ASSERT_2(vector == GP_VECTOR, current_val, vector);
62
63         vector = wrmsr_safe(MSR_IA32_PERF_CAPABILITIES, 0);
64         GUEST_ASSERT_2(vector == GP_VECTOR, 0, vector);
65
66         for (i = 0; i < 64; i++) {
67                 vector = wrmsr_safe(MSR_IA32_PERF_CAPABILITIES,
68                                     current_val ^ BIT_ULL(i));
69                 GUEST_ASSERT_2(vector == GP_VECTOR,
70                                current_val ^ BIT_ULL(i), vector);
71         }
72
73         GUEST_DONE();
74 }
75
76 /*
77  * Verify that guest WRMSRs to PERF_CAPABILITIES #GP regardless of the value
78  * written, that the guest always sees the userspace controlled value, and that
79  * PERF_CAPABILITIES is immutable after KVM_RUN.
80  */
81 static void test_guest_wrmsr_perf_capabilities(union perf_capabilities host_cap)
82 {
83         struct kvm_vcpu *vcpu;
84         struct kvm_vm *vm = vm_create_with_one_vcpu(&vcpu, guest_code);
85         struct ucall uc;
86         int r, i;
87
88         vm_init_descriptor_tables(vm);
89         vcpu_init_descriptor_tables(vcpu);
90
91         vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, host_cap.capabilities);
92
93         vcpu_args_set(vcpu, 1, host_cap.capabilities);
94         vcpu_run(vcpu);
95
96         switch (get_ucall(vcpu, &uc)) {
97         case UCALL_ABORT:
98                 REPORT_GUEST_ASSERT_2(uc, "val = 0x%lx, vector = %lu");
99                 break;
100         case UCALL_DONE:
101                 break;
102         default:
103                 TEST_FAIL("Unexpected ucall: %lu", uc.cmd);
104         }
105
106         ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_PERF_CAPABILITIES), host_cap.capabilities);
107
108         vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, host_cap.capabilities);
109
110         r = _vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, 0);
111         TEST_ASSERT(!r, "Post-KVM_RUN write '0' didn't fail");
112
113         for (i = 0; i < 64; i++) {
114                 r = _vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES,
115                                   host_cap.capabilities ^ BIT_ULL(i));
116                 TEST_ASSERT(!r, "Post-KVM_RUN write '0x%llx'didn't fail",
117                             host_cap.capabilities ^ BIT_ULL(i));
118         }
119
120         kvm_vm_free(vm);
121 }
122
123 /*
124  * Verify KVM allows writing PERF_CAPABILITIES with all KVM-supported features
125  * enabled, as well as '0' (to disable all features).
126  */
127 static void test_basic_perf_capabilities(union perf_capabilities host_cap)
128 {
129         struct kvm_vcpu *vcpu;
130         struct kvm_vm *vm = vm_create_with_one_vcpu(&vcpu, NULL);
131
132         vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, 0);
133         vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, host_cap.capabilities);
134
135         kvm_vm_free(vm);
136 }
137
138 static void test_fungible_perf_capabilities(union perf_capabilities host_cap)
139 {
140         const uint64_t fungible_caps = host_cap.capabilities & ~immutable_caps.capabilities;
141
142         struct kvm_vcpu *vcpu;
143         struct kvm_vm *vm = vm_create_with_one_vcpu(&vcpu, NULL);
144         int bit;
145
146         for_each_set_bit(bit, &fungible_caps, 64) {
147                 vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, BIT_ULL(bit));
148                 vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES,
149                              host_cap.capabilities & ~BIT_ULL(bit));
150         }
151         vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, host_cap.capabilities);
152
153         kvm_vm_free(vm);
154 }
155
156 /*
157  * Verify KVM rejects attempts to set unsupported and/or immutable features in
158  * PERF_CAPABILITIES.  Note, LBR format and PEBS format need to be validated
159  * separately as they are multi-bit values, e.g. toggling or setting a single
160  * bit can generate a false positive without dedicated safeguards.
161  */
162 static void test_immutable_perf_capabilities(union perf_capabilities host_cap)
163 {
164         const uint64_t reserved_caps = (~host_cap.capabilities |
165                                         immutable_caps.capabilities) &
166                                        ~format_caps.capabilities;
167
168         struct kvm_vcpu *vcpu;
169         struct kvm_vm *vm = vm_create_with_one_vcpu(&vcpu, NULL);
170         union perf_capabilities val = host_cap;
171         int r, bit;
172
173         for_each_set_bit(bit, &reserved_caps, 64) {
174                 r = _vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES,
175                                   host_cap.capabilities ^ BIT_ULL(bit));
176                 TEST_ASSERT(!r, "%s immutable feature 0x%llx (bit %d) didn't fail",
177                             host_cap.capabilities & BIT_ULL(bit) ? "Setting" : "Clearing",
178                             BIT_ULL(bit), bit);
179         }
180
181         /*
182          * KVM only supports the host's native LBR format, as well as '0' (to
183          * disable LBR support).  Verify KVM rejects all other LBR formats.
184          */
185         for (val.lbr_format = 1; val.lbr_format; val.lbr_format++) {
186                 if (val.lbr_format == host_cap.lbr_format)
187                         continue;
188
189                 r = _vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, val.capabilities);
190                 TEST_ASSERT(!r, "Bad LBR FMT = 0x%x didn't fail, host = 0x%x",
191                             val.lbr_format, host_cap.lbr_format);
192         }
193
194         /* Ditto for the PEBS format. */
195         for (val.pebs_format = 1; val.pebs_format; val.pebs_format++) {
196                 if (val.pebs_format == host_cap.pebs_format)
197                         continue;
198
199                 r = _vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, val.capabilities);
200                 TEST_ASSERT(!r, "Bad PEBS FMT = 0x%x didn't fail, host = 0x%x",
201                             val.pebs_format, host_cap.pebs_format);
202         }
203
204         kvm_vm_free(vm);
205 }
206
207 /*
208  * Test that LBR MSRs are writable when LBRs are enabled, and then verify that
209  * disabling the vPMU via CPUID also disables LBR support.  Set bits 2:0 of
210  * LBR_TOS as those bits are writable across all uarch implementations (arch
211  * LBRs will need to poke a different MSR).
212  */
213 static void test_lbr_perf_capabilities(union perf_capabilities host_cap)
214 {
215         struct kvm_vcpu *vcpu;
216         struct kvm_vm *vm;
217         int r;
218
219         if (!host_cap.lbr_format)
220                 return;
221
222         vm = vm_create_with_one_vcpu(&vcpu, NULL);
223
224         vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, host_cap.capabilities);
225         vcpu_set_msr(vcpu, MSR_LBR_TOS, 7);
226
227         vcpu_clear_cpuid_entry(vcpu, X86_PROPERTY_PMU_VERSION.function);
228
229         r = _vcpu_set_msr(vcpu, MSR_LBR_TOS, 7);
230         TEST_ASSERT(!r, "Writing LBR_TOS should fail after disabling vPMU");
231
232         kvm_vm_free(vm);
233 }
234
235 int main(int argc, char *argv[])
236 {
237         union perf_capabilities host_cap;
238
239         TEST_REQUIRE(get_kvm_param_bool("enable_pmu"));
240         TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_PDCM));
241
242         TEST_REQUIRE(kvm_cpu_has_p(X86_PROPERTY_PMU_VERSION));
243         TEST_REQUIRE(kvm_cpu_property(X86_PROPERTY_PMU_VERSION) > 0);
244
245         host_cap.capabilities = kvm_get_feature_msr(MSR_IA32_PERF_CAPABILITIES);
246
247         TEST_ASSERT(host_cap.full_width_write,
248                     "Full-width writes should always be supported");
249
250         test_basic_perf_capabilities(host_cap);
251         test_fungible_perf_capabilities(host_cap);
252         test_immutable_perf_capabilities(host_cap);
253         test_guest_wrmsr_perf_capabilities(host_cap);
254         test_lbr_perf_capabilities(host_cap);
255 }